Enforcement — p=reject — is the point of DMARC. It is also where people get nervous, because a mistake means legitimate mail gets rejected. The fix is not courage; it is doing it in stages, driven by your aggregate reports.

Stage 0 — Monitor until it’s boring

Start at p=none and stay there until you can account for every source in your reports. The goal: no legitimate sender is failing alignment. Fix each one by adding it to SPF or enabling DKIM for it.

Don’t move on while a real sender still fails. That is the single most common way to break mail.

Stage 1 — Quarantine a slice

Once the reports are clean, move to quarantine — but only for a fraction of mail, using pct:

v=DMARC1; p=quarantine; pct=25; rua=mailto:dmarc@yourdomain.com

Roughly a quarter of failing messages now goes to spam. Note that pct samples per message, not per sender: every failing source gets about a quarter of its mail quarantined, rather than a quarter of your senders being affected and the rest untouched. That is why the symptom of an unfinished rollout is “some of our invoices arrive and some don’t” rather than one system breaking cleanly.

Watch the reports (and your support inbox) for a week or two. Seeing nothing unexpected? Raise pct toward 100.

Note

pct is on its way out of the specification

Receivers honour pct today, so this ramp works — but the current revision of the DMARC specification removes the tag, having found that values other than 0 and 100 were applied inconsistently between implementations. Its replacement is t=y (test: apply one level below the stated policy) and t=n (the default). Treat a pct ramp as a transitional technique rather than part of a record you intend to keep. The tag reference has both tags, and what changed in the new standard has the reasoning.

Stage 2 — Full quarantine, then reject

With pct=100; p=quarantine stable, switch to reject:

v=DMARC1; p=reject; rua=mailto:dmarc@yourdomain.com
Warning

Don’t ramp reject with pct. It does not do what the quarantine ramp did. Mail not selected by pct= is not exempted — it drops to the next weaker policy. So p=reject; pct=25 rejects about a quarter of failing mail and quarantines the other three quarters; none of it is delivered normally. The quarantine ramp works because the policy below quarantine is none; there is no such headroom under reject. If you want a gradual move to reject, ramp by scope instead — enforce on one subdomain at a time with sp=, or finish the quarantine stage properly and then switch in one step.

At p=reject, mail that fails DMARC is refused at the SMTP transaction. Note the scope of what that buys: it stops forgery of this exact domain at receivers that honour the policy. Receivers are permitted to override it, and it does nothing about lookalike domains (yourc0mpany.com) or display-name spoofing, neither of which is a DMARC failure for your domain at all.

Stage 3 — Keep watching

Enforcement is not “set and forget”. New sending tools appear, keys rotate, and providers change. Keep the reports flowing so a new failing source shows up as a blip rather than a support ticket — the whole point of publishing rua= in the first place.

One thing not to wait for: forwarding and mailing-list failures never reach zero. Plain forwarding breaks SPF and lists break DKIM, so a portion of your reports will always show aligned-fail rows for mail that is perfectly legitimate. “No failures at all” is therefore not an achievable exit criterion — the criterion is that every source you control authenticates. ARC is often raised as the answer here; it is worth knowing what it does and doesn’t buy before you postpone enforcement on the strength of it.

Once you are at p=reject and stable, there is one thing enforcement unlocks that is worth knowing about: BIMI puts your logo next to your mail in supporting inboxes, and full enforcement is its entry requirement — which is why a pct= or t=y still sitting in the record disqualifies you.

New here? Start by publishing your first DMARC record.