All articles

Email Authentication

DMARCbis Explained: What Actually Changes in RFC 9989, 9990, and 9991

DMARC just left Informational status after eleven years and moved onto the IETF Standards Track, split across three RFCs. Here's what RFC 9989, 9990, and 9991 actually change, what they deprecate, and what a domain owner needs to do about it (mostly nothing, with two exceptions).

August 1, 2026

DMARC turned eleven years old still carrying the "Informational" label RFC 7489 gave it in 2015. That was always a little strange for a standard that, by 2026, sat behind the inbox filtering decisions of essentially every major mail provider on earth. In May 2026, the IETF closed that gap: RFC 7489 is obsolete, and DMARC is now defined by three companion documents, RFC 9989 (the core protocol and policy), RFC 9990 (aggregate reporting), and RFC 9991 (failure reporting), collectively nicknamed DMARCbis. Between them, they move DMARC onto the Standards Track as a Proposed Standard and clean up a handful of ambiguities the original spec left unresolved for over a decade.

If you already have a working DMARC record, the short version is: nothing breaks, nothing needs to change today, and you have years of runway before that stops being true. The longer version is worth knowing, because two of the changes are worth adopting deliberately rather than waiting for a deprecation deadline to force the issue.

Why DMARC needed a "bis"

RFC 7489 was published as Informational rather than Standards Track, which is unusual for something this load-bearing. It meant DMARC's own defining document couldn't be cited as authoritative IETF consensus, just as a description of what a group of large mailbox providers had already agreed to do. Eleven years of real-world deployment surfaced places where that description was incomplete: tags that receivers implemented inconsistently because the spec's wording allowed more than one reading, and gaps the spec never addressed at all, like what a receiver should do with a subdomain that doesn't exist in DNS.

DMARCbis was the IETF DMARC working group's attempt to close those gaps using running code as evidence, then advance the result to the Standards Track. That process is also why it landed as three documents instead of one: the core protocol in RFC 9989, aggregate reporting in RFC 9990, and failure reporting in RFC 9991 each had their own separate sets of ambiguities to resolve. Separating them let each move through review independently, and it means either reporting format can be revised later without reopening the policy spec.

What actually changes

pct= is deprecated in favor of t=. The original spec never fully resolved whether pct applied to a domain's entire outbound mail stream or only to the messages that failed authentication, and different receivers picked different interpretations. RFC 9989 drops the percentage rollout model entirely and replaces it with a binary testing flag:

_dmarc.example.com.  TXT  "v=DMARC1; p=reject; t=y; rua=mailto:[email protected]"

t=y marks the policy as being in a testing state. Receivers are expected to treat a testing-flagged policy less strictly in practice while still generating full reports, without the domain owner having to guess what fraction of traffic a given pct value actually covered. t=n (or omitting the tag) means the policy is live. It's a coarser lever than pct was, but a coarser lever that means the same thing to every receiver is a better trade than a precise one that means three different things depending on who's reading it.

np= closes the non-existent subdomain gap. Under RFC 7489, a domain's p= policy applied to subdomains via sp= (or p= itself, if sp= wasn't set) whether or not that subdomain existed in DNS at all. That's exactly backwards from a security standpoint: a subdomain that doesn't exist has no legitimate reason to send mail from anywhere, so it's the case that most deserves a strict default, and instead it inherited whatever policy the domain happened to have picked for subdomains that do send mail.

_dmarc.example.com.  TXT  "v=DMARC1; p=quarantine; sp=quarantine; np=reject; rua=mailto:[email protected]"

RFC 9989's new np= tag lets you set reject for nonexistent subdomains specifically, independent of whatever sp= says for subdomains that are actually in use. Most domains have far more unused subdomain names than active ones, and every one of them is a potential spoofing source until np= closes it off.

Aggregate reporting gets a clearer format contract. One of the persistent annoyances in DMARC reporting has been that the spec called for GZIP-compressed XML, and receivers didn't reliably follow it, some send .zip instead of .xml.gz, and any parser has had to handle both since day one. RFC 9990 pulls aggregate reporting into its own Standards Track document, formalizes the XML namespace and schema, and adds fields for the things RFC 9989 introduced, including which discovery method the receiver used and the np and testing values that were in effect. It also makes the DKIM selector mandatory whenever DKIM results are reported, which turns "some signature failed somewhere" into an actionable key-rotation diagnosis. It doesn't retroactively fix reports already sitting in your inbox, but new reports from updated senders should be more uniform.

The Public Suffix List is out of the loop. Working out a domain's organizational domain, the thing relaxed alignment compares against, used to mean consulting the Public Suffix List: an externally maintained file that every implementation had to fetch and keep current, with no way for a domain owner to correct it in a hurry. RFC 9989 replaces that with an in-protocol "DNS tree walk", where the receiver queries up the DNS hierarchy, capped at eight lookups, until it finds the boundary. A new psd= tag lets an operator whose domain is a public suffix, a registry or a SaaS platform issuing subdomains like github.io, declare that in DNS instead of waiting on a list update. If you're a normal domain owner there's nothing here to configure; it just removes a static file from the middle of the alignment decision.

Failure reports get their own document. RFC 9991 moves ruf= reporting out of the core spec and tightens the ARF-based format around it: required fields for alignment results, explicit redaction and transport-security guidance, mandatory verification of external report destinations, and a rate limit on outgoing reports. The ruf= and fo= tags themselves work exactly as before, and receiver support for failure reports is still thin, so this is mostly a specification cleanup rather than something you'll notice in your inbox.

What doesn't change

p=, sp=, rua=, ruf=, adkim=, aspf=, and the relaxed/strict alignment model all carry forward unmodified. The _dmarc. subdomain location, the requirement to pass SPF or DKIM plus alignment, and the none → quarantine → reject rollout philosophy are all untouched. RFC 9989 changed how a receiver finds your organizational domain, but not what aligning against it means. If you've already got a working DMARC record, as covered in DMARC Explained, essentially all of that reference material is still current.

The transition timeline

The transition is explicitly designed to be long and soft. pct still works, and will for years, since senders and receivers alike need time to update software before anyone can safely assume t= support is universal. RFC 9989 doesn't set a hard sunset date for pct; it's a deprecation in the sense that new deployments should prefer t=, not in the sense that existing pct= records stop functioning on a fixed date. The same applies to np=: not adopting it doesn't break anything, it just leaves nonexistent subdomains inheriting whatever policy your existing sp= (or p=) already specifies.

What to actually do about it

For most domains, two changes are worth making at the next opportunity, not urgently:

  1. Add np=reject if you haven't already, alongside whatever p= and sp= you're running. This is close to a strict improvement with minimal downside: nonexistent subdomains have no legitimate mail to protect against false positives.
  2. If you're mid-rollout using pct to ramp up enforcement gradually, finish that rollout as planned. There's no reason to switch to t=y/t=n partway through; adopt the new tag on your next new deployment instead of retrofitting an in-progress one.

Everything else, the record format, the reporting addresses, the alignment tags, needs no action at all.

dig TXT _dmarc.example.com

MyDMARC's DMARC checker has been updated to recognize t= and np= alongside the existing tag set, and flags a record still relying on pct= with a note rather than an error, since it's still valid, just on its way toward being the less-preferred option.

How this connects to the rest of email authentication

RFC 9989 changes the policy layer only. It still depends entirely on SPF and DKIM being configured correctly underneath it; nothing here changes how either of those work. If you're setting up DMARC for the first time, DMARC Explained covers the full anatomy of a record, and SPF Records Explained and DKIM Records Explained cover the two records DMARC alignment actually checks against. If you don't have an SPF record yet, Your Domain Has No SPF Record walks through adding one.

How DNS monitoring fits in

A DMARC record migrating from pct= to t=, or gaining an np= tag, is a deliberate, low-risk change. A DMARC record silently losing its policy entirely, or reverting from reject back to none during a provider migration, is not. OneDollarDNS monitors your _dmarc TXT record for any change, whether it's an intentional move to the RFC 9989 tags or an unintentional regression, and alerts you either way instead of leaving you to notice only when spoofed mail starts arriving.

Monitor your DNS for $1/month

OneDollarDNS watches your DNS records and alerts you the moment anything changes.

Get started free