DMARC tags and policy
Every DMARC tag with its default, how alignment is actually evaluated, what the reports contain, and a rollout order that does not break your mail.
A DMARC record is a single DNS TXT record published at _dmarc under your domain, made of semicolon-separated tag-value pairs. This page lists every tag, what it does, and what happens when you leave it out — plus how alignment actually works, which is the part that decides whether your mail passes.
To check a specific domain instead, use the DMARC checker.
How a receiver evaluates DMARC
Four steps, in order. Understanding them explains almost every surprising result.
- Read the
From:header domain. This is the domain DMARC protects — the one a human sees, not the envelope sender. - Look up the DMARC record at
_dmarcunder that domain. If there is none, walk up to the organizational domain and use its record instead. - Check alignment. SPF passed and its domain aligns with the From domain, or DKIM verified and its signing domain aligns. Either one is enough.
- Apply the policy if neither aligned, and send a report either way.
The critical point is step 3. DMARC never asks "did SPF pass?" in isolation. It asks whether a mechanism passed for the domain in the From header.
The tags
| Tag | Purpose | Default if omitted |
|---|---|---|
v |
Version. Must be DMARC1 and must come first. |
Required — record is invalid without it |
p |
Policy for the domain: none, quarantine, reject. |
Required |
sp |
Policy for subdomains. | Inherits p |
adkim |
DKIM alignment mode: r relaxed or s strict. |
r |
aspf |
SPF alignment mode: r relaxed or s strict. |
r |
pct |
Percentage of failing mail the policy applies to. | 100 |
rua |
Where to send aggregate reports. mailto: URIs. |
No reports |
ruf |
Where to send failure (forensic) reports. | No reports |
fo |
When to generate failure reports: 0, 1, d, s. |
0 |
rf |
Failure report format. | afrf |
ri |
Aggregate report interval, in seconds. | 86400 (daily) |
Only v and p are required. Everything else has a default, and the defaults are mostly sensible — the two worth setting deliberately are rua and sp.
p and sp
p is the whole point of the record. none means take no action and report; quarantine means treat as suspicious, in practice spam; reject means refuse the message during the SMTP conversation.
sp exists because subdomains are the common spoofing target. Left out, subdomains inherit p — usually what you want. Set it explicitly when subdomains need different treatment, most often sp=reject on a parent still at p=none so unused subdomains are protected while you work through the main domain.
adkim and aspf
Alignment mode, and the difference is narrow but consequential:
- Relaxed (
r) — the organizational domains must match.mail.example.comaligns withexample.com. - Strict (
s) — the domains must match exactly.mail.example.comdoes not align withexample.com.
Relaxed is the default and the right choice almost always. Strict breaks the moment a vendor signs with a subdomain you did not anticipate, and it buys very little: an attacker who controls a subdomain of your domain already has a bigger problem than alignment mode.
rua and ruf
rua receives aggregate reports: daily XML summaries, one per reporting receiver. This is the tag that makes DMARC useful rather than merely present.
ruf receives failure reports — near-real-time, per-message, and containing message headers. Most large receivers do not send them at all, for privacy reasons, so expect far fewer than you would guess. They can also contain personal data, which is worth thinking about before pointing ruf at a shared mailbox.
You can list several addresses, comma-separated. To receive reports at a domain you do not control, that domain has to publish an authorisation record — otherwise well-behaved reporters will refuse to send.
pct
Applies the policy to a random subset of failing mail. Designed for phased rollout: p=quarantine; pct=25 quarantines a quarter of failures and takes no action on the rest.
Two things to know. It is genuinely useful for a week or two while ramping. And it is a coin flip, so identical messages get different treatment — which makes debugging harder, not easier. Remove it once you are confident.
fo
Controls when failure reports are generated, when the receiver sends them at all:
| Value | Generate a report when |
|---|---|
0 |
Both SPF and DKIM failed to align (the default) |
1 |
Either failed to align — far more reports |
d |
DKIM failed to verify, regardless of alignment |
s |
SPF failed to verify, regardless of alignment |
fo=1 is the common choice when actively debugging, because fo=0 hides the case where one mechanism aligned and the other silently broke.
Alignment, with examples
Say your From: is [email protected].
| Scenario | SPF domain | DKIM d= |
Relaxed | Strict |
|---|---|---|---|---|
| Sent from your own server | example.com |
example.com |
Pass | Pass |
| Sent via a platform signing as you | bounce.vendor.net |
example.com |
Pass (DKIM) | Pass (DKIM) |
| Platform signs with its own domain | bounce.vendor.net |
vendor.net |
Fail | Fail |
| Platform signs with your subdomain | bounce.vendor.net |
mail.example.com |
Pass (DKIM) | Fail |
Row three is the one that catches people: the message is perfectly authenticated, and it still fails DMARC, because nothing authenticated your domain. Row four is why strict alignment costs more than it looks.
What the reports contain
Aggregate reports are compressed XML, typically daily, from each receiver that handled your mail. Each groups messages by source IP and sending domain and gives counts plus the SPF and DKIM results. No content, no subject lines, no recipient addresses. They answer one question well: who is sending as your domain, and is it aligning.
Failure reports are per-message and include headers, which is why they are increasingly rare. Do not build a process that depends on them.
Reading raw XML stops scaling quickly — a mid-sized domain gets dozens of files a day from a dozen providers. Our DMARC aggregation collects and groups them, which is the same job an XML parser and a spreadsheet do, minus the spreadsheet.
A rollout that does not break your mail
- Publish
p=nonewith aruaaddress. No effect on delivery; reports start arriving. - Read reports for two to four weeks. Build a list of every source sending as you.
- Fix or remove each source that fails alignment. This is the actual work, and it is where the time goes.
- Move to
p=quarantine, optionally withpctwhile ramping. Watch reports. - Move to
p=rejectand removepct. - Keep reading reports. A new vendor added later will break, and reports are how you find out before your customers do.
Things worth knowing
DMARC lives at _dmarc, not at the apex. A perfect record published on example.com instead of _dmarc.example.com does nothing. SPF does live at the apex, which is why this mistake is so common.
One record only. Two DMARC records at the same name means receivers treat the domain as having no valid policy.
Subdomains inherit, unlike SPF. DMARC applies down the tree via p or sp; SPF does not inherit at all. That asymmetry surprises almost everyone once.
p=none is not protection. A domain on p=none is exactly as spoofable as a domain with no DMARC. It is a measurement mode, and treating it as a finished project is the most common failure in the whole standard.
Related
- DMARC checker — read a live record and its policy.
- SPF mechanisms and modifiers — the full SPF reference.
- SPF checker — count a record's DNS lookups.
- DKIM checker — the mechanism that survives forwarding.
- Full domain check — everything at once.