From p=none to p=reject Without Black-Holing Your Own Mail
The DMARC record change takes five minutes. Knowing it won't bounce your invoices, your CRM, and a decade-old cron job takes 4-8 weeks of reading rua reports. Here is the safe ramp, the way people who watch reject decisions land every day actually do it.
EvilMail TeamJuly 18, 202611 min read
An admin flips p=reject on a Friday afternoon because a scanner report told them to. By Monday, finance is asking why Xero payment notifications stopped arriving, a recruiter's Greenhouse mail is bouncing at Gmail, and a backup-report cron on a box nobody has logged into since 2019 is throwing 550 5.7.1 dmarc=fail. Nobody spoofed the domain that weekend. The domain owner did all the damage themselves.
That is the part the tooling vendors undersell: DMARC breaks your own mail far more often than it stops attackers. Your spoofers are few. Your legitimate senders are many, scattered across SaaS platforms, and mostly undocumented. The DNS record is a two-line change. Knowing that change is safe is the entire job — and it is a data problem, not a DNS problem.
What p=reject actually tells receivers to do
The DMARC policy is an instruction to the receiving mail server, not to yours. When Gmail accepts a message claiming to be from evilmail.pro, it looks up _dmarc.evilmail.pro, reads your policy, and decides what to do with mail that fails. Three values:
DMARC p=none to p=reject Migration Guide (Without Blocking Your Mail) — EvilMail Blog
`p=none` — monitor only. Deliver as normal, just send me reports. Nothing changes for the recipient.
`p=quarantine` — failing mail goes to the spam folder. Recoverable.
`p=reject` — the receiver refuses the message at SMTP time with a 550. There is no folder to fish it out of. It is gone, and the sender gets a bounce.
DMARC "passing" is where most mental models are wrong. It is not "SPF passed" or "DKIM passed." It is:
(SPF passed AND SPF is aligned) OR (DKIM passed AND DKIM is aligned).
Alignment is the concept people miss and the reason careful admins still get burned. SPF authenticates the return-path (the RFC5321.MailFrom / bounce address), not the From: header your recipient sees. A message can pass SPF cleanly on bounces.sendgrid.net and still DMARC-fail, because that return-path domain does not align with the evilmail.pro in the visible From:. DKIM aligns the d= value in the signature against the From: domain. With relaxed alignment (the default), mail.evilmail.pro aligns with an evilmail.proFrom:; with strict, it must match exactly.
Turn on reporting and actually read it
This is 80% of the work, and the part the scanner-badge crowd skips. Before you touch the policy, publish a monitoring record and route the reports somewhere you will actually parse:
`rua` — aggregate reports. Daily XML rollups, one per receiver, no message content, no PII. This is the gold: every source IP sending as you, how many messages, and whether each passed SPF-aligned, DKIM-aligned, or neither.
`ruf` — forensic/failure reports, per-message. fo=1 asks receivers to generate one if *any* mechanism fails, not only if all do. Be honest with yourself: Gmail and Microsoft stopped sending forensic reports years ago over privacy, and in 2026 ruf is largely dead and GDPR-fraught. Publish it, but do not build your process around data that will not arrive.
The raw XML is unreadable at any real volume — a busy domain gets dozens of reports a day. Feed it to a parser. Self-hosted, parsedmarc ingests the .xml/.gz attachments into Elasticsearch and you visualize in Grafana or Kibana. Do not want to run that stack? Postmark's DMARC service emails free weekly digests, and Dmarcian, Valimail, or URIports will do the aggregation hosted. Any of them beats grepping XML by hand.
If your rua mailbox is on a different domain than the one being reported on, that other domain needs an authorization record or the receiver silently drops the report:
dns
evilmail.pro._report._dmarc.aggregator.example. IN TXT "v=DMARC1"
Sit at p=none for 2 to 4 weeks minimum and build a source inventory: every IP and platform sending as evilmail.pro, and its alignment status. You will find senders you forgot existed. Everyone does.
Fix alignment at the source before you move the needle
Now you have a list. Work it. The goal for each legitimate source is at least one aligned pass — and where you have a choice, make it DKIM, because DKIM survives forwarding and mailing lists where SPF does not.
ESPs (SendGrid, Mailgun, Postmark, and the rest) — configure each to sign with a d= matching or subdomaining your From: domain, and publish that selector in DNS. Confirm it landed:
SPF alignment — set a custom return-path / bounce domain (a subdomain of evilmail.pro) at each ESP so the MAIL FROM aligns too. Belt and suspenders.
"Send on behalf" SaaS — some CRMs and helpdesks send from your From: but sign with *their own* d=. That will never align. Either use their CNAME-delegated DKIM (so the signature is under your domain) or accept it will fail and must be fixed or retired before reject.
Mailing lists (Mailman and friends) rewrite the From: header or mangle the body and break the DKIM body hash. Use an ARC-aware list or From: rewriting; do not expect the original signature to survive.
The silent killer: the SPF 10-lookup limit. RFC 7208 caps SPF at 10 DNS lookups. Chain a few include: statements — Google, a CRM, a marketing tool, a helpdesk — and you blow past it. The result is PermError, which is an SPF fail, which is a DMARC fail. Count your includes:
bash
dig +short TXT evilmail.pro | grep spf
The rule that governs everything after this point: never advance the policy while a real source still shows aligned-fail in your `rua` data. Reject nothing you cannot see.
The ramp: quarantine first, and pct done right
The common advice — "ease into reject" with p=reject; pct=10 — is false safety. pct= tells receivers what fraction of failing mail to apply the policy to, so p=reject; pct=10 does not reject 10% *less* harm; it randomly black-holes 10% of your still-broken mail while hiding the breakage in the other 90%. You have not de-risked anything — you have made the failure intermittent and harder to diagnose. (The DMARCbis work that succeeds RFC 7489 deprecates pct= for exactly this bluntness.)
The real ramp uses quarantine as the reversible staging ground and pct= only as a quarantine dial:
dns
# Weeks 4-5: quarantine a quarter of failing mail, but reject unused subdomains outright
_dmarc.evilmail.pro. 600 IN TXT "v=DMARC1; p=quarantine; pct=25; sp=reject; rua=mailto:[email protected]; fo=1"
# Weeks 6-8: full quarantine
_dmarc.evilmail.pro. 600 IN TXT "v=DMARC1; p=quarantine; pct=100; sp=reject; rua=mailto:[email protected]"
# Week 8+: reject (alignment stays relaxed so subdomain-signed senders keep passing)
_dmarc.evilmail.pro. 300 IN TXT "v=DMARC1; p=reject; sp=reject; rua=mailto:[email protected]"
Note sp=reject from the very first quarantine step. The subdomain policy governs *.evilmail.pro, and attackers love spoofing unused subdomains precisely because they are unauthenticated by default. You almost never send legitimate mail from random subdomains, so setting sp=reject early costs you nothing and shuts a favorite spoofing vector — while your organizational policy is still the gentle quarantine. It doubles as a honeypot: any sp=reject hits in your rua are almost pure attacker traffic.
A word on strict alignment (adkim=s; aspf=s): leave it off unless every source signs at the exact organizational domain. If you followed the advice above and let an ESP sign with a subdomain d=, strict alignment turns that aligned pass into a fail and black-holes the sender. Relaxed is the safe default and the one these records use.
Every one of those gates is conditioned on clean `rua` data, not on the calendar. If week 6 arrives and your payroll SaaS still shows aligned-fails, you do not advance. You fix payroll, or you retire it as a sender. The weeks in the diagram are a rough shape, not a schedule.
When it breaks in production: reading the bounce
Something will slip through — a source that only fires monthly, a contractor's tool you never inventoried. Here is what the failure looks like from the two receivers that matter. Gmail:
550-5.7.26 Unauthenticated email from evilmail.pro is not accepted due to
550-5.7.26 domain's DMARC policy. Please contact the administrator...
550 5.7.26 dmarc=fail ...
Microsoft:
550 5.7.509 Access denied, sending domain evilmail.pro does not pass DMARC verification
To triage, read the Authentication-Results: header of a captured message — it spells out the verdict and, crucially, the domain it judged:
There is the tell: spf=pass but dmarc=fail, because the SPF domain (bounces.othervendor.net) does not align with header.from=evilmail.pro, and DKIM did not save it. That is a real source you missed, not a spoofer.
Tell the two apart using the source IP in your rua reports. A failing IP that belongs to your ESP or office range is your own broken source — fix it. A failing IP from some random hosting AS in another country you have never sent from is a spoofer you *correctly* blocked; leave it dead. And do not panic over a handful of dmarc=fail lines from mailing-list or forwarding IPs — that is the expected SPF-breaks-on-forward noise, and if your DKIM is aligned the forwarded copies with intact signatures still pass anyway.
Rollback is one DNS TTL away. This is why the migration records keep TTL at 300-600 seconds — if a legitimate stream starts bouncing, drop p=reject back to p=quarantine (or p=none) and within ten minutes receivers stop rejecting. Hold that short TTL for the whole migration; raise it once you have been stable at reject for a month.
Checklist before you type p=reject
rua has been on and parsed for at least 2-4 weeks, and you have a complete source inventory.
Every legitimate sender shows an aligned pass (DKIM preferred) in recent rua data — zero aligned-fails from known sources.
Each ESP signs DKIM with a d= under your domain and publishes its selector (dig confirms it resolves).
Your SPF record is under the 10-lookup limit — no PermError.
"Send on behalf" SaaS is either CNAME-delegated for DKIM or removed as a sender.
sp=reject has been live and quiet through the quarantine phase.
Alignment stays relaxed unless you have verified every source signs at the exact domain.
DMARC TTL is 300-600s and you know the exact record to revert to.
rua stays on permanently — a bare p=reject with no reporting is flying blind, and new broken senders appear all the time.
You are doing this on a Tuesday morning, not a Friday afternoon.
At evilmail.pro we run temp-email and real mail infrastructure side by side, which means we watch inbound DMARC-fail decisions land against customer domains every single day — the spoof attempts and the self-inflicted ones look identical at the SMTP layer. The only difference is whether someone read the rua data first. Graduate a policy only when the reports say you can. Reject nothing you cannot see.