DMARC Deployment in Depth
Operational DMARC deployment — full tag reference, subdomain policy, pct sampling, alignment strictness, report processing, forwarding/mailing-list failure modes, and the none→quarantine→reject rollout.
This article extends DMARC (concepts, alignment, the basic record) with the operational details a domain owner needs to deploy DMARC safely: the full tag set, subdomain policy, percentage sampling, alignment strictness, report handling, common failure scenarios, and the enforcement rollout path. Content is drawn from dmarc.org, the home of the DMARC specification.
Specification status
| Document | Role | Status |
|---|---|---|
| RFC 7489 (March 2015) | Original DMARC specification (Informational) | Obsoleted |
| RFC 9989 (May 2026) | Core DMARC protocol ("DMARCbis", Standards Track) | Current |
| RFC 9990 (May 2026) | Aggregate reporting | Current |
| RFC 9991 (May 2026) | Failure reporting | Current |
Key changes in the new RFCs (not breaking — records still begin v=DMARC1):
- Removed tags:
pct,rf,ri.pctwas removed because its definition in RFC 7489 was ambiguous from the start ("percentage of messages from the Domain Owner's mail stream to which the DMARC policy is to be applied"). - New tags:
np(policy for non-existent subdomains),psd(public suffix domain flag),t(testing flag, the replacement for thepct=0-style "monitor but don't enforce" use case). - Organizational Domain discovery: the Public Suffix List is replaced by a DNS Tree Walk — the receiver queries
_dmarc.<author-domain>, then_dmarc.<parent>, and so on up the tree, capped at eight queries.
Because RFC 7489 semantics are still what most deployed records and receivers use, the tag reference below covers both.
Full tag reference
DMARC records use the extensible tag-value syntax borrowed from DKIM. All tags other than v and p are optional.
| Tag | Purpose | Example | Notes |
|---|---|---|---|
v |
Protocol version; must be first | v=DMARC1 |
Only valid value |
p |
Policy for the Organizational Domain | p=quarantine |
none / quarantine / reject |
sp |
Policy for subdomains of the Organizational Domain | sp=reject |
Defaults to the p value when absent |
pct |
Percentage of failing messages the p policy is applied to |
pct=20 |
RFC 7489 only; removed in RFC 9989 |
rua |
URI(s) for aggregate reports | rua=mailto:aggrep@example.com |
Comma-separate multiple URIs |
ruf |
URI(s) for message-level failure ("forensic") reports | ruf=mailto:authfail@example.com |
|
adkim |
DKIM alignment mode | adkim=s |
r (relaxed, default) / s (strict) |
aspf |
SPF alignment mode | aspf=r |
r (relaxed, default) / s (strict) |
fo |
Failure-report options | fo=1 |
0 both fail (default), 1 either fails, d DKIM fail, s SPF fail |
rf |
Failure report format | rf=afrf |
RFC 7489 only; removed in RFC 9989 |
ri |
Requested aggregate report interval (seconds) | ri=86400 |
RFC 7489 only; removed in RFC 9989 |
np |
Policy for non-existent subdomains | np=reject |
New in RFC 9989 |
psd |
Marks a record published at a public suffix domain | psd=y |
New in RFC 9989 |
t |
Testing flag — evaluate but do not enforce | t=y |
New in RFC 9989; replaces the sampling role of pct |
Example record:
_dmarc.example.com. IN TXT "v=DMARC1; p=reject; pct=100; rua=mailto:postmaster@example.com"
Subdomain policy (sp=)
Without sp=, subdomains inherit the Organizational Domain's p= policy. Publishing sp= lets you enforce differently across the organizational structure, for example:
p=none; sp=reject— still monitoring the apex domain, but rejecting spoofed mail on subdomains that send no mail.p=reject; sp=none— apex locked down while a subdomain's mail streams are still being brought into alignment (a weak spot attackers can exploit; close it as soon as possible).
BIMI eligibility requires enforcement on both: p=quarantine|reject with no sp=none (see BIMI). Note that RFC 9989 adds np= so that non-existent subdomains can be rejected even while real subdomains are at a looser policy.
Percentage sampling (pct=, RFC 7489)
pct defines the percentage of failing messages the p= policy is applied to; the remaining messages are treated with the next-lower policy:
p=reject; pct=60→ 60% of failing traffic is rejected, 40% is quarantined.p=quarantine; pct=25→ 25% quarantined, 75% treated asnone.
This built-in throttle enables gradual enforcement: raise pct in steps at each policy level and watch the reports before going to 100. Under RFC 9989, pct is gone; the t=y testing flag covers the "publish enforcement intent without impact" case, and gradual rollout is done by moving between policy levels.
Alignment strictness (adkim= / aspf=)
Both alignment tags accept:
r(relaxed, default) — the authenticated domain (DKIMd=or SPF RFC5321.MailFrom) only needs to share the Organizational Domain with the RFC5322.From domain.news.example.comaligns withexample.com.s(strict) — the domains must match exactly.
Relaxed mode is the right default for almost all senders; strict mode is for domain owners who want to prevent even sibling subdomains from authenticating mail for one another (e.g., isolating business units, or defending against a compromised third party that signs as a delegated subdomain). Do not set s until aggregate reports confirm every legitimate stream authenticates with the exact From domain.
Report processing
Aggregate reports (rua=)
- XML documents, typically generated daily per reporting receiver; expect the first reports 24+ hours after publishing the record.
- Contain per-source-IP counts with SPF/DKIM raw results, alignment evaluation, and the disposition applied.
- Delivered gzip-compressed to
mailto:URIs — use a dedicated mailbox and machine parsing, never a human inbox. - This is the primary dataset for deployment decisions: it reveals every source (including forgotten third parties) using your domain in the RFC5322.From.
Failure reports (ruf=)
- Sent immediately, per failing message — volume "could be several times the volume of your legitimate emails" if the domain is being spoofed at scale.
- Enable message-level forensics, but many receivers do not send them (privacy), and they require capacity planning. Deploy
ruf=only after you understand your traffic via aggregate reports — or not at all.
External report destinations
If rua=/ruf= point to a domain other than the one publishing the DMARC record, receivers verify authorization. The report-receiving domain must publish:
example.com._report._dmarc.thirdparty.com. IN TXT "v=DMARC1"
(meaning: thirdparty.com agrees to accept reports about example.com). A wildcard form accepts reports for any domain, at the cost of an abuse vector:
*._report._dmarc.thirdparty.com. IN TXT "v=DMARC1"
DMARC report-processing services rely on this mechanism — it is why pointing rua= at a vendor address works without them controlling your DNS.
Tooling
dmarc.org maintains directories of deployment tools (record generators/wizards: dmarcian, EasyDMARC, DMARCLY, Fortra/Agari, Kitterman, Proofpoint, Global Cyber Alliance; record checkers: the same vendors plus Sendmarc, Valimail, Mimecast; message reflectors/validators: autoreply@dmarctest.org, aboutmy.email, Red Sift Investigate) and code and libraries (OpenDMARC milter, Mail::DMARC in Perl, mail-auth in Rust, rddmarc report-parsing scripts, dmarc-report-processor for CSV conversion, Lafayette for report storage, among others). Commercial report processors are listed under products and services.
Common failure scenarios
Forwarding
Simple forwarding rewrites the RFC5321.MailFrom (or reuses the original from a new IP), so SPF alignment is lost. DKIM survives forwarding only if the forwarder does not modify the signed content — typically, adding new headers is safe; touching the Subject or body breaks the signature. This is a core reason to authenticate with both protocols and to treat aligned DKIM as the load-bearing one: a message that keeps its DKIM signature intact passes DMARC after forwarding even though SPF fails.
Mailing lists
Traditional lists modify messages (subject tags, footers) — breaking DKIM — and send from their own infrastructure — breaking SPF alignment. Posts from a p=reject domain then bounce for all subscribers. Known mitigations:
| Mitigation | Mechanism | Trade-off |
|---|---|---|
| Strict forwarding | List preserves the message untouched so the original DKIM signature validates | Loses subject tags/footers list users expect |
| Original Authentication Results (OAR) / ARC | List records the authentication state it observed at ingestion so receivers can trust it | Requires receiver adoption; limited but growing (ARC is the modern successor) |
| From rewriting (ownership transfer) | List rewrites RFC5322.From to its own domain and DKIM-signs as itself | Message is now "from" the list; replies and address books are affected |
From rewriting is what most large list software does today when the author's domain is at enforcement. If your users post to mailing lists, expect this behavior once you move past p=none.
The rollout path: none → quarantine → reject
The dmarc.org five-step sender deployment process:
- Deploy DKIM and SPF on every legitimate mail stream (corporate mail, marketing platform, CRM, billing system, support desk — all of them).
- Ensure alignment: verify each stream's identifiers align with the RFC5322.From domain (DKIM
d=and/or RFC5321.MailFrom). - Publish
p=nonewithrua=pointing at a dedicated report mailbox or processor. No delivery impact; you are only collecting data. - Analyze reports and fix streams. Every source that fails is either (a) a legitimate sender to bring into alignment, or (b) abuse that enforcement will stop. Iterate until the aggregate reports show all legitimate mail passing.
- Escalate: move to
p=quarantine, initially with lowpctsampling (RFC 7489 receivers), raising towardpct=100; monitor reports for legitimate mail being quarantined. When none is, move top=reject— again optionally rampingpct.
Operational guidance for each phase:
p=nonephase: budget weeks, not days. Third-party senders (billing, HR, event platforms) surface slowly in reports because some send infrequently.p=quarantinephase: failing legitimate mail lands in spam rather than disappearing, so recipients can still rescue it — this is the safety net that makes quarantine the mandatory intermediate step. Watch for forwarding and mailing-list traffic (above), which will fail by design.p=rejectphase: only after aggregate reports show no legitimate messages being quarantined. Rejection is visible to the sending party (bounce), which aids detection of broken streams but means lost mail for anything you missed.- Remember
sp=at every step: a policy migration on the apex does not protect (or break) subdomains you have excluded.
Enforcement (quarantine or reject at 100%) is also the entry requirement for BIMI.
Related
- DMARC — concepts, SPF/DKIM primer, alignment, the basic record
- BIMI — logo display, which requires DMARC enforcement
- Foundations of Email Deliverability