dmarc.quest

DMARCbis is here: what actually changed in RFC 9989, 9990, and 9991

DMARC is finally a real IETF standard. What the new RFCs change — pct removed, the np tag, the DNS Tree Walk — and the five-minute checklist for your own record.

DMARC spent eleven years as a curiosity of the RFC series: universally deployed, required by Google and Yahoo for bulk senders, enforced by every major mailbox provider — and, formally, just an "Informational" document that the IETF never standardized. That changed in May 2026. The DMARC working group's long-running revision, known as DMARCbis, was published as three Standards Track RFCs:

  • RFC 9989 — DMARC itself: the policy record, identifier alignment, and how receivers discover and apply policy
  • RFC 9990 — aggregate reporting: the XML reports mailbox providers send domain owners
  • RFC 9991 — failure reporting: the per-message forensic reports almost nobody sends

Together they obsolete RFC 7489, the 2015 document every current DMARC deployment was built against. Here's what actually changed, and — more usefully — what you should do about it, which in most cases is nothing, and in a few cases is worth five minutes of your time.

The short version

If you run a domain and your DMARC record looks like v=DMARC1; p=quarantine; rua=mailto:..., nothing broke. The record format is compatible, receivers will evaluate your mail the same way tomorrow as yesterday, and no registrar is going to email you about this. The changes that matter are at the edges:

ChangeWho it affects
pct tag removed, t tag addedAnyone with pct= in a live record
rf and ri tags removedCosmetic — receivers ignored them anyway
np tag added (non-existent subdomains)Anyone who wants tighter subdomain protection
Public Suffix List replaced by a "DNS Tree Walk"Implementers; edge-case domain structures
Formal warning against premature p=rejectAnyone planning an enforcement rollout
Report format additionsReport processors, not domain owners

DMARC is finally a real standard

RFC 7489 was published in 2015 through the Independent Submissions stream — industry consortium work (the original DMARC.org group) that the RFC Editor published without IETF consensus. That never mattered much in practice, but it left DMARC in a strange position: the single most consequential email policy mechanism of the past decade had the same formal status as an April Fools RFC.

RFC 9989 is a Proposed Standard, the product of an IETF working group. For most people this is trivia. It matters in two situations: procurement and compliance contexts that require Standards Track protocols, and arguments — the "DMARC isn't even a real standard" objection is now retired.

pct is gone; meet t=y

The pct tag promised something intuitive: apply my policy to only N% of failing mail, so I can roll out enforcement gradually. Operational experience — documented bluntly in RFC 9989's Appendix A.6 — was that receivers "usually not accurately applied" it unless the value was 0 or 100. The partial percentages were fiction at many receivers.

Meanwhile pct=0 accidentally became load-bearing: some mailing lists and intermediaries treated it as a signal to rewrite the From header, which gave domain owners a way to measure how much of their mail flowed through non-rewriting intermediaries. So DMARCbis kept the useful endpoint and dropped the fiction: the new t tag ("testing") has exactly two values — t=y behaves like pct=0, and t=n (the default) like pct=100.

If your record carries pct=100, you can simply delete the tag — 100 is the default. If it carries pct=0 as a deliberate rewriting signal, t=y is the successor. If it carries something like pct=50, it was probably never doing what you hoped, and it's worth checking what your record actually says about the rest of your setup too. We wrote up the full story in pct is gone from DMARC — what to do with your record.

The np tag: policy for subdomains that don't exist

Attackers don't need mail.yourdomain.com to exist to put it in a From header. Under RFC 7489, a non-existent subdomain got the same treatment as any subdomain: your sp policy if you published one, otherwise your p. The new np tag — imported from the experimental RFC 9091 — lets you set a policy specifically for subdomains that don't exist in DNS at all.

This is one of the few genuinely free wins in the new spec. A subdomain that has never existed can't have legitimate mail, so np=reject costs nothing and closes the "spoof a subdomain nobody ever created" gap even while your apex policy is still p=none:

v=DMARC1; p=none; np=reject; rua=mailto:reports@example.com

Receivers that predate the tag ignore it — unknown tags are ignored by design — so there's no compatibility risk in publishing it today.

The Public Suffix List is out; the DNS Tree Walk is in

This is the deepest technical change, and the one domain owners will notice least. To evaluate "relaxed alignment" — whether mail.example.com and example.com belong to the same organization — RFC 7489 leaned on the Public Suffix List, a community-maintained file. The IETF was never comfortable standardizing a dependency on an external text file, and DMARCbis replaces it with the DNS Tree Walk (RFC 9989 §4.10): receivers now discover organizational boundaries by walking up the DNS tree looking for DMARC records, guided by a new psd tag that public suffix operators can publish.

For a typical business domain, the PSL answer and the Tree Walk answer are identical. The cases where they diverge involve deep subdomain trees, registry-level domains, and organizations doing unusual things with delegation. If that's you, the fix DMARCbis itself recommends is the same advice that was already good practice: publish explicit DMARC records for every domain you actually send from, and the discovery algorithm stops mattering.

The spec now tells you not to rush to p=reject

The most quotable change isn't a tag at all. RFC 9989 says, in as many words, that domains with human users who might post to mailing lists "SHOULD NOT publish Domain Owner Assessment Policies of p=reject" — and prescribes the path for domains that want to get there anyway: publish p=none and read your aggregate reports for at least a month, move to p=quarantine for an equally long period, compare the results, and only then decide about reject.

This deserves its own discussion — it's the change that most affects how you should actually operate a domain — so we wrote it up separately: The new DMARC standard says don't jump to p=reject. The one-sentence summary: enforcement is still the goal, but the standard now formally agrees that enforcement without reading your reports first is how you break your own mail.

Reporting got its own RFCs, and a few sharp edges got filed off

Splitting reporting into RFC 9990 (aggregate) and RFC 9991 (failure) is mostly organizational, but a few concrete things changed:

  • Reports should go to every listed address. RFC 7489 let receivers cap the number of rua destinations they'd send to (as long as they supported two); RFC 9990 says a report SHOULD be sent to each listed URI. Publishing your own mailbox and a processing service side by side is now on firmer ground.
  • The report-size suffix is gone. The old mailto:reports@example.com!10m syntax for capping report size was removed; it survives in the grammar only as obsolete syntax that reporters ignore. If your record has a !10m in it, it's inert — but some tooling mis-parses it, so removing it is tidier.
  • DKIM selectors are now required in reports. Under 7489 the selector was optional in the DKIM auth results; under 9990 it's required. As report generators adopt the new schema, aggregate reports will reliably tell you which DKIM key signed — which matters because selectors are otherwise unenumerable from the outside.
  • The report XML gets structure for extensions and errors, and the pct element gives way to testing and np in the published-policy block. Report processors need to handle both shapes for years to come; domain owners don't need to care.

One thing that didn't change: cross-domain report authorization. If your rua points at a different organization's domain, that destination still must publish an authorization record (yourdomain._report._dmarc.destination.com), and reporters are still told to ignore unauthorized destinations. The mechanism just moved from RFC 7489 §7.1 to RFC 9990 §4 — and it now explicitly blesses the wildcard form that reporting services (ours included) publish to accept reports for any domain.

What to actually do

For most domains, the honest checklist is short:

  1. If your record has pct= — delete it (if pct=100) or replace with t=y (if pct=0). Anything in between deserves a rethink.
  2. If your record has rf= or ri= — delete them. They were never honored and are now formally gone.
  3. Consider adding np=reject — free protection against never-created subdomains being spoofed.
  4. If you're planning enforcement — follow the ramp the spec now prescribes: monitor first, then quarantine, then decide. That requires actually receiving and reading aggregate reports, which is what monitoring is for.
  5. Everything else — leave it alone. Compatibility was a design goal of DMARCbis, and it delivered.

If you're not sure what your record says today, run the free check — it reads your live DNS, grades the whole setup (SPF, DKIM, DMARC, and the newer hardening layers), and tells you in plain language what's worth fixing.