📧 RFC 9989: DMARCbis Has Landed
Domain-Based Message Authentication, Reporting, and Conformance — Fully Revised
RFC 9989 | Standards Track | Published May 2026 | Obsoletes RFC 7489 and RFC 9091 Authors: T. Herr (Valimail), J. Levine (Standcore LLC) | Responsible AD: Murray Kucherawy
🎯 TL;DR
After a decade running on RFC 7489, DMARC has been formally re-specified as RFC 9989 — and this time it's a full Standards Track document, not just "Informational." If you run DNS/email infrastructure, this is the new canonical reference for DMARC. The core mechanism hasn't changed, but the Organizational Domain discovery model has been completely reworked, replacing the old Public Suffix List (PSL) dependency with a deterministic DNS Tree Walk algorithm.
🧩 What DMARC Actually Does
DMARC lets a Domain Owner publish a DNS TXT record that:
Enables validation of their domain's use in the
RFC5322.From(Author Domain) headerStates a handling preference for mail that fails that validation (
none/quarantine/reject)Requests reporting on how their domain is being used across the internet
It sits on top of SPF and DKIM, adding one critical ingredient neither provides alone: Identifier Alignment — the authenticated domain must actually match (loosely or strictly) the visible From: domain. That's the anti-spoofing piece.
🆕 What's Genuinely New in RFC 9989
Area | RFC 7489 (Old) | RFC 9989 (New) |
|---|---|---|
Track | Informational | Standards Track |
Org Domain discovery | Public Suffix List (PSL) dependency | DNS Tree Walk algorithm (Section 4.10) |
PSD support | Bolted on via separate experimental RFC 9091 | Native, via the |
Non-existent subdomains | No dedicated tag | New |
Report size limit syntax |
| Removed — now obsolete syntax |
| Present (partial enforcement rollout) | Removed entirely (see Appendix A.6) |
Reporting specs | Baked into RFC 7489 | Split into companion docs: RFC 9990 (aggregate reports) & RFC 9991 (failure reports) |
🌳 The Headline Feature: DNS Tree Walk
This is the part worth actually internalizing if you manage DNS for domains with any complexity.
The old way: Determine the Organizational Domain by checking a domain name against the Public Suffix List — a giant, externally maintained flat file. Different Mail Receivers used different PSL snapshots, causing quiet, hard-to-diagnose interoperability drift.
The new way — DNS Tree Walk:
Query
_dmarc.<full-author-domain>for a DMARC Policy Record.If found and valid → that's your policy (and possibly your Org Domain, depending on the
psdtag).If not found → strip the leftmost label and query again, walking up the tree.
Stop when a valid record is found, or you hit the registry-level suffix.
Hard cap: 8 queries. Domains with more than 8 labels get truncated to the top 7 remaining labels — a deliberate anti-DoS guardrail against pathological subdomain chains.
Worked example — Author Domain a.b.c.d.e.f.g.h.i.j.mail.example.com:
_dmarc.a.b.c.d.e.f.g.h.i.j.mail.example.com
_dmarc.g.h.i.j.mail.example.com
_dmarc.h.i.j.mail.example.com
_dmarc.i.j.mail.example.com
_dmarc.j.mail.example.com
_dmarc.mail.example.com
_dmarc.example.com
_dmarc.com
That's exactly 8 queries, no more, regardless of how deep the actual namespace goes.
⚠️ Practical gotcha for decentralized DNS
If you (or a client) delegate DNS management down a namespace with more than 8 labels and expect a psd=n record at some internal "zone cut" to be discovered — it won't be, because the Tree Walk truncates before reaching it. The RFC is explicit here:
Domain Owners wishing to have a specific DMARC Policy Record applied to a given Author Domain longer than eight labels MUST publish a DMARC Policy Record at that domain's own location — it will always be queried first, before any Tree Walk truncation kicks in.
🏷️ The Full Tag Reference
Tag | Required? | Purpose |
|---|---|---|
| REQUIRED, must be first |
|
| RECOMMENDED | Policy for the domain itself: |
| Optional | Policy override for existing subdomains |
| Optional 🆕 | Policy override for non-existent subdomains |
| Optional 🆕 |
|
| Optional |
|
| Optional | Aggregate report destination URI(s) |
| Optional | Per-message failure report destination URI(s) |
| Optional | Failure reporting trigger options ( |
| Optional | Testing mode flag — softens enforcement by one policy level |
~~ | ❌ Removed | No longer part of DMARC — see Appendix A.6 |
🛠️ Deployment Playbook (Section 5.1, Condensed)
Publish SPF with an aligned MAIL FROM domain
Configure DKIM signing with an aligned signing domain
Stand up a mailbox for aggregate reports
Publish
p=nonewithrua=pointed at that mailbox — this is Monitoring ModeParse and analyze aggregate reports (don't try to read them by eye — get tooling)
Fix unaligned/unauthenticated legitimate streams you discover
Move to Enforcement (
p=quarantine→p=reject) once confident — this can take months for anything non-trivial
🔐 Security & Operational Notes Worth Flagging
Never rely on
-allSPF hard-fail alone if you're atp=reject. Early SMTP-stage SPF rejection happens before DMARC evaluation even runs — meaning a message could be rejected on SPF alone, before DKIM alignment ever gets a chance, and it will never show up in your aggregate reports either, since the transaction never reachesDATA.p=rejectbreaks indirect mail flows. Mailing lists, alumni forwarders, and role aliases routinely fail SPF on relay and depend on DKIM surviving the hop. The RFC is blunt: domains hosting users who post to mailing lists SHOULD NOT publishp=reject.Mail Receivers MUST NOT reject solely on
p=reject. They're required to treat unmitigatedp=rejectfailures as if they werep=quarantinein the absence of other signal — a meaningful softening from blind trust in the published policy.DMARC does not stop display-name spoofing or lookalike domains. That's explicitly out of scope (Section 2.4) — don't oversell it to clients as a full phishing solution.
📚 Companion Documents
DMARCbis is now split across three RFCs instead of one monolith:
RFC | Covers |
|---|---|
RFC 9989 | Core mechanism (this document) |
RFC 9990 | Aggregate reporting format |
RFC 9991 | Failure reporting format |
🔗 Resources
Full text: https://www.rfc-editor.org/rfc/rfc9989.html
Datatracker page: https://datatracker.ietf.org/doc/rfc9989/
Companion: RFC 9990 (aggregate reports), RFC 9991 (failure reports)
Historical context: RFC 7960 (DMARC + indirect mail flow interop issues)
Compiled as a working reference — verify tag syntax against the RFC text directly before shipping production zone-file changes.

