Introduction
p=reject is the destination of every serious DMARC rollout. It's the only DMARC policy that fully eliminates exact-domain spoofing — and the only one where the protection is meaningful enough to satisfy modern compliance and security expectations.
In one sentence: with p=reject published, mail that fails DMARC for your domain is bounced at the SMTP gate by every major mailbox provider, before it ever reaches a recipient's mailbox in any folder. This article explains exactly what that means, when to deploy it, and how to get there without breaking your own email.
Why this topic matters
Most DMARC mistakes happen at the boundary between p=quarantine and p=reject. Teams either get nervous and stop short, leaving themselves at half-protection, or rush the move and bounce a legitimate sender. Both outcomes are avoidable with a clear understanding of what p=reject actually does.
DMARC p=reject is also the policy that produces the demonstrable business outcome — "our domain is unspoofable" — that makes DMARC for MSPs sellable and DMARC for security teams worth budgeting. Getting there is the goal.
What p=reject actually does
When a receiver gets mail claiming to be from your domain at p=reject, the receiver:
- Runs the DMARC check (does SPF or DKIM pass AND align with the From header).
- If yes: deliver normally.
- If no: reject the message at SMTP with a 5xx error code.
The rejection happens at the SMTP gate — before the message is accepted. The sending server (legitimate or attacker) sees an immediate failure. The recipient never sees the message in any folder; it doesn't go to spam, it doesn't get quarantined, it isn't delivered late. It simply doesn't arrive.
For an attacker, this means exact-domain spoofing of your brand stops working at every major mailbox provider. The phishing email they crafted with [email protected] in the From header gets bounced before it reaches anyone.
For a legitimate sender that's misconfigured, the same thing happens — which is why getting to p=reject safely matters so much.
Why p=reject is the only fully-effective policy
The three DMARC policies trade off differently against attacker behaviour:
p=nonedoes nothing to the message. Attackers can still spoof at will.p=quarantinesends failing mail to spam. Sophisticated phishing campaigns sometimes succeed at quarantine because users do open spam looking for missing legitimate messages.p=rejectremoves the message entirely. The attack vector is closed.
For deliverability, the difference between quarantine and reject is invisible to legitimate senders (who pass DMARC) and substantial for attackers (whose messages don't reach the user at all). Why enforcement matters more than monitoring makes the case for moving past the half-measure.
For compliance, modern frameworks specifically reference p=reject as the goal. PCI DSS, NIST guidance, and most cyber-insurance underwriters give credit for full enforcement, not for monitoring.
When you're ready to move to p=reject
The single test: every legitimate sender in your aggregate reports is at ≥99% DMARC pass rate, has been for at least two consecutive weeks, and you have no unknown senders in the report.
That's it. There's no calendar test, no domain-age test, no volume test. The signal is the data. If you can't name every row in your sender report, you're not ready.
Before moving, run through this checklist:
- [ ] All SPF records published and under the 10-lookup limit.
- [ ] DKIM configured and signing for every sending platform.
- [ ] Alignment passing for every legitimate sender.
- [ ] Currently at
p=quarantine pct=100for at least 2 weeks. - [ ] Aggregate-report pass rate ≥99% for all known senders.
- [ ] No unidentified senders in the last 4 weeks of reports.
- [ ] Subdomain policy (
sp=) deliberately chosen.
If every box is checked, you're safe to move.
Step-by-step approach to deploying p=reject
- Pre-move audit. Re-confirm the checklist above using the most recent week of aggregate reports.
- Update the record. Change
p=quarantinetop=reject. Keep everything else the same. - Optional: stagger with
pct=. If you want a final controlled rollout, start atp=reject pct=25for a few days, then 50, then 100. Belt-and-braces for high-stakes domains. - Validate the published record. Confirm via DNS lookup that the new policy is live.
- Watch the reports closely for 7 days. Any new rejections will appear quickly. The day-1 report will tell you whether everything is still passing.
- Update
sp=if it lagged. If you'd been atsp=quarantinewhile the parent policy was atp=quarantine, move both up together.
A typical p=quarantine → p=reject move with the optional pct= stagger takes 5-10 days. Skipping pct= entirely is fine when the data is clean.
Best practices
- Don't pair
p=rejectwithpct=below 100 as a permanent state. That's a half-reject, which is no different from quarantine for the messages the policy isn't applied to. - Watch the first week's reports daily. Most surprises surface in days 1-3.
- Communicate the change internally. If marketing or sales teams use the domain heavily, give them a heads-up the day before. This avoids a panic call when they think a customer's mail is bouncing.
- Be ready to roll back to
p=quarantinefor 24 hours if needed. A surprise sender that's hard-bouncing might justify a temporary step-back while you remediate. - Verify the move was clean. A week after going to
p=reject, run a final audit — pass rate, sender coverage, no spike in rejections.
What can still go wrong at p=reject
Three failure modes to watch:
- A new sender appears, fails, and gets bounced. Marketing adds a tool, doesn't tell IT, the tool sends mail unauthenticated, recipients don't receive it. The fix is the runbook — DMARC monitoring includes "watch for new senders" as a steady-state job.
- A long-standing sender's configuration drifts. A SaaS vendor rotates DKIM keys, you missed the announcement, suddenly the signing breaks. Aggregate reports surface this on day 1.
- A forwarding service or mailing list rewrites the From header in a way that breaks DKIM. This is more common with academic and large enterprise mailing lists. Provider-specific mitigations exist.
For all three, the steady-state monitoring posture catches them quickly. The risk is not having that posture.
Recommended next step
If you're currently at p=quarantine pct=100 and your reports are clean, the next move is p=reject. Pick a date in the next 7-14 days, communicate internally, run the pre-move checklist, then change the record. The post-move steady state is the same monitoring you already have — just with the protection actually in place.
If you're not at p=quarantine pct=100 yet, the path from monitoring to enforcement lays out the steps.
FAQ
Can p=reject block legitimate mail?
Yes — if a legitimate sender is misconfigured. That's why the monitoring and quarantine phases exist: to find and fix every legitimate sender before enforcement is final. Done right, the move to p=reject is a non-event.
What happens to forwarded mail at p=reject?
It depends on the forwarding mechanism. Plain SMTP forwarding without rewriting usually breaks SPF but preserves DKIM, so DMARC can still pass via DKIM. Mailing-list forwarders that rewrite the From header preserve DKIM only if they re-sign with their own DKIM. Most modern forwarders handle this correctly; older ones don't.
Does p=reject affect transactional mail differently from marketing mail?
No. The receiver doesn't distinguish — every message gets the same DMARC check. If your transactional system is properly authenticated, it passes; if not, it fails. The policy is content-agnostic.
Is p=reject permanent?
You can change the policy at any time by updating the DNS record. Most domains reach p=reject and stay there indefinitely. The reason to step back temporarily would be a major sender-infrastructure migration — and even then, well-planned migrations don't require it.
What about pct= at p=reject?
pct= tells receivers to apply the policy to that percentage of failing mail. p=reject pct=50 means 50% of failures get bounced, 50% get treated as if p=quarantine. Useful for the final ramp; not useful as a steady state.
Final thoughts
p=reject is the only DMARC policy that fully delivers on DMARC's original promise: a domain that can't be exact-spoofed. Every step before it — record creation, monitoring, remediation, quarantine — exists to make the move to p=reject safe and uneventful.
The discipline that produces a clean p=reject rollout is the same discipline that maintains it afterward: regular review of aggregate reports, fast remediation when new senders appear, and a clear runbook for the next configuration change. Get that operational posture right and p=reject is not the hard part — it's the moment you stop worrying about exact-domain spoofing forever.