HostleloBlog
SavedSearch
Visit Hostlelo

Is Your DMARC Record Out of Date? What RFC 9989 Changed

RFC 9989 replaced the old DMARC rules in May 2026. Learn how to audit your record, swap pct for the new t tag, add np, and check report authorisation.

The short answer

RFC 9989, published in May 2026, replaced RFC 7489 as the DMARC standard. The pct tag is now historic, along with rf and ri, and a new t tag (y or n) handles testing by applying one policy level below the one you publish. Look up your record with dig, remove outdated tags, consider np for non-existent subdomains, and read your aggregate reports before you tighten p.

Reading options

On this page

If your DMARC record was written before May 2026, it may still work, but parts of it now follow rules that no longer exist. RFC 9989 replaced the old DMARC document (RFC 7489), dropped the pct tag, and added a new t tag for testing. This guide shows you how to read your current record line by line and update it in about 30 minutes.

Here is the surprising part. The old pct tag, the "apply my policy to only 25 percent of failing mail" dial, was quietly unreliable for years. The new standard says so in plain words: "Operational experience showed that the "pct" tag was usually not accurately applied, unless the value specified was either 0 or 100 (the default), and the inaccuracies with other values varied widely from one implementation to another."

By the end, you will have a clean record that matches the new standard, and you will know what to read before tightening it.

What RFC 9989 actually is

DMARC is a small DNS record that tells receiving mail servers what to do with mail that claims to come from your domain but fails the SPF and DKIM checks. It also asks those servers to send you reports about who is sending mail as you.

Since March 2015, the rulebook was RFC 7489, an Informational RFC rather than an official IETF standard. In May 2026, the IETF published RFC 9989 as a Proposed Standard. It obsoletes RFC 7489 and RFC 9091. A companion document, RFC 9990, now defines the aggregate reports.

Think of it like a building code update. Your house does not fall down, but the next inspector reads the new code, and a few things you installed years ago are now outdated.

The changes that matter most for a small business record are these:

  • The pct tag is gone. RFC 9989 updates the IANA tag registry to list it as "historic".
  • The rf and ri tags are also marked historic, so they no longer do anything you can count on.
  • A new t tag (short for "testing") takes over the useful part of pct.
  • The np tag, for subdomains that do not exist, is now part of the main standard.
  • Receivers find your record with a "DNS Tree Walk" instead of relying on a public list of domain suffixes.
  • The option to set a maximum report size inside the report address has been removed.

Why this matters: if your record says p=reject; pct=10, you may think only one in ten failing messages gets rejected. A receiver following RFC 9989 has no pct instruction to follow, so you should treat that record as a plain p=reject.

Before you start

  • Login to wherever your DNS is hosted: your registrar, your DNS provider, or cPanel if your host manages DNS there.
  • A terminal with dig (Linux or macOS), or Command Prompt with nslookup (Windows).
  • Your domain name. In this guide we use example.com; swap in your own.
  • Access to the mailbox that receives your DMARC aggregate reports, if you have one.
  • About 30 minutes for the audit, plus several weeks of reading reports before any change to p.
  • Risk level: low for cleaning up tags, medium if you change p or remove testing mode.

Heads up: before you edit anything, save the current record text in a plain text file with today's date. The cPanel Zone Editor documentation describes editing, adding and deleting records, but it does not describe a zone export button, so a copy you made yourself is your undo button. If your DNS host offers a zone export or download, use it as well.

Step by step: audit your DMARC record

Step 1: Look up the record that is live right now

Always start from what the world sees, not from what you remember typing. DMARC records live as TXT records at a fixed name: _dmarc followed by your domain, so _dmarc.example.com.

This command asks DNS for the TXT record at that name and prints only the value.

dig +short TXT _dmarc.example.com

You should see something shaped like this. The values below are example values only.

"v=DMARC1; p=quarantine; pct=25; rua=mailto:dmarc@example.com; ri=86400"

On Windows, this command does the same lookup with nslookup and its -type= option.

nslookup -type=TXT _dmarc.example.com

Look for the v=DMARC1 text in the answer section; that is your record value.

Save the exact output into your backup text file now.

If you get nothing back, you have no DMARC record at that name. That is a setup job, not an audit, so follow our SPF, DKIM and DMARC setup guide first and come back here later.

Step 2: Check that there is exactly one record

Look at the output again. If you see two lines that both start with v=DMARC1, you have a real problem.

RFC 9989 describes it directly: if multiple DMARC records are returned for one name, they are all discarded. Two records do not add up. They cancel each other out, and receivers behave as if you published nothing at that name.

This usually happens when someone adds a new record instead of editing the old one. Merge them into one and delete the extra.

Step 3: Read each tag against the current list

RFC 9989 lists the valid tags. Here they are with their plain meaning and their default, which is the value a receiver assumes when you leave the tag out.

  • v: version. Required, must be first, and the only allowed value is DMARC1. If it is missing, not first, or wrong, the whole record is ignored.
  • p: your policy for mail that fails DMARC: none, quarantine or reject. If a valid record has no p, it is treated as p=none.
  • sp: policy for existing subdomains. If absent, p applies.
  • np: policy for subdomains that do not exist in DNS. If absent, sp applies, or p if there is no sp.
  • t: testing mode, y or n. Default n.
  • rua: where aggregate reports go. If missing, receivers must not send you aggregate reports.
  • ruf: where per-message failure reports go.
  • fo: failure report options. Default 0, and it is ignored unless ruf is also present.
  • adkim: DKIM alignment mode, r (relaxed) or s (strict). Default r.
  • aspf: SPF alignment mode, r or s. Default r.
  • psd: marks a public suffix domain. Default u. A normal business domain does not need it.

Now compare your record. Anything else, such as pct, rf or ri, is outdated. RFC 9989 says unknown tags must be ignored, so an extra tag will not break the record, but it can mislead the next person who reads it.

Quick tip: adkim and aspf control how closely the SPF or DKIM domain must match the From domain. If you never set them on purpose, leave them out and keep the relaxed default.

Step 4: Replace pct with t, if you used it as a rollout dial

Under the old rules, pct accepted any whole number from 0 to 100. The idea was a gradual rollout: ask receivers to apply your stricter policy to only a percentage of failing mail. In practice, only 0 and 100 behaved consistently.

The value 0 took on a special meaning. Some intermediaries and mailbox providers treated it as a signal to rewrite the From line on forwarded mail. RFC 9989 kept that useful behaviour and gave it a cleaner switch: t=y is meant to work like the old pct=0, and t=n like the old pct=100.

Here is what t=y asks of a receiver, according to RFC 9989:

  • With p=quarantine; t=y, failing mail should be treated as none.
  • With p=reject; t=y, failing mail should be treated as quarantine.
  • With p=none, t has no effect.
  • t never changes reporting. You still get the same reports.

In plain words, t=y means "apply one level below what I wrote, I am still testing." It is a single step down, not a percentage.

Made-up example: Amira runs a small online flower shop. Two years ago a guide told her to publish p=quarantine; pct=25 and raise the number later. She never did. Under RFC 9989 there is no 25 percent: her real choices are full quarantine, or quarantine with t=y.

This is the record before the change, using example values.

v=DMARC1; p=quarantine; pct=25; rua=mailto:dmarc@example.com; ri=86400

This is the record after the change, if you are still testing and your reports are not clean yet.

v=DMARC1; p=quarantine; t=y; rua=mailto:dmarc@example.com

This is the record after the change, if your reports show all your real mail passing and you are ready for quarantine to apply in full.

v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com

Notice that ri=86400 is gone too. The ri tag (the requested report interval) is historic. RFC 9990 says a reporting period typically covers a single UTC day anyway.

Heads up: if your old record had pct=100, or no pct at all, you were already getting full enforcement. Just delete the pct tag. Do not add t=y "to be safe", because that steps your policy down a level.

But what if some receivers have not updated yet? A receiver that does not know t will skip it, because unknown tags are ignored. So only publish a p value you can live with at full strength.

Step 5: Add np if you have unused subdomains

Someone faking your domain can invent subdomains like billing.example.com or secure-login.example.com. If those names do not exist in your DNS, a query for them returns NXDOMAIN, the DNS answer for "this name does not exist". RFC 9989 calls these non-existent domains.

The np tag sets the policy for exactly those names. It does not touch your main domain or subdomains that really exist.

This record keeps the main domain in testing while asking receivers to reject mail from made-up subdomains.

v=DMARC1; p=quarantine; t=y; np=reject; rua=mailto:dmarc@example.com

Why this matters: nobody legitimately sends mail from a name that does not exist, so np=reject is low risk for most small businesses. Note that t=y steps it down one level too, to quarantine, until you remove t=y.

Quick tip: before you add np=reject, list the subdomains you actually send from, such as mail.example.com or news.example.com. Those exist, so they fall under sp or p, not np. Make sure each one really exists in DNS.

How do receivers find the policy for a subdomain? RFC 9989 checks the sending domain itself first, then walks up the DNS tree one label at a time, using no more than eight DNS queries. A subdomain without its own record ends up using your main domain's record.

Step 6: Check the authorisation for outside report addresses

Many people send reports to a DMARC reporting service. That means the rua address is on someone else's domain, for example mailto:reports@dmarc.example.net while your domain is example.com.

RFC 9990 protects that outside company from being flooded with unwanted reports. When the report address is on a different organisational domain, the receiver builds a special name and looks for a TXT record there. The name is your domain, then _report._dmarc, then the host from the report address.

For our example, this command checks that authorisation record.

dig +short TXT example.com._report._dmarc.dmarc.example.net

A working authorisation returns at least one record that starts with v=DMARC1, like this example.

"v=DMARC1"

If the answer is empty, RFC 9990 says the receiver must ignore that report address. You would get no reports there at all, even though your own record looks perfect.

You cannot fix this from your side, because the record lives in the reporting service's DNS. Ask them to publish it. RFC 9990 also allows a wildcard like *._report._dmarc.example.net that accepts reports for any domain.

Skip this step if your report address is on your own domain, such as dmarc@example.com.

Step 7: Edit the record in your DNS panel

Now publish your cleaned-up record. Edit the existing record. Do not add a second one, or you will hit the problem from Step 2.

In cPanel, open cPanel > Domains > Zone Editor. Click Manage next to your domain, find the TXT record for _dmarc.example.com, and click Edit. Paste the new value into the Record box and click Save Record.

Heads up: the cPanel documentation warns that the Record text box "will accept invalid data". cPanel will not catch a typo for you, so copy the record from your text file instead of typing it by hand.

On other DNS hosts, the idea is the same: find the TXT record for the _dmarc name, edit its value, and save. Check your provider's own help page for the exact buttons.

If your mail is sent from a website, such as WordPress contact forms, and your DNS lives in cPanel, our guide to WordPress email on the same domain in cPanel explains the routing settings that often confuse people at this point.

Step 8: Read your reports before you enforce

Cleaning up tags is safe. Changing p, or removing t=y, is where real mail can get hurt.

Aggregate reports, as defined in RFC 9990, are XML files with a root element called feedback. They should arrive compressed with GZIP. Each one typically covers a single UTC day and lists records grouped by sending IP address, result and authentication identifiers.

Look for two new items. A testing value in the published policy section shows the t value the receiver saw. A policy override reason of policy_test_mode means the receiver held back your full policy because of t=y, which shows it understood the tag.

RFC 9989 recommends starting at p=none and fixing every legitimate sender that fails before you move to enforcement. It adds that this "may take many months" for some domains. For domains whose users post to mailing lists, it is stronger: such domains "SHOULD NOT" publish p=reject, and any that want to should first run p=none for at least a month, then p=quarantine for an equally long period, and compare the results.

For a walk through the XML itself, see how to read DMARC aggregate reports.

How to check it worked

Resolvers may keep serving the old answer from cache until its TTL (time to live) runs out. Give it at least that long, then check.

This command shows the live record again so you can compare it with your text file.

dig +short TXT _dmarc.example.com

You should see one line only, starting with v=DMARC1, with no pct, rf or ri tags. For example:

"v=DMARC1; p=quarantine; t=y; np=reject; rua=mailto:dmarc@example.com"

This command shows the record with its TTL, the number of seconds resolvers may cache it.

dig +noall +answer TXT _dmarc.example.com

Then confirm these points:

  • v=DMARC1 is the first tag, in the only DMARC record at that name.
  • Your p value is one you would accept at full strength.
  • If rua points outside your domain, the Step 6 lookup returns v=DMARC1.
  • Within a day or two, reports keep arriving, and their published policy section matches what you set.

Troubleshooting

Reports stopped after I changed the record

Symptom: the rua mailbox goes quiet. Likely cause: a typo such as a missing mailto:, or two records now exist and both are discarded. Fix: run the Step 1 lookup and compare the rua value letter by letter with your backup.

No reports ever arrive at my reporting service

Symptom: your own record looks right, but the outside service shows no data. Likely cause: the authorisation TXT record at example.com._report._dmarc.<their host> is missing. Fix: run the Step 6 lookup. If it is empty, send the result to the service and ask them to publish the record.

dig shows my record split into several quoted parts

Symptom: output like "v=DMARC1; p=none; " "rua=mailto:dmarc@example.com". Likely cause: a long record stored in chunks. Fix: usually nothing, because RFC 9989 tells receivers to join the parts in order. Check that no semicolons were lost at the joins.

The record seems to be ignored completely

Symptom: reports show no policy, or a checker says there is no valid DMARC record. Likely cause: v=DMARC1 is not the first tag, is misspelled, or uses the wrong case. RFC 9989 says the value is case sensitive and the record is ignored if the version tag is not first. Fix: make sure the record begins exactly with v=DMARC1;.

My subdomain is not covered the way I expected

Symptom: mail from news.example.com is treated differently from what you planned. Likely cause: the subdomain exists, so np does not apply to it, or the subdomain has its own _dmarc record that overrides the parent. Fix: look up _dmarc.news.example.com too. If it has its own record, that one wins, and its own p applies.

I added t=y and nothing seems different

Symptom: you expected a visible change after adding t=y. Likely cause: your policy is p=none, where t has no effect, or the change has not passed the TTL yet. Fix: check your p value. Then look for policy_test_mode in the next reports to confirm receivers read it.

A few notes from experience

The ruf tag deserves a second look while you are in there. RFC 9989 points out that failure reports can include actual message content, which makes those addresses more attractive targets. If nobody reads your ruf mailbox, removing ruf is a reasonable choice.

A receiver does not have to obey your policy. RFC 9989 says final handling is up to the receiving server, and that receivers "SHOULD NOT reject messages solely because of a published policy of "reject"". Receivers vary, so read your reports to see what actually happened; a receiver that overrides your policy should say so there.

If you are tidying up email security this week anyway, setting up MTA-STS and TLS-RPT is a good next job. It works on a different problem: protecting mail in transit to your domain.

Ask your host or a developer for help if you have many sending services, or if you are thinking about p=reject for a domain where staff use mailing lists.

The one message worth forwarding

Copy this to whoever manages your DNS or email:

"Hi, DMARC has a new standard (RFC 9989, May 2026) that replaces RFC 7489. Could you check our record at _dmarc.example.com? Please make sure there is only one record, remove the old pct, rf and ri tags, and use t=y instead of pct if we are still testing. If our rua goes to an outside reporting service, please confirm their example.com._report._dmarc authorisation record exists. Please keep a copy of the current record before editing, and do not change p until we have reviewed recent reports together. Thanks."

The short version: read your record as if pct were not there, because under the new standard it is not.

Reader questions

Do I have to update my DMARC record right away?

No. RFC 9989 tells receivers to ignore unknown tags, so an old record will not suddenly break. Updating it simply makes sure the record means what you think it means under the current standard.

Is there a replacement for pct=50 or other partial values?

No. RFC 9989 keeps only the useful behaviour of pct=0 and pct=100, through t=y and t=n. There is no tag for applying a policy to a percentage of failing mail.

Why do my reports arrive at a different mailbox than my rua address?

If your rua points to an outside reporting service, RFC 9990 lets that service replace the address through its authorisation record, as long as it keeps the same destination host. Ask the service which mailbox it set.

Which document defines DMARC aggregate reports now?

RFC 9990, published in May 2026 alongside RFC 9989. It defines the XML report format, the root element called feedback, and the check for report addresses on other domains.

Does RFC 9989 still use the Public Suffix List?

Not for finding your policy. RFC 9989 uses a DNS Tree Walk that queries DNS labels from the sending domain upwards, with a limit of eight queries. The RFC notes that receivers still on RFC 7489 may get different answers in some cases.

Does p=none change how my mail is delivered?

It should not. RFC 9989 says a discovered policy of p=none must not modify existing mail handling processes, so it is a safe place to start collecting reports.

Sources & further reading

  1. RFC Editor: RFC 9989 information page
  2. RFC 9989: Domain-Based Message Authentication, Reporting, and Conformance (DMARC)
  3. RFC 9990: DMARC Aggregate Reporting
  4. cPanel documentation: Zone Editor
  5. BIND 9 manual pages: dig
  6. Microsoft Learn: nslookup
  7. Microsoft Learn: nslookup set type

Originally published . About our editorial updates.

Your next project deserves a better foundation.

Explore hosting built for your next chapter.

Explore hosting

Find your next answer.

Search published guides and articles.

Ctrl / ⌘ K to open · Esc to close