Guides

What RFC 9989 changed about DMARC

DMARC stopped being RFC 7489 in May 2026. pct is gone, the Public Suffix List is gone, np and t arrived, and the external reporting record moved.

Yowl’s DMARC ladder tracks the current specification, not the one from 2015 — and the single biggest change here is one Yowl was already built around.

The withdrawn tag was the old way of doing what Yowl does

pct= is gone. It was the tag everybody’s staging advice is built on: p=quarantine; pct=10, then 50, then 100 — enforce against a slice, watch, widen. It was removed because receivers implemented it inconsistently enough that the results were not comparable between mailbox providers. Which means the standard advice for getting from monitoring to enforcement no longer has a mechanism behind it.

The replacement is not another tag. It is evidence: you climb when your reports say it is safe to climb. That is exactly the loop Yowl runs — the reports come back to an address on your own domain, Yowl parses them into who actually sent as you and whether they aligned, and the domain page shows one card when it is time to tighten and nothing at all when there is nothing to do. t=y marks the record as test-mode while you do it; the decision itself comes from the reports, not from a percentage.

So a guide still telling you to write pct=10 is not merely out of date — it is recommending a substitute for a judgement, and the substitute has been withdrawn.

Your agent can audit the record you already have

The rest of this page is a list of things that are now wrong in most published records. That is exactly the shape of job to hand to an AI. Connect Claude to your Yowl inbox and ask “is our DMARC record current?” — it reads the live record, the policy history, the parsed reports and the next rung, and tells you which of the four changes below apply to you.

Ask the same question about every domain you own, including the parked ones, and you get the same answer per domain. That is the part a checker website cannot do: it has no idea what else you run, no history, and nothing to compare this month against.

What actually moved

DMARC spent eleven years as RFC 7489, an Informational document from March 2015. In May 2026 it was replaced. The work that everyone called DMARCbis landed as three Standards Track RFCs, and 7489 is now historic:

Nothing you have published has stopped working. v=DMARC1 is preserved and existing records remain valid, which is why the change went almost unnoticed. But four things are now different enough to matter when you write or audit a record.

pct is gone, and two tags went with it

Covered above, with one detail worth keeping: rf= (only one format was ever defined) and ri= (ignored in practice) were withdrawn alongside it. A record still carrying any of the three keeps working, because receivers ignore tags they do not recognise — there is just no reason to write one into a new record. t=y / t=n is the replacement for “I am not ready to enforce yet”.

The Public Suffix List is gone

This is the deeper change, and the one with consequences.

Relaxed alignment accepts a pass on the same organisational domain — mail.example.com aligning with example.com. Under 7489, receivers worked out where the organisational boundary was by consulting the Public Suffix List, an externally maintained file. Different receivers carried different snapshots of it, which made alignment quietly non-deterministic for anything unusual.

RFC 9989 replaces it with a DNS tree walk: the receiver climbs the name one label at a time looking for a _dmarc record, capped at eight queries, and uses that both to discover policy and to decide alignment. No third-party file, and better behaviour on complex domain structures.

The practical consequence is that a _dmarc record at a higher level now has more reach than it used to, in both directions. Publish explicit records for the domains and subdomains that actually send, rather than relying on a parent to cover them — partly because that is clearer, and partly because 7489 receivers and 9989 receivers will not always agree about which record applies to a given subdomain during the years both are deployed.

np and psd arrived

np= sets the policy for non-existent subdomains, closing a real spoofing gap: sp covered subdomains that exist, and forgers were free to invent ones that did not.

psd= gives public-suffix operators — the registries behind .bank, .gov and similar — a way to publish policy for the names beneath them.

Both are worth having. Both are also inert on a 7489 receiver, which ignores tags it does not recognise, so adding np today is safe and takes effect gradually as receivers upgrade.

The external reporting record moved

If your rua sends reports to a domain other than the one publishing the policy, that other domain has always had to authorise it, or it is accepting reports about a domain it has nothing to do with.

Under 7489 the authorisation record was published at the reporting domain as example.com._report._dmarc.reports.net. RFC 9989 tightens this and the record now lives at _dmarc-report._report.<rua-domain>. Two other reporting details changed with it: the !10m size suffix on a rua address is removed, and aggregate reports are still XML but on a new schema namespace, urn:ietf:params:xml:ns:dmarc-2.0.

If reports mysteriously stopped arriving at a third-party service, this is now on the list of reasons why. Keeping rua on a domain you already control avoids the question.

What a current record looks like

_dmarc   TXT   "v=DMARC1; p=reject; sp=reject; np=reject; rua=mailto:dmarc@example.com"

v and p remain the only required tags. sp defaults to p. adkim and aspf default to r (relaxed) and only need stating to choose strict. ruf can stay out — Gmail has never sent failure reports and most large receivers either stopped or never started, which is what RFC 9991 exists to govern for the few that do.

Checking where you stand

dig +short TXT _dmarc.example.com

Look for three things: a pct you can now delete, a missing np you could add, and — if your rua points off-domain — whether the receiving service has moved its authorisation record to the new name.

Before you touch it, make sure there is exactly one record and that it carries a real p=, because those two faults are far more common than an outdated tag and far more damaging: check the record you already have.

⚠ This page describes a specification published in May 2026. Receiver behaviour lags specification by years, so for a while you are writing records that two generations of receiver will read differently. Where the two disagree, the safe record is the explicit one.

Connect a domain to Yowl →