DMARC Engine
Home/Blog/RFC 7489: the DMARC standard explained
Blog

RFC 7489: the DMARC standard explained

A close reading of RFC 7489, the document that defines DMARC: the From-header trust model, identifier alignment, the record tags, policy discovery and application, the two report types, and the clauses people consistently misread.

24 March 2026 · 12 min read

RFC 7489: the DMARC standard explained

Almost everything written about DMARC paraphrases one document: RFC 7489, "Domain-based Message Authentication, Reporting, and Conformance (DMARC)", published by the IETF in March 2015. It is an Informational RFC, not a Standards Track one, which surprises people who treat it as gospel. It runs to about 75 pages, and most of the confusion in the field comes from the gap between what the specification actually says and what blog posts claim it says.

This article is a guided tour of the document itself: the trust model it builds, the record it defines, how alignment is computed, how a receiver applies policy, what the two report types contain, and the specific clauses that people consistently misread. It is not a generic "what is DMARC" explainer; if you want that, the DMARC glossary entry and Understanding your DMARC record cover the basics. Here we read the spec.

What problem RFC 7489 was actually written to solve

Before DMARC, two authentication mechanisms already existed and were widely deployed: SPF (RFC 7208) and DKIM (RFC 6376). Both worked, and both had the same blind spot. Neither of them validates the domain a human reads.

  • SPF authenticates the envelope sender, the MAIL FROM address used during the SMTP transaction, also called the Return-Path. The recipient never sees it.
  • DKIM authenticates the domain in the d= tag of the signature, chosen by whoever signs the message. It need not match the visible sender either.

The address a person actually sees and trusts is the From: header, defined in RFC 5322. Section 1 of RFC 7489 names this directly: the From domain is the "RFC5322.From" identity, and the entire purpose of DMARC is to let a domain owner assert a policy about messages bearing their From domain, and to receive reports about who is sending under it. The specification frames itself as filling the gap between channel authentication (SPF, DKIM) and the identity end users rely on.

That single design decision, anchoring everything to the From header, is the root of both DMARC's usefulness and its most common misunderstandings. Hold onto it; we return to it repeatedly.

The trust model: alignment, not just authentication

The conceptual core of RFC 7489 is in Section 3, and it is short enough to state plainly. DMARC does not invent a new authentication method. It reuses SPF and DKIM and adds one test on top: identifier alignment.

A message produces a DMARC pass when at least one of the following holds:

  1. SPF returns pass for the envelope domain, and that domain is aligned with the From domain, or
  2. DKIM returns pass for a signature, and that signature's d= domain is aligned with the From domain.

Note the logic. It is an OR, not an AND. You do not need both to pass. You need one of them to both authenticate and align. This is why a message can carry a broken DKIM signature and still pass DMARC on SPF alone, and vice versa. It is also why "SPF passes and DKIM passes but DMARC fails" is possible: both can authenticate for the wrong domain, so neither aligns. We have a whole piece on that failure mode in DMARC fails but SPF and DKIM pass, and it falls straight out of the OR rule above.

How alignment is defined

Section 3.1 defines alignment in two modes:

  • Strict alignment requires the authenticated domain and the From domain to be identical.
  • Relaxed alignment requires only that they share the same Organizational Domain.

You can confirm the spec uses the term "Organizational Domain", capitalised, as a defined concept. The Organizational Domain is computed using the Public Suffix List, not by counting dots. This matters. Under relaxed alignment, news.example.com and example.com align because both reduce to the registrable domain example.com. But example.co.uk reduces to example.co.uk, because co.uk is a public suffix, so mail.example.co.uk aligns with example.co.uk and not with co.uk. The DMARC alignment glossary entry goes deeper, and the return-path entry explains why SPF alignment is the harder of the two to achieve.

The defaults are relaxed for both SPF and DKIM. You change them with the aspf and adkim tags, which we cover below.

A subtlety the spec is explicit about: SPF alignment uses MAIL FROM

Section 3.1.1 specifies that for SPF, the domain used for the alignment check is the one in the SMTP MAIL FROM (the RFC5321.MailFrom domain). If MAIL FROM is empty, as it is for bounce messages, the HELO identity is used instead. This is why mail relayed through a third party so often fails SPF alignment even when SPF itself passes: the provider sets MAIL FROM to its own bounce domain, so SPF passes for the provider and aligns with nothing of yours. There is no way around this except a custom Return-Path domain (a CNAME or delegated subdomain) that shares your Organizational Domain. The SPF checker shows you the envelope domain in play.

Reading the DMARC record, tag by tag

The DMARC record is a DNS TXT record published at _dmarc.<your-domain>. Section 6.3 defines the tags. A representative record looks like this:

_dmarc.example.com.  IN  TXT  "v=DMARC1; p=quarantine; sp=reject; rua=mailto:rua@example.com; ruf=mailto:ruf@example.com; adkim=s; aspf=r; pct=100; fo=1; ri=86400"

Here is what each tag means according to the spec, including the parts people get wrong.

  • v is the version and must be the literal string DMARC1, and it must be the first tag. Section 6.3 is explicit: if v is absent or not exactly DMARC1, the record is not a DMARC record and the receiver discards it. A trailing-space or lowercase dmarc1 will cause the whole record to be ignored.
  • p is the requested policy for the domain itself: none, quarantine, or reject. This tag is required. A record with no p is invalid and treated as if no DMARC record exists.
  • sp is the policy for subdomains. If absent, subdomains inherit p. This is one of the most misread tags; see the dedicated section later and Subdomain DMARC record.
  • adkim and aspf set DKIM and SPF alignment mode: r for relaxed (default), s for strict.
  • pct is the percentage of messages the requested policy is applied to, from 0 to 100, default 100. This is widely misunderstood; see below.
  • rua is the list of URIs to send aggregate reports to, comma-separated mailto: addresses.
  • ruf is the list of URIs for failure (forensic) reports.
  • fo controls when failure reports are generated: 0 (default) only when all mechanisms fail, 1 when any mechanism that produced an aligned result fails, d and s for DKIM- and SPF-specific failures. fo=1 is what most operators actually want, yet 0 is the default.
  • ri is the requested interval between aggregate reports in seconds, default 86400 (one day). It is a request, not a guarantee.
  • rf is the failure report format, defaulting to AFRF (RFC 6591). In practice only this value is used.

A few tags exist in the spec that are effectively dead in the field. pct is honoured unevenly. ruf is barely supported by major receivers any more for privacy reasons. Knowing what the spec defines versus what receivers implement is half the battle; you can validate a record's syntax against the spec with the DMARC checker and build a compliant one with the DMARC generator.

Tags the spec does NOT define

People routinely invent tags. There is no rua size limit tag, no forensic tag, no mode tag. Any tag the receiver does not recognise is ignored, per Section 6.3, but an unknown tag does not invalidate the record. What does invalidate it is a missing or malformed v or p. If you have ever seen a record "disappear" from a checker, it is almost always a broken v=DMARC1 prefix.

Policy discovery: how a receiver finds your record

Section 6.6.3 lays out the lookup algorithm, and it is more involved than "query _dmarc.example.com". The receiver:

  1. Extracts the domain from the From header. If there are multiple From addresses or multiple domains, the message is outside DMARC's defined behaviour and most receivers fail it.
  2. Queries _dmarc. plus that exact domain for a TXT record.
  3. If no valid DMARC record is found there, the receiver computes the Organizational Domain of the From domain and queries _dmarc. plus that domain instead.
  4. Crucially, the policy found at the Organizational Domain in step 3 is applied only via the sp tag, the subdomain policy. If sp is absent, p is used for the subdomain too.

This two-step lookup, exact domain then Organizational Domain, is why a subdomain with no DMARC record of its own still inherits a policy from the parent. It is also why publishing a strict policy at the apex silently governs every subdomain you forgot about. The enforcement journey doc and Reaching p=reject without breaking email walk through the operational consequences.

Applying policy: disposition, overrides, and the local-policy escape hatch

Once a receiver has authenticated, checked alignment, and found your policy, Section 6.6.2 governs what it does. If the message passes DMARC, it is delivered normally and DMARC imposes nothing. If it fails, the receiver consults p (or sp for a subdomain) and applies the requested disposition: deliver (for none), quarantine, or reject.

But here is a clause that catches people out. The spec says the published policy is the domain owner's request, and that receivers may apply local policy that overrides it. Section 6.7 and the override reason codes in the aggregate report schema make this explicit. A receiver is permitted to:

  • Deliver a message you asked to reject, for example because it recognises a trusted forwarder (the local_policy or forwarded override).
  • Honour a mailing-list exception via ARC (Authenticated Received Chain), recorded as the arc override.
  • Apply a sampled_out override when your pct value excluded the message from enforcement.

This is why your reports will show messages that "failed DMARC at p=reject" but were nonetheless delivered. The receiver is following the spec, which always treats your policy as advisory, never as a command. Understanding the override reason codes is essential to reading reports correctly; Reading your first DMARC report decodes them, and the DMARC report analyzer surfaces them from raw XML.

The reporting half of DMARC: the part most people ignore

The "R" in DMARC is for Reporting, and it is genuinely half the specification. Two report types exist, defined in Sections 7.1 and 7.2.

Aggregate reports (RUA)

An aggregate report is an XML document a receiver sends, typically once a day, to the addresses in your rua tag. It does not contain message content. It contains counts: how many messages from each source IP claimed your From domain, what SPF and DKIM results they produced, whether each aligned, and what disposition the receiver applied. The schema is defined in Appendix C of the RFC.

A trimmed aggregate record looks like this:

<record>
  <row>
    <source_ip>203.0.113.10</source_ip>
    <count>42</count>
    <policy_evaluated>
      <disposition>none</disposition>
      <dkim>fail</dkim>
      <spf>pass</spf>
    </policy_evaluated>
  </row>
  <identifiers>
    <header_from>example.com</header_from>
  </identifiers>
  <auth_results>
    <spf><domain>bounce.provider.net</domain><result>pass</result></spf>
  </auth_results>
</record>

Read that carefully and you can see a classic misalignment: SPF pass, but the SPF domain is bounce.provider.net, not example.com, so policy_evaluated/spf shows pass while the message would still fail DMARC if DKIM also failed. Aggregate reports are how you discover every system sending under your domain before you tighten policy. The aggregate report glossary entry and our monitoring product exist for exactly this.

Failure reports (RUF)

Failure reports, sometimes called forensic reports, are per-message and are sent in close to real time when a message fails (subject to your fo setting). They use the AFRF format from RFC 6591 and can include headers and partial content. Because they may carry personal data, most large receivers (Google, Microsoft, Yahoo) do not send them at all. This is a major gap between the spec and reality: RFC 7489 defines ruf in detail, but you should not plan around receiving forensic reports. The forensic report glossary entry covers the privacy reasons.

The parts people consistently misread

These are the clauses where the spec and the folklore diverge most sharply.

"p=none does nothing" is wrong

p=none requests no enforcement action, true. But it still triggers alignment evaluation and reporting. The whole monitoring phase of a deployment runs at p=none, and the reports it produces are how you find your legitimate senders before you enforce. The mistake is treating p=none as a destination. It is a starting line. The false security of p=none and the docs version make the case that staying there indefinitely gives you visibility but zero protection against spoofing.

pct does not mean "scan this percentage"

pct=20 does not mean "evaluate DMARC on 20% of mail". DMARC is evaluated on all mail. pct controls only what fraction of failing messages the requested policy is applied to; the rest fall back to the next weaker policy (reject becomes quarantine, quarantine becomes none). It is a rollout dial for enforcement, not a sampling rate, and Section 6.3 is clear that reporting is unaffected by it. Receivers also implement it inconsistently, so it is a blunt instrument at best.

Alignment defaults to relaxed, and you usually want it that way

Copying a record with adkim=s or aspf=s is a common self-inflicted wound. Strict alignment rejects perfectly legitimate subdomain selectors and provider bounce domains. Unless you have a specific reason, leave both relaxed. The spec sets relaxed as the default precisely because strict breaks more than it protects for typical senders.

DMARC checks exactly one From domain

Section 6.6.1 is explicit that DMARC operates on a single RFC5322.From domain. Messages with multiple From addresses, or a From header that does not parse cleanly, are not defined by the spec and are generally failed outright by receivers. This is a deliberate anti-evasion stance: an attacker cannot smuggle a second From domain to dodge policy.

DMARC has no opinion on display names

This is the big one. RFC 7489 authenticates the domain in the From header. It does nothing about the display name. An attacker can send from attacker@gmail.com with the display name "Your Bank" and pass DMARC perfectly, because gmail.com is correctly authenticated. Display-name spoofing is entirely outside DMARC's scope by design, which is exactly why BIMI and brand indicators exist as a separate layer. See the display-name spoofing glossary entry and BIMI product page.

Where RFC 7489 sits in the wider standards stack

DMARC does not stand alone. It is the policy and reporting layer on top of:

  • SPF, RFC 7208, IP-based authorisation of the envelope sender. See /products/spf.
  • DKIM, RFC 6376, cryptographic signing of selected headers and the body. See DKIM glossary and /products/dkim.
  • ARC, RFC 8617, which preserves authentication results across forwarders and mailing lists, addressing a known DMARC weakness the original spec could not. See the ARC glossary entry.

There is also a successor effort: the IETF DMARC working group has been preparing DMARCbis to move DMARC onto the Standards Track and fold in years of operational lessons (notably replacing the Public Suffix List dependency with a DNS tree-walk for finding the Organizational Domain). When it publishes, it will obsolete RFC 7489, but the model described here, From-header anchoring, alignment, OR-logic, and the two report types, carries through essentially unchanged. The Gmail and Yahoo sender requirements that now mandate DMARC are built on this same foundation.

The practical takeaway

RFC 7489 is smaller and stranger than its reputation. Strip it down and it says: authenticate with SPF or DKIM, require the authenticated domain to align with the From header, let the domain owner publish an advisory policy, and send back reports so the owner can see reality before they enforce. The mistakes almost all come from a handful of misreadings: thinking pct samples evaluation, thinking p=none is pointless, thinking DMARC guards the display name, or thinking your policy is a command rather than a request a receiver may override.

If you want to see how your own domain measures against the spec right now, run it through the DMARC checker and read what your real aggregate reports are telling you. And if reading XML and chasing every sender into alignment is not how you want to spend the next three months, our done-for-you DMARC service takes a domain from p=none to p=reject against exactly this specification, with no email outage along the way.

Share

See where your domain stands today

Run a free DMARC scan, then let us take you to enforced p=reject with no email outage.