Configuring a DMARC Policy: Moving Safely from p=none to p=reject
Stage a DMARC rollout on a live transactional domain: p=none monitoring, pct-ramped quarantine, then reject, with exact DNS records and aggregate-report reading.
You run a live domain already sending password resets, receipts, and notifications, and you need to move DMARC from monitoring to full p=reject enforcement without bouncing a single legitimate message. The danger is that flipping straight to reject rejects mail you forgot you were sending. This walks the staged rollout that prevents that, building on the records introduced in the SPF, DKIM, and DMARC authentication guide.
Root Cause: Why Jumping Straight to Reject Breaks Legitimate Mail
DMARC enforcement acts on every message claiming your From domain, including senders you may have forgotten. Two categories fail at the moment you publish p=reject:
- Unaligned forwarders. When a recipient auto-forwards your mail, the forwarding server becomes the new connecting IP, so SPF breaks. DKIM survives forwarding only if the forwarder does not alter the body. A forwarder that appends a footer breaks the DKIM body hash too, leaving the message with no aligned, passing mechanism โ and
rejectbounces it. - Third-party senders. Your billing platform, helpdesk, CRM, and marketing tool may all send as your domain without aligned SPF or DKIM. Under
p=nonethey deliver fine; underp=rejectthey vanish.
The entire point of the staged rollout is to discover these senders through aggregate reports before enforcement can drop their mail.
There is a second, subtler failure mode: alignment that passes in isolation but not for the From domain. A message can show spf=pass and dkim=pass in the raw headers yet still fail DMARC, because the passing SPF was for the ESP's bounce domain and the DKIM d= was a provider subdomain โ neither aligned with the visible From. At p=none this is invisible because nothing acts on the failure; at p=reject it bounces real mail. Aggregate reports expose exactly this distinction, separating "authenticated" from "authenticated and aligned," which is why you must read the reports rather than assume a passing test send means you are safe to enforce.
Exact Fix: The Staged Rollout
Stage 1 โ Monitor with p=none
Publish a monitoring-only policy. It changes nothing about delivery; it only asks receivers to send you reports.
; Stage 1: monitoring only. Delivery is unaffected; collect reports.
_dmarc.yourdomain.com. IN TXT "v=DMARC1; p=none; rua=mailto:dmarc-agg@yourdomain.com; ruf=mailto:dmarc-forensic@yourdomain.com; fo=1; adkim=s; aspf=s; pct=100"
; | | | | |
; | | | | +-- fo=1: report on any auth failure (not just full DMARC fail)
; | | | +-- forensic reports; few receivers send, but harmless to request
; | | +-- aggregate XML rollups; Google, Yahoo, Microsoft send these daily
; | +-- no action taken on failures yet
; +-- required first token
Leave this in place for at least two to four weeks so weekly and monthly senders appear in the data.
Stage 2 โ Quarantine with a pct Ramp
Once reports confirm your legitimate senders pass, move to quarantine but only on a fraction of mail using pct. Failing mail lands in spam rather than bouncing, so a mistake is recoverable.
; Stage 2a: quarantine 25% of failing mail. Failures go to Junk, not bounced.
_dmarc.yourdomain.com. IN TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc-agg@yourdomain.com; adkim=s; aspf=s; pct=25"
; | |
; | +-- only 25% of failing mail is quarantined; rest still delivered
; +-- failing mail to Gmail/Yahoo/Outlook is filed as spam
Ramp pct=25 โ 50 โ 100 over one to two weeks each, watching aggregate reports for any drop in legitimate volume.
Stage 3 โ Reject
With pct=100 quarantine clean, switch to full enforcement.
; Stage 3: full enforcement. Unaligned mail is bounced by Gmail, Yahoo, Outlook.
_dmarc.yourdomain.com. IN TXT "v=DMARC1; p=reject; rua=mailto:dmarc-agg@yourdomain.com; adkim=s; aspf=s; pct=100; sp=reject"
; | |
; | +-- subdomain policy: reject spoofed mail from unused subdomains
; +-- receivers bounce any message failing DMARC
Drop the ruf=/fo= once stable โ forensic reports carry recipient data and few receivers send them.
How to Read Aggregate Reports
Receivers send daily gzipped XML to your rua address. Each <record> reports a source IP, message count, and the SPF/DKIM/DMARC result. The fields that matter:
<record>
<row>
<source_ip>198.51.100.7</source_ip> <!-- which server sent as your domain -->
<count>240</count> <!-- how many messages -->
<policy_evaluated><disposition>none</disposition></policy_evaluated>
</row>
<auth_results>
<spf><domain>yourdomain.com</domain><result>pass</result></spf> <!-- aligned SPF -->
<dkim><domain>yourdomain.com</domain><result>pass</result></dkim> <!-- aligned DKIM -->
</auth_results>
</record>
Reverse-lookup unfamiliar source IPs. A source passing for mail.helpdesk.com instead of yourdomain.com is an unaligned third party you must fix before enforcement. Hand-parsing XML does not scale; route reports to a processor (Dmarcian, Postmark's DMARC Digests, or a self-hosted parser) and feed the parsed signal into your webhook event pipelines for alerting.
Variant Cases
Subdomain policy (sp=). The p= policy applies to the organizational domain; sp= governs subdomains. Set sp=reject to stop attackers spoofing unused subdomains like marketing.yourdomain.com. If a subdomain has its own slower rollout, give it a dedicated _dmarc.subdomain record with its own p=, which overrides the parent's sp.
Multiple third-party senders. Each tool needs either an aligned DKIM signature (d=yourdomain.com) or an aligned custom Return-Path. The cleanest pattern is to delegate each sender to its own subdomain โ bills.yourdomain.com for billing, notify.yourdomain.com for the ESP โ so reputation is isolated and alignment is straightforward. Your ESP selection and integration provider supplies the custom Return-Path needed for SPF alignment.
Aggregate-Report Tooling
Hand-parsing gzipped XML stops scaling after the first week โ a single domain can receive dozens of reports a day from Google, Yahoo, Microsoft, Comcast, and others, each with many <record> rows. Route the rua mailbox to a processor that aggregates across receivers and surfaces unaligned sources as a list rather than raw XML. The realistic options:
| Tool | Hosting | Best for |
|---|---|---|
| Dmarcian | SaaS | Rich source-IP attribution and rollout dashboards |
| Postmark DMARC Digests | SaaS (free) | Weekly plain-language digest; good for low-volume domains |
| Valimail / EasyDMARC | SaaS | Automated source identification and guided enforcement |
parsedmarc + Elasticsearch/Grafana |
Self-hosted | Full data ownership; EU residency; custom alerting |
For a self-hosted pipeline, parsedmarc ingests the rua mailbox over IMAP, parses each report, and writes structured records you can query. The key field to alert on is any source where the message count is non-trivial and neither SPF nor DKIM aligns with your organizational domain โ that is an unaligned legitimate sender (or an active spoofer) you must resolve before tightening the policy.
# parsedmarc: pull DMARC aggregate reports from the rua IMAP mailbox and index them.
# Run on a schedule; the output feeds a dashboard that flags unaligned sources.
parsedmarc --imap-host imap.yourdomain.com \
--imap-user dmarc-agg@yourdomain.com \
--elasticsearch-hosts http://localhost:9200 \
--save-aggregate
# Alert rule (pseudo): disposition trending toward quarantine/reject for a KNOWN source = a sender about to break at enforcement.
The decisive metric the tooling exposes is the split between "authenticated" and "authenticated and aligned." A raw test send can show spf=pass/dkim=pass yet still be unaligned; only the aggregate data, summed across receivers and source IPs, tells you whether you are actually safe to advance a stage.
Variant: Aligning a Stubborn Third-Party Sender
The hardest senders to bring into alignment are SaaS tools that send "as" your domain โ billing (Stripe, Chargebee), helpdesk (Zendesk, Intercom), CRM, and survey tools โ because many sign DKIM with their own d= domain and use their own Return-Path, so they pass authentication but never align with your From. You have three levers, in order of preference:
- Custom DKIM (
d=yourdomain.com). The cleanest fix: the vendor provides CNAME records that delegate a signing selector to your domain, so thed=becomesyourdomain.comand DKIM aligns. Most mature SaaS senders support this โ enable it everywhere it exists. - Custom Return-Path / MAIL FROM. If the vendor cannot do custom DKIM but lets you set a custom envelope domain (e.g.
bounce.yourdomain.com), SPF then aligns through that subdomain. This depends on the ESP and provider integration settings the vendor exposes. - Dedicated subdomain with its own policy. When a sender supports neither, move it to a dedicated subdomain (
survey.yourdomain.com) with its own_dmarcrecord kept atp=noneorp=quarantinewhile the parent goes toreject. This isolates the laggard so it cannot block enforcement on the organizational domain, and its weaker policy is scoped to a subdomain attackers rarely target.
Drive each sender from the aggregate-report data: the report tells you exactly which source IP and d=/Return-Path a tool is using, which is what you reference when you open a support ticket asking the vendor to enable aligned DKIM.
Pipeline Integration: Managing the Record as Code
Hand-editing DNS in a console invites typos and undocumented changes. Manage the DMARC record in your DNS-as-code so each stage of the rollout is a reviewed commit.
# Terraform: DMARC record managed in version control (AWS Route 53).
# Promoting through stages is a reviewed pull request, not a console edit.
resource "aws_route53_record" "dmarc" {
zone_id = aws_route53_zone.primary.zone_id
name = "_dmarc.yourdomain.com"
type = "TXT"
ttl = 300 # short TTL during rollout so policy changes propagate fast
records = [
# Bump p and pct here per stage; git history is your rollout audit log.
"v=DMARC1; p=quarantine; rua=mailto:dmarc-agg@yourdomain.com; adkim=s; aspf=s; pct=50; sp=reject"
]
}
Keep the TTL low (300s) during the rollout so a regression can be rolled back fast, then raise it once you stabilize at p=reject. Encode the rollout itself as a sequence of merged pull requests โ one per stage โ so the git history doubles as an audit trail of when each policy change went live and who approved it. Pair each promotion with a note in the PR description recording the aggregate-report state that justified it ("two weeks at quarantine pct=100, zero unaligned legitimate sources"), so a future engineer can reconstruct why the domain is at its current policy without spelunking through receiver reports.
A practical guardrail: gate the Terraform apply behind the same lookup-count and policy-sanity checks you run for SPF, so a typo like p=rejct or a record that would exceed DNS length limits fails CI rather than silently disabling protection in production.
Validation Checklist
Frequently Asked Questions
How long should we stay at each policy stage?
Long enough for the aggregate reports to cover a full business cycle โ two weeks at monitoring is a reasonable minimum, and a month is better for an organisation with monthly processes such as payroll or invoicing that only send once. The reports are the evidence for promotion; promoting on a calendar rather than on the reports is how legitimate senders get blocked.
What does pct actually apply to?
Only to the quarantine or reject action, and only for messages that fail. It is a sampling dial for the enforcement, not for the evaluation โ every message is still evaluated and still reported. That makes it useful for a gradual rollout at quarantine, and largely pointless at reject, where a partial policy mostly creates inconsistent behaviour for the same sender.
Should the subdomain policy differ from the organisational one?
Set sp explicitly rather than letting it inherit. The common pattern is a stricter subdomain policy than the organisational domain during a rollout, because your sending subdomains are the ones you control and have already aligned, while the organisational domain may still have unknown sources. Leaving sp unset means the subdomain silently inherits whatever p becomes.
Do we need forensic reports?
Rarely, and they carry a privacy cost since they can contain message content and recipient addresses. Aggregate reports identify the unaligned sources, which is what a rollout needs. Forensic reports are worth enabling briefly when a source is unidentifiable from aggregate data alone, then turning off again.
What breaks at reject that did not break at quarantine?
Forwarding, most visibly. A forwarded message frequently fails SPF because the forwarding host is not in your record, and if DKIM was broken by the forwarder's rewriting then DMARC fails outright โ at quarantine that lands in spam, at reject it bounces. This is why DKIM alignment matters more than SPF: DKIM survives forwarding that SPF does not.
Related
- SPF, DKIM, and DMARC for transactional email โ the full authentication layer this rollout sits on
- Fixing SPF PermError: too many DNS lookups โ an SPF PermError can sink DMARC alignment during rollout
- ESP selection and integration โ configuring a custom Return-Path for SPF alignment
- Webhook event pipelines โ routing parsed aggregate reports into alerting
โ Back to Email Authentication: SPF, DKIM, and DMARC