Everyone knows a DMARC policy should end up at p=reject. Almost nobody gets there. The reason is simple, and it is not technical: the day you flip the switch, if you got it wrong, your ERP invoices stop reaching your customers — and nobody tells you. The mail does not bounce with a helpful message. It disappears.
That risk is real. It is also entirely avoidable, as long as you stop treating this as "publishing a DNS record" and start treating it as a migration.
Why p=none protects nothing
Worth restating, because the confusion is common. A p=none policy tells receiving servers: "report to me what you see in my name, but change nothing." It is observation mode. An attacker spoofing your domain while you sit at p=none will have their messages delivered normally — you simply get the report a few hours later.
p=quarantine asks receivers to treat failures as suspicious; p=reject asks them to refuse. Only the last one actually shuts the door.
What actually breaks, and why
In the migrations we run, legitimate mail that fails DMARC almost always falls into one of these buckets.
Third-party services sending in your name. Billing tool, recruitment platform, e-signature service, marketing mail router, ticketing system. Each was wired up one day by a different team, and nobody keeps the list. By a wide margin, this is the leading cause of failure.
Missing alignment. A message can pass SPF and still fail DMARC: DMARC requires the domain validated by SPF to match the one shown in the From: header. Many platforms send with their own envelope domain, which passes SPF technically without aligning you.
Forwarding. An address that forwards mail to another mailbox breaks SPF by construction — the relaying server is not in your record. DKIM survives forwarding, unless something in the middle modifies the message.
Mailing lists. Same mechanics, made worse by lists that rewrite the subject or append a footer: the DKIM signature dies with it.
The method, in order
1. Publish in observation mode, and actually wait
Publish p=none with an aggregate reporting address, and let it run. Two weeks is rarely enough: you need to cover at least one billing cycle, one marketing campaign, one payroll run. We plan for four to six weeks on a primary domain.
The goal of this phase is not to collect reports. It is to build the complete inventory of what sends in your name — including what you did not know about.
2. Sort the inventory into three piles
Every identified source goes into one of three:
| Pile | Decision | Typical example |
|---|---|---|
| Legitimate, align it | Configure SPF and DKIM at the provider | ERP, HR tool, marketing |
| Legitimate, retire it | Cut the source, migrate the use case | Old print server, forgotten script |
| Illegitimate | Do nothing — this is what p=reject will block | Phishing, spoofing |
That third pile is what justifies the whole exercise. On a reasonably well-known mid-market domain, it routinely runs to several thousand messages a month.
3. Align, without touching the policy
At each legitimate provider: enable DKIM signing with your own domain, and check that the envelope domain aligns. This is configuration work, provider by provider, and it is the longest part. It carries no risk: while the policy stays at p=none, nothing can be rejected.
Prefer DKIM over SPF wherever you can. DKIM survives forwarding, consumes no DNS lookup, and does not depend on the provider's IP addresses — which will change without warning you.
4. Move in stages, using a percentage
DMARC accepts a pct tag that applies the policy to only a fraction of traffic. That is your safety net:
v=DMARC1; p=quarantine; pct=25; rua=mailto:...
Our reference progression, one step a week, checking the reports in between:
p=quarantine; pct=25p=quarantine; pct=100p=reject; pct=25p=reject; pct=100
An incident at 25% shows up in the reports and gets fixed before it touches the other three quarters. That is the entire point.
5. Do not stop there
A domain at p=reject is not a solved domain. An acquisition, a new SaaS tool, a provider changing infrastructure: each of these can reintroduce an unaligned source. Without monitoring, you will find out the day a customer tells you they never received anything.
How long it really takes
On a primary domain with a dozen legitimate sources, expect six to ten weeks from the first record to p=reject; pct=100. Most of that time is deliberate waiting, not workload.
Across a fifty-domain estate — the reality for any group that acquires regularly — the work is not fifty times longer: most secondary domains send nothing at all and can go straight to p=reject with an empty SPF record. Those are in fact the urgent ones: a domain that never sends mail is the easiest spoofing target there is, because nobody is watching what leaves it.