📧 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:

  1. Enables validation of their domain's use in the RFC5322.From (Author Domain) header

  2. States a handling preference for mail that fails that validation (none / quarantine / reject)

  3. 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 psd tag

Non-existent subdomains

No dedicated tag

New np tag

Report size limit syntax

rua/ruf URI !size suffix

Removed — now obsolete syntax

pct tag

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:

  1. Query _dmarc.<full-author-domain> for a DMARC Policy Record.

  2. If found and valid → that's your policy (and possibly your Org Domain, depending on the psd tag).

  3. If not found → strip the leftmost label and query again, walking up the tree.

  4. Stop when a valid record is found, or you hit the registry-level suffix.

  5. 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

v

REQUIRED, must be first

DMARC1 — record version

p

RECOMMENDED

Policy for the domain itself: none / quarantine / reject

sp

Optional

Policy override for existing subdomains

np

Optional 🆕

Policy override for non-existent subdomains

psd

Optional 🆕

y = this is a Public Suffix Domain; n = this is its own Org Domain; u = undetermined (default)

adkim / aspf

Optional

r (relaxed) or s (strict) alignment mode per mechanism

rua

Optional

Aggregate report destination URI(s)

ruf

Optional

Per-message failure report destination URI(s)

fo

Optional

Failure reporting trigger options (0, 1, d, s)

t

Optional

Testing mode flag — softens enforcement by one policy level

~~pct~~

Removed

No longer part of DMARC — see Appendix A.6

🛠️ Deployment Playbook (Section 5.1, Condensed)

  1. Publish SPF with an aligned MAIL FROM domain

  2. Configure DKIM signing with an aligned signing domain

  3. Stand up a mailbox for aggregate reports

  4. Publish p=none with rua= pointed at that mailbox — this is Monitoring Mode

  5. Parse and analyze aggregate reports (don't try to read them by eye — get tooling)

  6. Fix unaligned/unauthenticated legitimate streams you discover

  7. Move to Enforcement (p=quarantinep=reject) once confident — this can take months for anything non-trivial

🔐 Security & Operational Notes Worth Flagging

  • Never rely on -all SPF hard-fail alone if you're at p=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 reaches DATA.

  • p=reject breaks 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 publish p=reject.

  • Mail Receivers MUST NOT reject solely on p=reject. They're required to treat unmitigated p=reject failures as if they were p=quarantine in 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

Compiled as a working reference — verify tag syntax against the RFC text directly before shipping production zone-file changes.

Keep Reading