DMARC Standard Reference (RFC 9989 / DMARCbis)
The standards-track DMARC spec that obsoletes RFC 7489 — full record tag registry, the DNS Tree Walk replacing the Public Suffix List, alignment rules, policy discovery, and what changed.
RFC 9989 (Standards Track, May 2026) is the current DMARC specification, obsoleting RFC 7489 and RFC 9091. It splits DMARC into three documents: RFC 9989 (core protocol), RFC 9990 (aggregate reporting), and RFC 9991 (failure reporting). For the conceptual introduction — what DMARC does, alignment basics, rollout strategy — see DMARC; this article is the record-level and algorithm-level reference.
Complete tag registry
Published as a TXT record at _dmarc.<domain>. Tags are semicolon-separated key=value pairs; v= must be first.
| Tag | Values | Default | Meaning |
|---|---|---|---|
v |
DMARC1 |
required, first tag | Version. |
p |
none | quarantine | reject |
none if absent |
Requested handling for messages from the domain that fail DMARC. |
sp |
same as p |
inherits p |
Policy for existing subdomains of the record's domain. |
np |
same as p |
inherits sp, then p |
New in 9989. Policy for non-existent subdomains (no A/AAAA/MX). Lets you set e.g. p=none; np=reject to kill spoofing of made-up subdomains while still ramping the main domain. |
adkim |
r | s |
r |
DKIM alignment mode: relaxed (same Organizational Domain) or strict (identical domain). |
aspf |
r | s |
r |
SPF alignment mode. |
rua |
comma-separated mailto: URIs |
none | Destinations for aggregate reports. |
ruf |
comma-separated mailto: URIs |
none | Destinations for failure reports. |
fo |
0 | 1 | d | s (colon-separated combos) |
0 |
Failure-report triggers: 0 = report only if all mechanisms fail to produce an aligned pass; 1 = report if any mechanism fails; d = report DKIM failures regardless of alignment; s = report SPF failures regardless of alignment. |
psd |
y | n | u |
u |
New in 9989. Whether this domain is a Public Suffix Domain (y), definitely not one (n), or unknown (u). Consumed by the Tree Walk. |
t |
y | n |
n |
New in 9989. Test mode: t=y asks receivers to treat the policy as advisory (evaluate and report, but don't enforce disposition). Replaces pct. |
Removed from RFC 7489: pct (percentage sampling — replaced by the all-or-nothing t tag) and ri (report interval). Receivers still encountering old records simply ignore unknown/retired tags.
If a discovered record has no valid p tag but has a valid rua, receivers treat it as p=none (monitoring-only) rather than discarding it.
Alignment
An Authenticated Identifier is a DKIM d= domain from a passing signature, or the SPF-validated RFC5321.MailFrom domain.
- Relaxed (default): the From: domain and the Authenticated Identifier share the same Organizational Domain.
- Strict: the domains must be identical.
- Comparison is case-insensitive. An aligned pass from either DKIM or SPF yields DMARC pass.
The DNS Tree Walk (replaces the Public Suffix List)
RFC 7489 needed the browser-world Public Suffix List to find a domain's Organizational Domain. RFC 9989 replaces this with an in-DNS Tree Walk, capped at 8 queries per walk:
- Query
_dmarc.<domain>for the exact domain; discard anything not startingv=DMARC1. - If the name has more than 8 labels, jump straight to its last (rightmost) 7 labels for subsequent steps.
- Remove the leftmost label and query
_dmarc.at each successively shorter name. - Stop early when a record with
psd=norpsd=yis found (these anchor the organizational/public-suffix boundary). - The walk ends when a suitable record is found or labels are exhausted.
The Organizational Domain is determined from the walk results (the domain below the point where psd=y appears, or the longest name with a record / psd=n). This changes edge-case behavior vs. the PSL for deeply delegated zones, but for typical example.com / mail.example.com setups the outcome is the same.
Policy discovery for a message
- Query
_dmarc.<RFC5322.From domain>. If a valid DMARC record exists, use it. - Otherwise perform the Tree Walk upward; the first valid record found governs.
- When the applied record was found above the From: domain (i.e., the From: domain is a subdomain): use
spif the subdomain exists in DNS,npif it does not exist, else fall back top. - No valid record anywhere → DMARC does not apply to the message (disposition
none, result "none" in Authentication-Results).
Operational implications
- Publish
psd=non an organizational domain's record if you delegate deep subdomain trees — it pins the Tree Walk and prevents mis-attribution. - Use
np=to protect against spoofing of non-existent subdomains even while the primary policy is stillp=noneduring rollout. t=yreplacespct=ramping. Under RFC 7489,pct=25gave partial enforcement; under 9989 you either enforce or you test. Plan rollouts asp=none→ (t=ywithp=quarantine/reject) → enforcement, driven by aggregate-report data as described in DMARC.- Receivers roll out DMARCbis gradually; expect a long period where both RFC 7489 semantics (PSL,
pct) and RFC 9989 semantics (Tree Walk,t,np,psd) are live in the wild. Records containing only the common subset (v,p,sp,adkim,aspf,rua,ruf,fo) behave identically under both.
Related
- DMARC — concepts, alignment primer, rollout strategy
- DMARC aggregate reports (RFC 9990)
- DMARC failure reports (RFC 9991)
- SPF · DKIM · ARC