How to Move DMARC From p=none to p=reject Without Breaking Mail
A staged plan for moving DMARC from none to reject: pre-flight checks, reading aggregate reports, fixing unaligned senders, the pct ramp, sp= for subdomains, and what breaks.
How to Move DMARC From p=none to p=reject Without Breaking Mail
I’ve lost count of the teams who published p=none, ticked the compliance box, and kept getting spoofed, because none reports and blocks nothing. Here’s how to move DMARC from none to reject without breaking your own mail: get SPF and DKIM passing and aligned on every legitimate sender, read your aggregate reports for at least a couple of weeks until the unaligned rows are all spoofers or forwarders, step up to p=quarantine, ramp it, and only then publish p=reject. The DNS edits take five minutes. The work is everything before them.
This guide assumes you already know what alignment means. If you don’t, read SPF, DKIM, and DMARC explained first, then come back. Everything below is the operational part: what to check, how to read a report row, and what will go wrong.

What needs to be in place before you touch the policy?
Before changing p=, you need a valid SPF record under the 10-lookup limit, DKIM signing on every legitimate sender with your domain in the d= tag, a DMARC record with a working rua= address that has been collecting reports for at least a few weeks, and a written inventory of everyone who sends as your domain. Skip any of these and enforcement will block your own mail.
Google’s own rollout guide asks for SPF and DKIM to be live at least 48 hours before you publish DMARC, then a week at p=none. I’d double that week. The HR system that only mails on payday won’t show up in seven days of reports.
The pre-flight checklist:
- SPF resolves and stays under 10 DNS lookups. RFC 7208 caps evaluation at ten, and crossing it returns PermError, which DMARC treats as an SPF fail. Run the SPF record checker; at eight lookups you’re one new vendor away from breaking.
- DKIM signs with your domain, on every sender. A vendor signing with
d=vendor.compasses DKIM and fails DMARC alignment. Confirm each selector with the DKIM record checker. - The DMARC record parses and has a live RUA address. Check it with the DMARC record checker. Under RFC 7489, receivers “MUST NOT generate aggregate feedback reports” if
rua=is missing, so no address means no data. - A sender inventory, on paper. Marketing platform, transactional API, CRM, helpdesk, billing, HR, the office printer, the agency that sends “from” you. The reports will show you sources you forgot, and you need a list to compare against.
- Someone reading the reports. Aggregate reports arrive as gzipped XML, one per receiver per day. Nobody reads that by hand at volume, which is the reason DMARC monitoring parses RUA and RUF into a dashboard with alignment tracking.
How do you read aggregate reports to find unaligned legitimate mail?
Every row in an aggregate report is a source IP, a count, the SPF and DKIM results, and whether each aligned with your From: domain. Sort the rows into four buckets: aligned and passing, legitimate but unaligned, forwarded, and spoofed. Only the second bucket needs your attention before enforcement; the other three are either fine, tolerable, or exactly what reject is for.
| Bucket | What the row looks like | What it means | What to do |
|---|---|---|---|
| Aligned pass | SPF or DKIM pass, dmarc=pass, IP belongs to a known sender | Working as intended | Nothing |
| Legitimate, unaligned | DKIM passes with a vendor d=, or SPF passes on the vendor’s bounce domain, dmarc=fail, IP belongs to a known sender | Your vendor authenticates as itself, not you | Fix it (next section) before enforcing |
| Forwarded | SPF fails on an unfamiliar IP, DKIM passes and aligns, low volume, often a university, ISP, or Gmail range | Someone auto-forwards your mail | Usually nothing; DKIM carries it |
| Spoofed | Both fail, unfamiliar IP, sometimes high volume in bursts | Impersonation | Nothing to fix; this is what reject stops |
Two reading tips. First, look at the DKIM d= domain in every failing row before you look at the IP. If it’s your domain and the signature still failed, something modified the message in transit, which points to a mailing list or a security gateway. If it’s a vendor’s domain, that vendor is signing as itself and you have an alignment fix to make. Second, watch volume over time. A source that sends 40 messages every weekday is a system. A source that sends 12,000 on a Tuesday and vanishes is an attacker.
The bucketing is only as good as the sample. Receivers only have to send reports daily, so two weeks is about fourteen data points per receiver: enough to spot a weekly job, not a monthly one. That’s why the 30 days of history DMARC monitoring keeps by default matters more than it sounds.
How do you fix third-party senders that fail alignment?
A third party fails DMARC alignment when it authenticates as its own domain instead of yours. You have four fixes, in rough order of preference: give the vendor a DKIM key so it signs with your d=, set a custom Return-Path on your domain so SPF aligns, delegate a subdomain the vendor controls, or accept the failure and let the mail fail. Pick per vendor, not globally.
Relaxed alignment, the default, only requires the authenticated domain and the From: domain to share an organizational domain, so bounce.example.com aligns with example.com. That’s what makes the custom Return-Path work: the vendor still handles bounces, but the envelope domain is yours. Most large platforms support this as a CNAME setup. The dmarc.org FAQ lays out the same options: delegate a subdomain, hand the vendor a vendor-specific DKIM key you can revoke, or have them relay through your mail server.
Here’s the part vendors’ setup guides skip. DKIM alignment is the one you want, because it survives forwarding and SPF alignment doesn’t. If a platform offers “authenticate your domain” with only an SPF include, push for DKIM too. If a platform can’t do either, your honest options are to have them send from their own From: domain with a Reply-To back to you, or to move that stream to a subdomain you’ll enforce later. Don’t hold the whole apex at p=none for one stubborn vendor.
The tradeoff: every vendor you route through your own bounce domain now ties its sending behavior to your reputation. That’s the correct tradeoff, and it’s why the inventory matters.
Should you stop at quarantine before going to reject?
Yes. Quarantine is the stage where a mistake sends legitimate mail to a spam folder it can be pulled back from, instead of a 550 rejection the recipient never sees. Some practitioners argue you should skip it because major receivers already treat failing mail from none and quarantine domains similarly. I’d still take the recoverable failure over the unrecoverable one.
There’s a mechanical reason quarantine and reject are one continuum rather than two decisions. RFC 7489 section 6.6.4 says that when a message isn’t selected for reject because of the pct= sampling, the receiver “SHOULD treat the email as though the ‘quarantine’ policy applies.” So p=reject; pct=25 is quarantine for three quarters of failing mail and reject for the rest. Ramping reject is ramping quarantine with a harder edge on part of it.
Quarantine is also where the second wave of forgotten senders shows up. Once failing mail actually lands in spam, someone from finance notices a customer’s statements went to junk, and you learn about a sender no report row had made obvious. At reject, that feedback arrives as a support ticket after the mail is already gone. Hold at quarantine until you’ve gone a full billing cycle with nothing legitimate in the unaligned bucket.
How does the pct= ramp actually work in 2026?
The pct= tag asks receivers to apply your policy to only that percentage of failing messages. Under RFC 7489 the remainder falls back one level (unsampled reject becomes quarantine, unsampled quarantine becomes normal filtering), and reports always cover 100% of mail regardless. Receivers honor it inconsistently, and the 2026 DMARC revision removed it entirely, so treat it as a soft brake, not a precise throttle.
RFC 7489 section 6.3 defines pct as an integer from 0 to 100, default 100, and says it exists to “allow Domain Owners to enact a slow rollout enforcement.” The RFC also says pct “MUST NOT be applied to the DMARC-generated reports,” so you still see every source in aggregate data during a ramp. Full visibility, partial enforcement.
Google’s rollout page suggests starting quarantine at a small percentage (their example: 10% for a small organization, 1% for a large one), reviewing reports daily, and raising it until you reach 100%. A ramp that matches what most guides converge on:
v=DMARC1; p=none; rua=mailto:dmarc@example.com
v=DMARC1; p=quarantine; pct=10; rua=mailto:dmarc@example.com
v=DMARC1; p=quarantine; pct=50; rua=mailto:dmarc@example.com
v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com
v=DMARC1; p=reject; pct=25; rua=mailto:dmarc@example.com
v=DMARC1; p=reject; rua=mailto:dmarc@example.com
Hold each step at least a week, longer if your mail has monthly streams. If a legitimate sender starts failing, fix the sender rather than dropping back to none; you can lower pct while you troubleshoot without giving up the policy.
Now the 2026 caveat. In May 2026 the IETF published RFC 9989, which obsoletes RFC 7489 and has no pct tag. It adds t= instead: t=y asks receivers to treat the policy as one level below what’s published (reject behaves like quarantine, quarantine like none), and t=n, the default, applies it as written. Receivers had mostly honored only 0 and 100 anyway. Your existing record stays valid and unknown tags are ignored, but as receivers adopt RFC 9989 a pct=25 may be read as 100.
What I’d do today: keep pct for older receivers, add t=y when you first move to a stricter p=, and remove both at full enforcement. v=DMARC1; p=reject; t=y; pct=25; rua=... tells both generations of receiver the same thing: heading to reject, go easy for now.
What does sp= do for subdomains?
The sp= tag sets the policy for subdomains of the domain the record is published on. If it’s absent, RFC 7489 says the p= policy “MUST be applied for subdomains” too. That means a bare p=reject at your apex rejects unaligned mail from every subdomain you’ve never published a record for, whether you meant it or not.
This bites in two directions. The subdomain you forgot: notify.example.com sends from a ticketing tool, nobody set up DKIM for it, and the day you publish p=reject at the apex its mail bounces. And the subdomain nobody uses: secure-login.example.com is wide open while the apex sits at p=none, because a receiver walks up to your organizational record and finds none.
Stage them separately:
v=DMARC1; p=reject; sp=quarantine; rua=mailto:dmarc@example.com
That enforces the apex while subdomains sit one step behind, buying time to authenticate each sending subdomain or publish its own record. A subdomain’s own DMARC record always wins over the organizational record’s sp, so notify.example.com can sit at p=none while the apex is at reject.
RFC 9989 adds np=, a policy for subdomains that don’t exist in DNS at all. Under RFC 7489 a never-created subdomain falls under sp, and if that’s absent, p, so get sp= to reject as soon as your real subdomains are authenticated; it’s the only thing covering the fake ones. One more trap: sp only works on the organizational domain’s record. Publish it on mail.example.com and receivers ignore it.
What breaks when you enforce, and what can you do about it?
Three things break at enforcement: forwarding, mailing lists, and third-party senders you didn’t authenticate. Forwarding mostly survives if DKIM is intact. Mailing lists usually don’t, and that’s documented in an RFC, not a vendor blog. Third parties are the only category fully within your control, which is why the sections above spent so long on them.
| What breaks | Why | Who can fix it | What to do |
|---|---|---|---|
| Plain forwarding (alias, auto-forward) | The forwarder’s IP isn’t in your SPF, so SPF fails; DKIM survives if the message is untouched | You, by ensuring DKIM on every sender | Nothing extra once DKIM aligns everywhere |
| Mailing lists | Lists add subject tags and footers, which invalidates DKIM after SPF already failed | The list operator | Nothing you can do; modern list software rewrites From: to the list domain for DMARC-enforcing senders |
| Security gateways and re-encoders | Some gateways rewrite bodies or re-encode messages, breaking DKIM | The gateway owner | Check the DKIM d= on failing rows; if it’s yours and still failed, something modified the message |
| Third-party senders | Vendor authenticates as itself, not you | You, with the vendor | Custom Return-Path, vendor DKIM key, or subdomain delegation |
| Your own forgotten systems | Never added to SPF or DKIM | You | Inventory, then authenticate or move to a subdomain |
RFC 7960 is the document to read on the first two rows. On forwarders: if the forwarder keeps your original MailFrom, “SPF validation will fail unless the forwarder is an authorized part of the originator’s email sending infrastructure,” and if it substitutes its own domain, SPF may pass but alignment fails, so DKIM has to carry the message. On mailing lists: they “very commonly modify headers or message content in ways that will cause DKIM to fail,” and “any such modifications would invalidate a DKIM signature.” It also documents the mitigation most lists now use, rewriting From: to the list’s own domain when the author’s domain enforces.
So p=reject will change how your users’ posts appear on older lists, and on very old ones their posts may bounce. That’s the cost of enforcement, and it’s small next to the cost of being spoofed. I’d take it every time, but I’d tell whoever runs your community lists before flipping the record, not after.
Forwarding is the one that scares people and shouldn’t. “This email failed SPF but still delivered” is the classic ticket, and the answer is that DMARC passes on either aligned check. As long as DKIM is on every sender and the forwarder doesn’t touch the body, the forwarded copy passes. That’s why DKIM alignment matters more than SPF alignment on the road to reject.
Why reject is worth the trouble
Google and Yahoo have required a DMARC record from anyone sending 5,000 or more messages a day to their users since February 1, 2024, and both accept p=none as the minimum (Google, Yahoo). Microsoft followed for Outlook.com, Hotmail, and Live from May 5, 2025, also at p=none minimum, and later moved non-compliant high-volume mail from Junk to outright rejection (Microsoft). All three also want the From: domain aligned with SPF or DKIM.
None of those requirements make you go to reject. The providers set the floor, and the floor blocks nothing. Reject is the only policy under which a receiver refuses mail that impersonates you; Yahoo says as much in its own FAQ, and it’s what BIMI needs too. The tradeoff is the work in this guide and a few weeks of watching reports. Publish p=none, let the reports pile up for 30 days, then work the four buckets until only spoofers and forwarders are left. If you’d rather not read the XML yourself, DMARC monitoring does the parsing, tracks alignment per source, and walks the policy from none to quarantine to reject.
Frequently asked questions
How long does it take to move DMARC from p=none to p=reject?
Google’s rollout guide says one week at p=none is usually enough for the reports to cover every mail stream, but that’s the floor, not the plan. A domain with a handful of senders can reach reject in a month or two. One with dozens of SaaS tools, agencies, and legacy systems often takes a quarter or more, and most of that time is spent chasing vendors, not editing DNS.
Can I skip quarantine and go straight to p=reject?
You can, and some practitioners recommend it because several big receivers treat none and quarantine similarly. I don’t. Quarantine is the only stage where a mistake lands in a spam folder you can still recover from instead of a 550 bounce. Under RFC 7489 an unsampled reject falls back to quarantine anyway, so a pct ramp on reject is quarantine in disguise.
Does p=reject break email forwarding?
Plain forwarding usually survives. The forwarder’s IP fails SPF, but an intact DKIM signature with your domain in d= still aligns, and DMARC passes on either check. What breaks is mailing lists and anything that rewrites the body or subject, because that invalidates DKIM after SPF is already gone. Keep DKIM on every sender and forwarding is mostly a non-issue.
Is the pct tag still supported in 2026?
It still works at receivers that implement RFC 7489, but RFC 9989 (DMARCbis, published 2026) removed pct and added a t=y testing flag that steps the policy down one level. Receivers were never consistent about intermediate percentages anyway. Treat pct as a soft brake, not a precise throttle, and consider publishing both pct and t=y during the transition.
Do I need a separate DMARC record for each subdomain?
No. A record at the organizational domain covers every subdomain through the p tag unless you override it with sp=. That cuts both ways: a bare p=reject at the apex rejects unaligned mail from every subdomain, including the one your ticketing system sends from and nobody documented. Use sp= to stage subdomains separately.
Written by
Ryan Sullivan , Email Deliverability & Operations
Ryan has spent over a decade cleaning lists and protecting sender reputation for outbound teams and ESP marketers, and writes about the parts of email deliverability you usually learn the hard way.