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.
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
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.