DMARC explained: policy, alignment and reports
Updated 2026-10-26 ยท Published 2026-10-08
Domain-based Message Authentication, Reporting and Conformance (DMARC) builds on SPF and DKIM. It lets the owner of the domain in the visible From address say what receivers should do when a message fails both, and it asks receivers to send back reports. Since May 2026 DMARC is an IETF standard in three parts: RFC 9989 for the protocol, RFC 9990 for aggregate reports and RFC 9991 for failure reports. They replace RFC 7489 from 2015. Existing records keep working.
What DMARC adds to SPF and DKIM
SPF and DKIM each authenticate a domain, but neither one has to be the domain in the From header. An SPF pass is about the envelope sender; a DKIM pass is about the d= domain of a signature. DMARC passes a message only when SPF or DKIM passes and the authenticated domain is aligned with the From domain. Without that link, an attacker could pass SPF with their own domain while showing yours to the reader. See SPF explained and DKIM explained.
Alignment
Alignment compares the authenticated domain with the From domain. In relaxed mode (the default) the two only need the same organisational domain, so mail.example.com aligns with example.com. In strict mode they must be identical. The tags aspf and adkim choose the mode for SPF and DKIM.
The record
A DMARC record is a TXT record at _dmarc.<domain> made of tag=value pairs separated by semicolons. The first tag must be v=DMARC1. Tags that a receiver does not know are ignored.
| Tag | Meaning |
|---|---|
p |
Policy for the domain: none, quarantine or reject. Recommended; a record without it counts as p=none. |
sp |
Policy for subdomains that exist. If absent, p applies to them as well. |
np |
Policy for subdomains that do not exist. If absent, sp (or p) applies. |
t |
t=y asks receivers to treat the policy as testing: one level weaker than published. |
rua |
Where to send aggregate reports. Any URI is allowed, but mailto: is the only kind receivers must support. |
ruf |
Where to send failure (forensic) reports. |
adkim, aspf |
Alignment mode, r (relaxed, default) or s (strict). |
psd |
For operators of public suffixes such as com; ordinary domains leave it out. |
If p, sp or np has an invalid value, receivers treat the record as p=none when it has a valid rua, and apply no DMARC at all otherwise (DMARC_INVALID_POLICY).
Where receivers look: the DNS tree walk
A receiver first queries _dmarc at the domain in the From address. If there is no record, it does not just jump to the registered domain. RFC 9989 section 4.10 defines a DNS tree walk: it queries _dmarc at each parent name, up to the top-level domain, with at most eight queries however long the name is. The shortest name with a record is the organisational domain, and its record applies, with its sp tag for a subdomain that exists or its np tag for one that does not. The check reports this as DMARC_INHERITED.
For a.mail.example.com, the walk queries _dmarc.a.mail.example.com, _dmarc.mail.example.com, _dmarc.example.com and _dmarc.com. If only example.com publishes a record, that record applies. RFC 7489 used the Public Suffix List for this step instead; the tree walk usually gives the same answer but needs no external list.
If a name returns more than one DMARC record, receivers discard all of them and continue the walk (DMARC_MULTIPLE_RECORDS).
Testing mode and the end of pct
RFC 7489 had a pct tag that applied the policy to a percentage of failing mail. Receivers implemented values between 0 and 100 inconsistently, and RFC 9989 removed it, together with rf and ri. Receivers that follow RFC 9989 ignore these tags; a record with p=reject; pct=10 is then a full reject. The check reports a pct below 100 as DMARC_PARTIAL_PCT and the other removed tags as DMARC_HISTORIC_TAG.
The new t=y tag replaces pct=0. It asks receivers to apply the policy one level below the published one: reject is handled as quarantine, and quarantine as none. Reports are sent as usual. The check reports it as DMARC_TESTING_MODE.
Rolling out a policy
- Publish
v=DMARC1; p=none; rua=mailto:...and read the aggregate reports. They list the sources that send mail as your domain and whether SPF and DKIM align for them. - Fix legitimate senders until they pass in alignment: authorise them in SPF or, better, have them sign with a DKIM key for your domain.
- Publish
p=quarantine; t=y. Receivers then handle failing mail asnone, while you prepare. Removet=yto enforce quarantine. - Move to
p=rejectthe same way when the reports show no legitimate failing mail; witht=y, failing mail is quarantined rather than rejected. - Consider
np=reject: names that do not exist never send legitimate mail.
Mailing lists and forwarding services can break both SPF and DKIM, so a strict policy can affect legitimate mail from those paths. The reports are how you see it.
Reports
Aggregate reports (rua, RFC 9990) are XML files, usually sent daily, with counts per source IP and the SPF, DKIM and DMARC results. Failure reports (ruf, RFC 9991) are per-message copies. Many receivers do not send them at all, partly for privacy reasons, so do not rely on them. Older records sometimes add a size limit to a URI, such as mailto:[email protected]!10m; RFC 9989 marks that syntax as obsolete and report senders ignore the limit.
If a report address is in a domain with a different organisational domain than the one that publishes the policy, the receiving domain must publish an authorisation TXT record (RFC 9990 section 4); otherwise report senders discard the address. A report address that uses a scheme other than mailto is reported as DMARC_UNSUPPORTED_REPORT_URI, since mailto is the form every report sender is required to support.
Common mistakes
- No record on the sending domain or any of its parents (
DMARC_NOT_FOUND). - Several DMARC records on the same name (
DMARC_MULTIPLE_RECORDS). - An invalid
p,spornp(DMARC_INVALID_POLICY), which turns the whole record intop=none, or into no DMARC at all when there is no validrua. - Staying on
p=none(DMARC_POLICY_NONE) or having norua(DMARC_NO_RUA), which leaves you without data. - Relying on
pctfor a gradual rollout after RFC 9989. - Typos in tags and values (
DMARC_SYNTAX_ERROR), and tags that are not defined (DMARC_UNKNOWN_TAG).
Use the DMARC check to read the effective policy for a domain, or the mail check to see it next to SPF, DKIM and MX. The check reads published records only. It does not look at your mail flow or at received reports.
DMARC findings
- Info
DMARC_HISTORIC_TAGThe DMARC record contains a tag that RFC 9989 lists as historic. - Info
DMARC_INHERITEDThe DMARC policy comes from a parent domain. - Error
DMARC_INVALID_POLICYThe DMARC record has an invalid p, sp or np tag. - Error
DMARC_MULTIPLE_RECORDSMore than one DMARC record was found. - Warning
DMARC_NOT_FOUNDNo DMARC record was found for the domain or any of its parent domains. - Info
DMARC_NO_RUAThe DMARC record has no aggregate report address (rua). - Info
DMARC_PARTIAL_PCTThe DMARC record uses pct below 100, a tag that RFC 9989 removed. - Info
DMARC_POLICY_NONEThe DMARC policy is p=none (monitoring only). - Error
DMARC_SYNTAX_ERRORThe DMARC record contains a tag that cannot be parsed or has an invalid value. - Info
DMARC_TESTING_MODEThe DMARC policy is in testing mode (t=y). - Info
DMARC_UNKNOWN_TAGThe DMARC record contains tags that are not defined. - Info
DMARC_UNSUPPORTED_REPORT_URIA DMARC report address uses a scheme other than mailto.
Frequently asked questions
Where is the DMARC record published?
As a TXT record at _dmarc. followed by the domain, for example _dmarc.example.com. If the sending domain has no record, receivers walk up the DNS tree to its organisational domain and use that record (RFC 9989 section 4.10). The DMARC check does the same lookup.
Is p=none useful?
It is the starting point. It asks receivers not to act on failures, but it still enables aggregate reports (rua), which show who sends mail as your domain and whether it aligns. It does not protect the domain against spoofing.
Can DMARC pass if SPF fails?
Yes. A message passes DMARC when at least one of SPF or DKIM passes in alignment with the From domain. Mail that is forwarded often fails SPF but keeps a valid DKIM signature.
What happened to pct?
RFC 9989, which replaced RFC 7489 in May 2026, removed pct because receivers applied values other than 0 and 100 inconsistently. Receivers that follow RFC 9989 ignore it and apply the full policy. The new t=y tag takes over the role of pct=0.
Does the check verify that report addresses on other domains accept reports?
No. RFC 9990 section 4 requires a domain that receives reports for another domain to publish an authorisation record, and report senders check it. The DMARC check reads the record you publish and does not test that authorisation.