Every DMARC Tag Explained
A complete, accurate reference for what each DMARC record tag actually controls, its valid values and defaults, and how tags interact with each other.
The Complete Tag Reference
A DMARC record is a flat list of tag=value pairs separated by semicolons. Every tag beyond v= and p= is optional, falling back to a defined default when omitted — but knowing exactly what each one does, and what its default actually is, is the difference between a record that expresses your intended policy and one that quietly does something slightly different than you assumed.
Full Tag Table
| Tag | Values | Default | Purpose |
|---|---|---|---|
| v= | DMARC1 | Required, no default | Identifies the record as DMARC, must be first |
| p= | none / quarantine / reject | Required, no default | Policy for your exact domain |
| sp= | none / quarantine / reject | Inherits p= | Separate policy for subdomains |
| pct= | 0–100 | 100 | Percentage of failing mail policy applies to |
| rua= | mailto: URI list | None | Aggregate report destination(s) |
| ruf= | mailto: URI list | None | Forensic report destination(s) |
| fo= | 0 / 1 / d / s (colon-joined) | 0 | When forensic reports trigger (needs ruf=) |
| adkim= | r / s | r | DKIM alignment strictness |
| aspf= | r / s | r | SPF alignment strictness |
| ri= | seconds (integer) | 86400 | Requested aggregate report interval |
p= in Depth
none takes no action, existing purely to enable reporting. quarantine routes failing mail to spam/junk. reject blocks it entirely. This is the single most consequential tag in the record, since it determines what actually happens to mail, while every other tag either configures reporting or fine-tunes how alignment itself is measured.
sp= in Depth
Without sp=, subdomains inherit whatever p= specifies. Setting sp= explicitly lets you, for example, keep p=reject on your main domain while leaving subdomains at p=none if you're not yet confident in their configuration — or the reverse, locking down rarely-used subdomains more strictly than your actively-managed main domain.
pct= in Depth
pct= only matters when p= is quarantine or reject. At 100 (the default), the full policy applies to all failing mail. At a lower value, only that percentage of failing mail receives the policy treatment, with the remainder treated as if a less strict policy applied — a deliberate mechanism for gradual, lower-risk rollout rather than an all-or-nothing switch.
rua= and ruf= in Depth
Both accept comma-separated mailto: URIs. rua= reports arrive as periodic aggregate XML summaries; ruf= reports, where supported, are triggered per-message on failure. The companion guide on rua vs ruf covers the practical differences and current adoption reality in full depth.
fo= in Depth
| Value | Triggers Forensic Report When |
|---|---|
| 0 (default) | Both SPF and DKIM fail to produce an aligned pass |
| 1 | Either SPF or DKIM fails to produce an aligned pass |
| d | DKIM signature fails to verify, regardless of alignment |
| s | SPF fails to pass, regardless of alignment |
Values can be combined with colons, such as fo=1:d, to trigger under multiple conditions simultaneously.
adkim= and aspf= in Depth
Relaxed (r) accepts any subdomain of the organizational domain as aligned — mail.example.com aligns with example.com. Strict (s) requires an exact match between the authenticating domain and the visible From: domain, with no subdomain tolerance. Relaxed is the far more common choice since strict alignment can break legitimate mail sent from functionally-related subdomains that a relaxed check would correctly accept.
ri= in Depth
Requests a preferred reporting interval, but most major receivers send daily aggregate reports regardless of what's requested here, treating it more as a hint than a binding contract. Leaving it at default is almost always the practical choice.
Worked Examples of Full Records at Each Stage
| Stage | Full Record |
|---|---|
| Initial monitoring | v=DMARC1; p=none; rua=mailto:reports@example.com |
| Adding forensic reports | v=DMARC1; p=none; rua=mailto:reports@example.com; ruf=mailto:forensic@example.com; fo=1 |
| Partial enforcement with subdomain override | v=DMARC1; p=quarantine; sp=none; pct=25; rua=mailto:reports@example.com |
| Full enforcement, strict alignment | v=DMARC1; p=reject; rua=mailto:reports@example.com; adkim=s; aspf=s |
Notice how each stage's record differs by exactly the tags relevant to what changed — this is deliberate. A record shouldn't carry tags left over from a previous stage that no longer reflect current intent; reviewing and pruning the record at each stage transition keeps it an accurate reflection of your actual current policy rather than an accumulation of historical settings.
How Tags Interact With Each Other
Most tags are independent, but a few genuinely depend on others to have any effect. fo= is meaningless without ruf=. sp= is meaningless without a valid p=. pct= only matters when p= is quarantine or reject, since p=none takes no action regardless of what percentage is specified. Understanding these dependencies prevents a specific category of mistake: setting a tag carefully and correctly, then being confused when it appears to do nothing, because its prerequisite tag wasn't also set.
A Note on Tag Value Formatting Edge Cases
A few formatting details trip people up specifically because they're easy to get subtly wrong by hand. Multiple rua= or ruf= addresses must be comma-separated within a single tag, not written as separate rua= tags — rua=mailto:a@x.com,mailto:b@y.com is correct; writing rua= twice is not valid syntax. The fo= tag's multiple values are colon-separated, not comma-separated, unlike the email address lists — a small but easy inconsistency to trip over if you're not specifically aware of it. pct= takes a bare integer with no percent sign or decimal point.
Reading Tag Values From an Existing Live Record
When auditing a domain you didn't originally configure, parsing an existing DMARC record's tags correctly matters as much as knowing what to set for a new one. Split the record on semicolons, trim whitespace from each segment, and split each segment on the first equals sign to separate tag name from value — straightforward for well-formed records, though real-world records occasionally have inconsistent spacing around semicolons or equals signs that a naive parser might mishandle. Using a dedicated lookup tool that already handles this parsing correctly, rather than eyeballing raw TXT record text, avoids misreading a tag value due to a formatting quirk that's visually easy to miss but functionally different from what it appears to say.
Tags You Won't Find in a DMARC Record
It's worth briefly noting what DMARC does not have a tag for, since assuming otherwise is a specific, recurring confusion. There's no DMARC tag for specifying individual authorized sending IPs — that's SPF's job entirely. There's no DMARC tag for specifying a cryptographic key — that's DKIM's. DMARC's tags are exclusively about policy, reporting, and alignment configuration; it has no mechanism of its own for authorizing senders, only for acting on what SPF and DKIM already determined.
A Fully Annotated Example Record
Putting every tag together with inline reasoning helps cement how they combine: v=DMARC1; p=quarantine; sp=none; pct=50; rua=mailto:agg@example.com; ruf=mailto:forensic@example.com; fo=1; adkim=r; aspf=r; ri=86400. Reading through it: DMARC1 identifies the record. p=quarantine means failing mail on the main domain goes to spam. sp=none means subdomains are still unenforced, a deliberate choice reflecting that subdomain testing hasn't caught up yet. pct=50 limits the quarantine action to half of failing mail as a gradual step. rua= and ruf= both have report destinations set, with fo=1 requesting forensic reports on any single mechanism failure rather than requiring both to fail. adkim=r and aspf=r use relaxed alignment, the sensible default. ri=86400 explicitly restates the default reporting interval, included here mainly for illustration since omitting it would have the identical effect.
Related Reading in This Series
For the full safe rollout process using these tags in sequence, see Create a DMARC Record. For a deep comparison of the two reporting tags, read rua vs ruf. For general best practices across all these settings, see DMARC Best Practices. To build a record with these exact tags, open DMARC Record Generator.
ToolsNovaHub tools are built and independently maintained with a focus on accurate, no-signup network and security utilities. Spotted an error? Let us know.
📋 Related Tools & Guides Comparison
| Resource | Type | Link |
|---|---|---|
| DMARC Record Generator | Tool | Open Tool → |
| Create a DMARC Record | Guide | Read Guide → |
| rua vs ruf | Guide | Read Guide → |
| DMARC Lookup | Tool | Open Tool → |
| DMARC Record Explained | Guide | Read Guide → |