RFC 9989: DMARC Deleted Three Tags and 46% Still Publish One

RFC 9989 made DMARC a real internet standard in May 2026 and deleted three tags on the way: pct, ri and rf. Of 173 live DMARC records we resolved from real sending domains on August 15, 2026, 79 still publish at least one of them. Almost none of those domains will notice, because 66 of the 68 records carrying pct set it to 100, which did nothing before and does nothing now.

The exception is the record a careful sender is most likely to have published. A policy of quarantine or reject with a pct below 100 was a deliberate ramp, applying enforcement to a slice of failing mail. That slice is gone at any receiver following the current standard, and the record got stricter without anyone editing DNS.

This guide covers every RFC 9989 change that reaches a published record, with the section numbers to check each one against.

RFC 9989 replaced three documents, not one

RFC 9989 obsoletes RFC 7489 and RFC 9091, and it is standards track rather than informational. That status change is the substance: DMARC spent eight years as an informational document describing what an existing deployment did, and it is now a specification receivers are expected to conform to.

Two companion documents split off the reporting half, and both also obsolete RFC 7489. RFC 9990 covers aggregate reports, the ones that arrive as XML at your rua address. RFC 9991 covers failure reports, the per-message ones at ruf. RFC 9091 was the experimental extension for public suffix domains, and its psd tag survives in the main specification.

A page that cites RFC 7489 for anything DMARC in 2026 is citing a document that three separate RFCs have replaced. That includes most vendor documentation, and it includes Google's and Microsoft's own sender guidance, which still describes DMARC in RFC 7489 terms.

Three tags are registered historic, which is not the same as unknown

RFC 9989 created an IANA registry for DMARC tags and registered pct, ri and rf with status historic. The RFC defines that status in its own words: the tag "is considered deprecated and is not expected to be in use in any current implementation."

TagWhat it didStatus now
pctSampling rate, the share of failing mail the policy applied toHistoric
riAggregate reporting interval, in secondsHistoric
rfFailure reporting formatHistoric

Historic is a different state from unknown, and a checker has to treat it as one. These three have names, a documented history, and in pct's case a stated reason for going. An unknown tag is something nobody has defined. Both are ignored by a conforming receiver, and neither may invalidate a record, but only one of them is worth telling a publisher about by name.

What a receiver does with any of them is settled in section 4.8: "Unknown tags MUST be ignored. Syntax errors in the remainder of the record MUST be discarded in favor of default values (if any) or ignored outright." So pct=abc and pct=50 are equally inert at an RFC 9989 receiver, and a checker that reds a record over either one is reporting a fault that no receiver acts on.

Only one of the three deletions changes what happens to your mail

pct is the tag whose removal moved live mail, and it moved it in the strict direction. Under RFC 7489, p=reject; pct=25 asked receivers to reject a quarter of failing messages and apply the next policy down to the rest. At an RFC 9989 receiver the tag is ignored and p=reject applies to every failing message.

Nobody edited DNS for that to happen. The record is identical and the outcome is not, which is the opposite of how a deprecation usually feels.

Both behaviours are live at once, which is the part worth planning around. Google and Microsoft have not committed to RFC 9989 semantics and their sender documentation still describes sampling, so the same record can be sampled at one receiver and fully enforced at another on the same day.

That also sets the order of operations for fixing it. Deleting a sub-100 pct raises enforcement at every receiver still honouring it, so the safe sequence is to reach the enforcement level you actually want first, then delete the tag. Doing it the other way round is a step up in enforcement disguised as a cleanup.

ri and rf are quieter. ri asked for a reporting interval in seconds, and receivers overwhelmingly sent daily reports regardless of what it said. rf named a failure report format, and afrf was the only value anyone published. Removing either changes nothing about your mail.

The p tag is no longer required, and two habits follow it out

RFC 9989 lists p as "RECOMMENDED for DMARC Policy Records" rather than required, and the formal grammar names only the version tag as mandatory. A record with no p is not a syntax error.

Two rules that older checkers enforce are gone with it, and both of them reject records that every receiver accepts:

  • Tag order after v is unconstrained. RFC 7489 pinned p to second place, and Google's publisher documentation still says so. RFC 9989 does not.
  • Tag values are case-insensitive. They are bare ABNF literals, so p=Reject is valid.

A missing p is still worth flagging, because a record with no policy is a real consequence for the domain. It is just not a syntax error, and the difference decides what the reader is told to do.

A record is discarded for exactly two reasons, and they are different states

Three failure states have to stay apart, because collapsing them is how a checker tells an unprotected domain it merely has a typo. This is the part almost no explainer covers, and it is the part that decides whether a tool is right.

The version tag is wrong. Absent, not first, or not the exact case-sensitive DMARC1. Section 4.7: "the entire record MUST be ignored." Policy discovery carries on past it, so the name may still be covered by a record further up the tree.

The policy is unusable. p absent or unrecognised, or an sp or np that is present and invalid. Section 4.10.1 puts all three in one branch, and the outcome depends on rua: with at least one syntactically valid reporting URI "the Mail Receiver MUST act as if a record containing p=none was retrieved", and without one the receiver applies no DMARC processing to the message. That second outcome is worse than p=none and worse than publishing nothing at all.

Everything else is repaired in place. Section 4.8 again: a bad fo, a bad t, a historic tag, an unknown tag. None of them may make a record invalid.

The clause people miss sits in the second of those. A typo in sp discards a perfectly good p=reject wholesale. v=DMARC1; p=reject; sp=quarintine protects nothing, and a checker that reports the p it can read hands a green badge to an open domain. If you publish sp or np, they are load-bearing in a way p alone is not, and subdomain policy is where that bites hardest.

What 173 live DMARC records actually publish

We keep a corpus of DMARC records published by real sending domains, resolved from dns.google over DoH, as the no-false-positive control for our own parser: every record in it carries real mail, so any failure our analyzer raises against one is wrong until proven otherwise. Here is what the tags look like, as captured on August 15, 2026.

TagRecords carrying itShare
At least one historic tag7946%
pct6839%
pct set to 1006638%
pct below 10021%
ri169%
rf116%
All three historic tags1under 1%

Two things stand out, and the second is why the first does not matter much. Nearly half the corpus carries a deleted tag, which sounds alarming until you look at the values: 66 of the 68 pct tags are set to 100, a value that applied the policy to everything before RFC 9989 and applies it to everything now. The ri values are 3600, 14400 and 86400 seconds, and every single rf value is afrf.

The exposure is one record out of 173: a p=reject; pct=25 that asked for a quarter and now gets all of it. That is the whole practical risk of this deletion, and it is concentrated in the senders who were being careful.

This corpus is a set of domains we track rather than a random sample of the internet, so read the shares as what real published records look like and not as a measurement of every domain. For the population figure, 48% publish a DMARC policy at all across the Unspam 2026 Email Deliverability Benchmark.

RFC 9990 section 4 requires a receiver to verify that an external reporting destination has agreed to receive your reports, and to drop any URI it cannot confirm. RFC 9991 section 5 repeats it for ruf. RFC 7489 said such checks "are to be taken"; the new text makes it a MUST and deletes the escape hatch that let a receiver skip the check in favour of a local allowlist.

In practice this means a rua pointing at a vendor's domain needs a record in the vendor's zone authorising your domain to send there. Most reporting vendors publish that automatically when you add a domain, so this is usually a fact about a setup you did not do rather than a change to one you did.

There is a separate trap in the same tag that predates RFC 9989 and still catches people. The record grammar uses two different separators: semicolons separate tags, commas separate URIs inside one tag. So rua=mailto:a@example.com; mailto:b@example.net is not a two-address list. It is one rua tag followed by a bare term that is not tag=value, and the second address receives nothing. A checker built from per-tag regular expressions cannot see that, because each expression only asks whether its own tag appears somewhere.

BIMI still cites RFC 7489, and that is correct

The BIMI specification disagrees with RFC 9989 about pct on purpose, and both statements are current. RFC 9989 made the tag historic in May 2026. The BIMI draft published the same month still cites RFC 7489, and its section 7.1 still blocks a logo when a p=quarantine record carries a pct that is not 100.

So a domain can hold a record that is perfectly modern under RFC 9989 and still fails the BIMI check over a tag DMARC no longer has. Anything about BIMI is cited to a draft revision and never to an RFC, because there is no BIMI RFC: the current revision is draft-brand-indicators-for-message-identification-14, dated 1 May 2026.

This is the kind of detail that gets flattened when a tool shares one DMARC parser between features. The BIMI path needs its own pct check that survives an RFC 9989 parser dropping the tag on the floor.

What to do with your record this week

Read your record before changing it, because three of these checks depend on values you may not remember publishing. Our DMARC record checker parses to the RFC 9989 grammar and sorts tags into active, historic and unknown, so a deleted tag is reported as an advisory rather than an error.

  1. Look for a pct below 100. If you find one and your policy is quarantine or reject, your record is already stricter than you think at some receivers. Decide the enforcement level you want, get there, then delete the tag.
  2. Check sp and np character by character. A typo in either discards the whole record. If you do not need a different subdomain policy, not publishing them is safer than publishing them approximately.
  3. Delete ri and rf at your leisure. They are inert and always were close to it.
  4. Confirm your rua uses commas between addresses, not semicolons, if it lists more than one.
  5. Leave pct=100 alone unless you are already editing. It is noise, not a fault.

If you are building a record from scratch rather than auditing one, the DMARC record generator produces current syntax, and what DMARC does covers the mechanism behind the tags.

A tag nobody honours is not a broken record

The single most common mistake in the write-ups of this change is treating a historic tag as an error. It is not, and section 4.8 is unambiguous about why: a receiver ignores what it does not recognise and repairs what it cannot parse, rather than throwing the record away. A tool that reds a record over pct sends its user to edit working DNS, which is worse than saying nothing.

The one place a warning is earned is the narrow case above, and it earns it by being a statement about your mail rather than about your syntax: a sub-100 pct at enforcement means your policy now applies to messages it used to spare. Everything else in this deletion is housekeeping.

Run your domain through the DMARC record checker, then send a test message to see whether the policy you publish matches where your mail actually lands.

Frequently asked questions

What is RFC 9989?

RFC 9989 is the standards-track specification for DMARC, published in May 2026. It obsoletes RFC 7489, the informational document DMARC ran on for eight years, and RFC 9091, the experimental extension for public suffix domains. Two companion documents cover reporting: RFC 9990 for aggregate reports and RFC 9991 for failure reports, and both also obsolete RFC 7489.

Is pct still valid in DMARC?

No. RFC 9989 registered pct with status historic in the IANA DMARC tag registry, alongside ri and rf. The RFC defines historic as a tag that is deprecated and not expected to be in use in any current implementation. A receiver following RFC 9989 ignores it, because section 4.8 says unknown tags MUST be ignored and syntax errors elsewhere in the record MUST be discarded in favour of defaults rather than invalidating it.

Does removing pct change what happens to my mail?

Only if your pct was below 100 and your policy was quarantine or reject. Under RFC 7489, p=reject with pct=25 rejected a quarter of failing messages. At an RFC 9989 receiver the tag is ignored and the full policy applies to every failing message, with no edit to your DNS. A pct of 100 was a no-op before and is a no-op now.

Is the p tag still required in a DMARC record?

No. RFC 9989 lists p as RECOMMENDED for DMARC policy records rather than required, and the formal grammar names only the version tag as mandatory. Two things follow that older checkers get wrong: tag order after v is unconstrained, so p no longer has to come second, and tag values are case-insensitive, so p=Reject is valid.

What happens if my sp or np tag has a typo?

The whole record stops protecting you, even if p is perfect. Section 4.10.1 puts an invalid p, sp or np in one branch: with a syntactically valid rua the receiver must act as if p=none was retrieved, and without one it applies no DMARC processing to the message at all. A record like v=DMARC1; p=reject; sp=quarintine protects nothing, and a checker that reports the p it can read hands a green badge to an open domain.

Do I need to delete pct from my record?

Eventually, and in the right order. If your pct is below 100 and you are at quarantine or reject, deleting it raises enforcement at the receivers still honouring it, so reach the enforcement level you actually want first and delete the tag afterwards. If your pct is 100, it is inert either way and you can remove it whenever you next edit the record.

See where your campaign actually lands.

Start a free spam test Inbox placement test