Skip to content
correct.email
Email authentication

DMARC RFC 9989: what changed and what to do

What RFC 9989 changed in DMARC compared with RFC 7489: the DNS tree walk, new np, psd and t tags, removed pct, rf and ri, and what your record needs now.

By Exmoor Software8 min read

In May 2026 the IETF published DMARC as a Standards Track protocol in RFC 9989. It obsoletes RFC 7489, the 2015 specification most DMARC deployments were built on, and RFC 9091, an experiment for public suffix domains. Reporting moved into two companion documents: RFC 9990 (aggregate reports) and RFC 9991 (failure reports).

The short answer: your existing v=DMARC1 record keeps working. The version tag did not change, and receivers following either specification ignore tags they don’t know. Look closer if you use pct or publish DMARC only on subdomains.

The changes at a glance

AreaRFC 7489 (2015)RFC 9989 (2026)
StatusInformational, independent submissionIETF Standards Track
Documentsonethree: RFC 9989, 9990, 9991
Organizational domainPublic Suffix ListDNS Tree Walk
New tags—np, psd, t
Removed tags—pct, rf, ri
Size limit after a report URI (!10m)allowedobsolete, ignored
Version tagv=DMARC1v=DMARC1

RFC 7489 was not the product of IETF work: the Independent Submissions Editor published it as an Informational RFC (Appendix C.1), based on the work of DMARC.org, an industry consortium whose members included large mailbox providers. RFC 9989 is an IETF Standards Track document, developed in the IETF DMARC working group. It is also far more detailed about what domain owners should do (Section 5.1): aligned SPF and DKIM, a mailbox for reports, p=none first, then a decision about enforcement.

The DNS Tree Walk replaces the Public Suffix List

DMARC needs an organizational domain for two jobs: finding a policy when the From domain has no record of its own, and deciding whether two domains align in relaxed mode. RFC 7489 took it from a Public Suffix List — a list of suffixes such as com or co.uk — without saying which list or how often to refresh it.

RFC 9989 uses DNS queries instead (Section 4.10). For mail from news.mail.example.com with no record of its own, the receiver walks up the tree:

_dmarc.news.mail.example.com   ; the From domain itself
_dmarc.mail.example.com
_dmarc.example.com
_dmarc.com

Long names are shortened first, so a walk never takes more than eight queries.

  • Policy: the From domain’s own record wins (policy from p). Otherwise the record of its organizational domain applies — or, failing that, that of a public suffix domain: sp for subdomains that exist, np for subdomains that don’t, p when those tags are missing (Section 4.10.1).
  • Alignment: the organizational domain is the domain with the fewest labels on the path that publishes a DMARC record, unless a psd tag says otherwise (Section 4.10.2). With a record at _dmarc.example.com, both mail.example.com and bounce.example.com belong to example.com — the same answer the Public Suffix List gave.

For ordinary setups — one record at example.com, perhaps with overrides on some subdomains — both methods agree. The RFC notes that strict alignment and explicit records for every From domain avoid any difference between old and new receivers (Appendix C.3).

New tags: np, psd and t

np — non-existent subdomains

np sets the policy for subdomains that don’t exist in DNS (the query returns NXDOMAIN), such as a made-up billing-team.example.com in a phishing message. A name with any DNS record counts as existing (Appendix A.4). Without np, sp applies, then p.

_dmarc.example.com.  3600  IN  TXT  "v=DMARC1; p=quarantine; np=reject; rua=mailto:dmarc-reports@example.com"

Receivers still implementing RFC 7489 ignore np and fall back to sp or p.

psd — public suffix domains

psd=y is for operators of public suffixes, such as a top-level domain registry; RFC 9989 requires them to include it (Section 5.2). psd=n declares a domain to be an organizational domain of its own, for example a department that manages its own part of the namespace (Section 5.1.8). The default u means “use the tree walk”. If you own an ordinary domain, leave psd out.

t — testing mode

t=y asks receivers to apply one level less than the stated policy: quarantine is treated as none, reject as quarantine. Whoever checks DMARC — a receiver or an intermediary such as a mailing list — may also apply its own special handling, such as rewriting the From header. Reporting is unaffected, and t has no effect on p=none. Remove it, or set the default t=n, when you are ready to enforce.

Removed tags: pct, rf and ri

IANA now lists these tags as historic (Section 9.3). RFC 9989 no longer defines them, so receivers following it don’t act on them; receivers still implementing RFC 7489 do.

TagWhat it didWhat to do now
pctApplied the policy to a percentage of failing mailpct=0: use t=y. pct=100: delete. In between: see below
rfChose the failure report formatDelete; RFC 9991 defines the format
riRequested a report intervalDelete; receivers should report at least daily (Section 8)

Why pct went away

According to Appendix A.6, pct was rarely applied accurately unless it was 0 or 100, and implementations differed widely. pct=0, however, had become useful: some intermediaries and mailbox providers took it as a signal to rewrite the From header, which helped domain owners prepare for enforcement. t=y keeps that function under a clearer name and is meant to work like pct=0, while t=n corresponds to pct=100.

The effect matches: under RFC 7489, failing mail not selected by pct for reject was quarantined, and mail not selected for quarantine got normal handling — one level down, as with t=y.

If you use a value between 1 and 99

This is where the change can bite. With p=reject; pct=25, an RFC 7489 receiver rejects about a quarter of failing mail and quarantines the rest. An RFC 9989 receiver ignores pct and rejects all of it. Decide what you want:

  • Your reports are clean: remove pct and enforce fully.
  • You are not ready: add t=y, so updated receivers quarantine instead of rejecting while older ones keep following pct. Or step back to p=quarantine without pct.

During the transition you can keep pct=0 and t=y side by side: both kinds of receivers then apply one level less than p.

Reports moved to RFC 9990 and RFC 9991

The rua and ruf tags work as before; the reports are now specified separately:

  • Aggregate reports (RFC 9990) keep the XML format, with a clarified schema, one policy domain per report and the DKIM selector required for every reported signature (RFC 9990, Appendix C).
  • Failure reports (RFC 9991) may include headers or the whole failed message. RFC 9989 notes that most receivers refuse to send them for privacy reasons (Section 10.2).
  • External report addresses still need authorization: a TXT record v=DMARC1 at example.com._report._dmarc. followed by the report domain (RFC 9990, Section 4).

A size limit after a report URI, as in mailto:reports@example.com!10m, is obsolete and should be ignored. And instead of requiring support for at least two report addresses, RFC 9989 says a report should go to each address listed (Appendix C.7).

Stronger words about p=reject

Section 7.4, building on RFC 7960, spells out what p=reject does to forwarded mail, aliases and mailing lists:

  • Domains with p=reject must not rely on SPF alone and must sign with DKIM: forwarding breaks SPF, while DKIM usually survives.
  • Domains whose users may post to mailing lists should not publish p=reject. If they do, they should first run p=none for at least a month, then p=quarantine for as long, and compare the results.
  • Receivers must not reject mail solely because of p=reject; without other evidence they must treat failing mail as if the policy were quarantine.

The RFC admits that many receivers reject such mail anyway, and that mailing-list software works around it by rewriting the From address. For a domain sending only transactional and marketing mail, p=reject remains a sensible goal; where staff use mailing lists, weigh the trade-off.

Does my record need to change?

Your recordChange needed?
v=DMARC1; p=…; rua=… without pct, rf or riNo
Contains pct=100, rf=afrf or ri=86400No, but you can delete them
Contains pct=0Add t=y
Contains pct between 1 and 99Yes: remove it or add t=y
DMARC records only on subdomainsAdd a record at the registered domain
From domains with more than eight labelsPublish records at those exact names (Section 5.1.8)

Migration checklist

  1. Run the DMARC checker on your domain and every subdomain you send from. It follows the RFC 9989 tree walk and flags removed tags.
  2. Make sure the registered domain, such as example.com, has a DMARC record.
  3. Replace pct=0 with t=y (keeping both for a while is fine) and resolve any pct between 1 and 99.
  4. Delete rf, ri and size suffixes such as !10m.
  5. Consider np=reject: non-existent subdomains send no legitimate mail.
  6. Before p=reject, confirm that every legitimate source passes DKIM with a d= domain aligned to the From address — with the DKIM checker and a real message in the email header analyzer.
  7. Leave psd out unless you run a public suffix or a delegated part of the namespace.
  8. Keep reading aggregate reports. Receivers move to RFC 9989 at their own pace, and where the specifications differ, the reports show what each one did.

For the full rollout from p=none to p=reject, see How to configure DMARC correctly.

References