DMARC has been respecified. RFC 9989 — the work everyone has been calling DMARCbis — is now a Proposed Standard, and it obsoletes RFC 7489, the specification every DMARC article and generator on the internet was written against.
Your existing v=DMARC1 records keep working. But three things changed, and
almost nothing has caught up.
The pct tag was removed
This is the headline. Appendix A.6 of RFC 9989 is titled, unambiguously,
“Removal of the pct Tag.”
pct was how you rolled a policy out gradually — p=reject; pct=25 meant apply
reject to a quarter of failing mail. It was well-intentioned and awkward in
practice, because it made a policy probabilistic and made reports harder to
reason about.
It is replaced by a t tag with two values:
t=n— the default. Apply the stated policy.t=y— test mode. Receivers do not enforce; arejectpolicy is treated asquarantine, andquarantineasnone. Reports still flow.
That is a cleaner model. You publish the policy you actually intend and flip one tag when you are ready to enforce it, rather than ratcheting a percentage.
Two new tags arrived
np sets the policy for non-existent subdomains, independently of the
parent domain. Publishing np=reject is the cheapest possible win in DMARC:
subdomains you have never used and never will cannot be spoofed, and it costs you
nothing because there is no legitimate mail to break.
If you take one thing from this post, take that one.
psd flags whether a domain is a public suffix domain — y, n, or u
for unknown, which is the default and triggers the tree walk described next.
Most senders will never set it.
The Public Suffix List is replaced by a DNS tree walk
Working out a domain’s organisational domain — whether mail.brand.co.uk
belongs to brand.co.uk or something else — used to depend on the Public Suffix
List, a manually curated file.
RFC 9989 replaces that with a DNS tree walk: the receiver climbs the domain tree looking for a DMARC record. It is a better mechanism, and for most senders it is invisible. It matters if you operate a public suffix, or if you have been relying on quirks of PSL matching.
Almost every tool still emits the old format
Here is the practical bit. We ran a handful of well-known domains through our own
bulk domain auditor while testing it, and found large,
sophisticated senders still publishing pct= in their DMARC records.
That is not a failure on their part. It is what happens when a specification
changes and the entire ecosystem of generators, guides and monitoring dashboards
is written against the previous one. pct is still widely honoured by receivers,
so nothing breaks. It is simply no longer part of the standard.
Our own generator was doing it too. Until this week
the DMARC generator emitted pct=100 on every record,
because it was written against RFC 7489 like everything else. It now emits t=,
supports np=, and omits ri= unless you deliberately set it.
What to actually do
If you have no DMARC record, publish one. Start at p=none with a rua
address so reports flow, and add np=reject immediately — it protects unused
subdomains without touching your real mail.
If you have a record using pct, you are not broken and there is no urgency.
When you next touch it, drop pct and express the same intent with t.
If you are mid-rollout with pct=25, finish the rollout the way you planned.
Switching mechanism halfway is more disruptive than completing it.
If you build tooling, this is the moment to update. Being the generator that emits the current standard is a small differentiator that will not last long — everyone will catch up eventually.
The wider point
DMARC records are one of the few pieces of infrastructure most operators set once and never revisit. That is usually fine. It is also exactly why a specification change like this propagates so slowly: nobody has a reason to look at the record again.
Worth putting a calendar reminder on. Not because pct will stop working, but
because np=reject is sitting there, free, and almost nobody has it.