# DMARCbis (RFC 9989): What Changed and Must You Edit Records?

Source: https://srvscripts.com/guides/dmarcbis-rfc-9989-changes/
Updated: 2026-10-06
Publisher: srvScripts (https://srvscripts.com/)

**Short answer:** DMARCbis was published in May 2026 as RFC 9989 (the protocol), RFC 9990 (aggregate reports) and RFC 9991 (failure reports), replacing RFC 7489. Records still start with `v=DMARC1`, so existing records keep working. The changes: new `np`, `psd` and `t` tags; `pct`, `rf` and `ri` are now historic; and the Public Suffix List is replaced by a DNS “tree walk” to find the organizational domain. Most domains need no change. Edit only if you rely on `pct` values other than 100, or want `np` to protect non-existent subdomains.

Checked against the text of RFC 9989, 9990 and 9991 (linked below) on 6 October 2026. This page explains records rather than server commands; the `dig` lookups shown are standard and were not specific to our lab servers.

## What was published

| RFC | Title | Replaces |
| --- | --- | --- |
| RFC 9989 | DMARC (the protocol, record format and policy discovery) | RFC 7489 and RFC 9091 (the experimental PSD DMARC) |
| RFC 9990 | DMARC Aggregate Reporting | Reporting parts of RFC 7489 |
| RFC 9991 | DMARC Failure Reporting | Failure-report parts of RFC 7489; updates RFC 6591 |

RFC 7489 was an Informational RFC published through the Independent Submissions stream. The new documents are IETF Standards Track. For admins, that mainly means the rules are now settled and mailbox providers and software vendors will move towards them over time. Expect a period where some receivers follow RFC 7489 and some follow RFC 9989.

## Tag changes at a glance

| Tag | Status in RFC 9989 | What it does |
| --- | --- | --- |
| v | Unchanged | Still DMARC1, still must be the first tag |
| p | Now RECOMMENDED, not required | A record without p is treated as p=none |
| sp | Active | Policy for existing subdomains |
| np | New (imported from RFC 9091) | Policy for non-existent subdomains (names that return NXDOMAIN) |
| psd | New | y = this is a public suffix domain, n = this is an organizational domain, u = unknown (default) |
| t | New | Test mode: t=y asks receivers to apply one level less than the policy |
| adkim, aspf | Active | Relaxed (default) or strict alignment |
| rua, ruf, fo | Active | Report addresses and failure-report options |
| pct | Historic (removed) | Sampling percentage |
| rf | Historic (removed) | Failure-report format |
| ri | Historic (removed) | Aggregate report interval |

Both RFC 7489 and RFC 9989 tell receivers to ignore tags they do not know. That is why the new tags are safe to publish today: an old receiver skips `np` or `t`, and a new receiver skips `pct`.

## np: protect subdomains that do not exist

Spammers like to forge random subdomains such as `invoice.example.com` that were never created. With `np` you can set a strict policy for those names without touching real subdomains:

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

A “non-existent” domain here means the receiver gets NXDOMAIN for that name. If `np` is absent, `sp` applies, and if that is absent too, `p` applies. Before using `np=reject`, make sure every subdomain that sends mail exists in DNS. A subdomain used only as a From address with no records at all would count as non-existent.

## pct is gone: what t=y does instead

RFC 9989 explains that receivers rarely applied `pct` accurately except for the values 0 and 100. `pct=0` had become a signal to mailing lists and forwarders to rewrite the From header, which domain owners found useful while testing a stricter policy. The new `t` tag keeps that use:

- `p=quarantine; t=y` asks receivers to apply `none` to failing mail.

- `p=reject; t=y` asks receivers to apply `quarantine`.

- `t=n` (the default) means apply the policy as written.

- `t` has no effect on reports, and none on a `p=none` policy.

What to do with existing records:

| Your record today | Action |
| --- | --- |
| pct=100 or no pct | Nothing. 100 was the default. You can remove pct=100 to tidy up. |
| pct=0 while testing quarantine or reject | Add t=y. During the transition you can publish both: new receivers ignore pct, older ones ignore t. |
| pct=10 to pct=90 as a gradual ramp | Stop relying on it. New receivers ignore it and apply the full policy. Use your aggregate reports to decide, then move to the full policy or use t=y. |
| rf=afrf or ri=86400 | Harmless, but obsolete. Remove when convenient. Aggregate reports typically cover one UTC day anyway. |

Google’s BIMI help page still says `pct` must be 100. Leaving `pct` out has the same meaning under both the old and the new rules, so removing `pct=100` does not break BIMI.

## The tree walk replaces the Public Suffix List

Under RFC 7489, receivers used a Public Suffix List (PSL) to decide that the organizational domain of `mail.example.co.uk` is `example.co.uk`. Different receivers used different copies of the list, and RFC 7489 did not say which one. RFC 9989 replaces this with DNS queries:

- Look for `_dmarc` at the exact From domain. If a valid record is there, it is the policy to apply.

- If not, remove labels from the left one at a time and query `_dmarc` at each level, up to the top-level domain. Names with more than eight labels are shortened first, so one walk never needs more than eight queries.

- A record with `psd=n` stops the walk and marks the organizational domain. A record with `psd=y` marks a public suffix, so the organizational domain is one label below it.

- Otherwise the record found at the name with the fewest labels is the organizational domain.

For alignment, receivers run the same walk for the SPF and DKIM domains. Relaxed alignment passes when the From domain and the authenticated domain have the same organizational domain.

For an ordinary domain such as `example.com` with one record at `_dmarc.example.com`, the result is the same as before. Differences appear in unusual setups: a subsidiary that publishes its own record on a subdomain, or a company that runs many independently managed subdomains. RFC 9989 notes that strict alignment plus an explicit DMARC record for every From domain avoids any difference between old and new receivers.

You only need `psd` if you operate a public suffix (a registry, or a platform that hands out customer subdomains as separate organizations) or if you deliberately want a subdomain treated as its own organizational domain. Normal businesses can leave it out.

## Other changes worth knowing

- **p=reject guidance.** RFC 9989 says domains whose users post to mailing lists SHOULD NOT publish `p=reject`, and should first run `p=none` for at least a month, then `p=quarantine` for as long, comparing reports. Domains with `p=reject` MUST NOT rely only on SPF and must DKIM-sign.

- **Receivers may soften reject.** Receivers MUST NOT reject solely because of `p=reject`. Without other evidence they should treat it as quarantine. Do not expect every failing message to bounce.

- **Report size suffix removed.** The old `!10m` size limit after a `rua` address is obsolete syntax that reporters should ignore.

- **Reports to every address.** A report SHOULD be sent to each listed `rua` URI, rather than receivers supporting at least two.

- **External report addresses still need authorization.** If `rua` points to another domain, that domain must publish a record such as `example.com._report._dmarc.reports.example.net TXT "v=DMARC1;"` (RFC 9990).

## Check your record

Look at what is published:

```
dig +short TXT _dmarc.example.com
```

Then confirm: exactly one record, starts with `v=DMARC1`, has a `p` tag (still the clearest way to state intent), and a `rua` address you actually read. Our [DMARC Checker](/tools/dmarc-checker/) parses the record and our [DMARC Report Analyzer](/tools/dmarc-report-analyzer/) reads the aggregate XML. If you want to add `np` or `t`, write the record by hand or start from our [DMARC Record Generator](/tools/dmarc-record-generator/) and add the tags.

After a change, wait at least a full day of reports before judging the effect, because aggregate reports usually cover a whole UTC day.

**Official documentation:** [RFC 9989: DMARC](https://www.rfc-editor.org/rfc/rfc9989.html) · [RFC 9990: DMARC Aggregate Reporting](https://www.rfc-editor.org/rfc/rfc9990.html) · [RFC 9991: DMARC Failure Reporting](https://www.rfc-editor.org/rfc/rfc9991.html)

**Related:** [DMARC Checker](/tools/dmarc-checker/) · [DMARC Record Generator](/tools/dmarc-record-generator/) · [DMARC Report Analyzer](/tools/dmarc-report-analyzer/) · [SPF, DKIM and DMARC in cPanel DNS: Setup and Checks](/guides/spf-dkim-dmarc-cpanel-dns/) · [Microsoft 365 SPF DKIM DMARC: Secure Exchange Online Setup](/guides/microsoft-365-spf-dkim-dmarc-exchange-online/)

**See also:** [BIMI VMC vs CMC: Requirements, DMARC and Which Inboxes Show Logos](/guides/bimi-vmc-vs-cmc/) · [Gmail and Yahoo Bulk Sender Requirements: 2026 Host Checklist](/guides/gmail-yahoo-bulk-sender-requirements/)

## Frequently asked questions

### Do I need to change my DMARC record for RFC 9989?

Usually not. v=DMARC1 records stay valid. Change it only if you use pct values other than 100, want np for non-existent subdomains, or want to drop the obsolete rf and ri tags.

### Is the DMARC version now DMARC2?

No. RFC 9989 keeps v=DMARC1 as the only valid version value, and it must still be the first tag.

### What replaces pct=0?

The t=y test-mode tag. It asks receivers to apply one level below your policy, the same way pct=0 was used in practice.

### What does np=reject do?

It sets the policy for subdomains that do not exist in DNS (NXDOMAIN). Real subdomains still follow sp, or p when sp is absent.

### Will old receivers break on the new tags?

No. RFC 7489 already required receivers to ignore unknown tags, so np, psd and t are skipped by older implementations.

### Do I need psd=n on my domain?

Normally no. It is for domains that want to be treated as their own organizational domain or for public suffix operators, who use psd=y.
