Rolling out DMARC to p=reject without losing mail
Publishing p=reject on a domain whose senders are not fully authenticated will silently destroy legitimate mail. Done in stages, with reports read between each one, the risk is close to zero. The whole process takes about six weeks, most of it waiting.
Stage 1 — monitor, change nothing
Publish this at _dmarc.yourdomain and leave it alone:
v=DMARC1; p=none; rua=mailto:dmarc@yourdomain
This blocks nothing and cannot break anything. What it does is start the flow of aggregate reports — daily XML from every major receiver listing each IP that sent mail as you and whether it passed SPF and DKIM.
Stage 2 — read the reports for three to four weeks
The reports are XML and painful by hand; any DMARC report parser will do. What you are looking for is a complete list of sending sources. Expect surprises: invoicing tools, the recruiting platform, an old marketing account, a support desk nobody migrated.
Four weeks matters because monthly senders exist. A billing system that fires on the 1st will not appear in a two-week sample, and that is exactly the mail you cannot afford to lose.
Stage 3 — authenticate everything you found
For each source, either add its SPF include and enable its DKIM signing, or stop it sending as your domain. Watch the SPF lookup count as you go — adding four or five providers is often enough to blow the ten-lookup budget, and that breaks SPF for every sender at once.
Prefer DKIM where you have the choice. It survives forwarding, and it does not consume any of the SPF budget.
Stage 4 — quarantine, ramped
v=DMARC1; p=quarantine; pct=25; rua=mailto:dmarc@yourdomain
A quarter of failing mail goes to spam; the rest is untouched. Raise to 50, then 100 over two weeks, checking reports at each step. If a legitimate sender was missed, it shows up as spam complaints rather than lost mail — recoverable.
Stage 5 — reject
v=DMARC1; p=reject; sp=reject; rua=mailto:dmarc@yourdomain
Set sp=reject explicitly. Without it subdomains inherit p, which is usually what you want — but being explicit prevents a future edit to p from quietly weakening subdomain protection. If you never send from subdomains at all, add np=reject to cover ones that do not exist.
rua forever. It is not just a rollout tool — it is the only ongoing visibility you have into who is sending as your domain.