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.

📅 Published August 2026· ⏳ 16 min read· ✍️ ToolsNovaHub Editorial Team
🛠️ Related tool: Open DMARC Record Generator →

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.

ToolsNovaHub Pro Tip
Only include tags whose non-default value you actually mean to set. A record listing every tag at its default value adds length and complexity with zero functional benefit over simply omitting them.
⚠︑
Common Beginner Mistake
Confusing adkim=/aspf= (how alignment is measured) with p= (what happens on failure). Setting strict alignment doesn't make your policy stricter in the p= sense — it changes what counts as passing in the first place.

Full Tag Table

TagValuesDefaultPurpose
v=DMARC1Required, no defaultIdentifies the record as DMARC, must be first
p=none / quarantine / rejectRequired, no defaultPolicy for your exact domain
sp=none / quarantine / rejectInherits p=Separate policy for subdomains
pct=0–100100Percentage of failing mail policy applies to
rua=mailto: URI listNoneAggregate report destination(s)
ruf=mailto: URI listNoneForensic report destination(s)
fo=0 / 1 / d / s (colon-joined)0When forensic reports trigger (needs ruf=)
adkim=r / srDKIM alignment strictness
aspf=r / srSPF alignment strictness
ri=seconds (integer)86400Requested 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

ValueTriggers Forensic Report When
0 (default)Both SPF and DKIM fail to produce an aligned pass
1Either SPF or DKIM fails to produce an aligned pass
dDKIM signature fails to verify, regardless of alignment
sSPF 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

StageFull Record
Initial monitoringv=DMARC1; p=none; rua=mailto:reports@example.com
Adding forensic reportsv=DMARC1; p=none; rua=mailto:reports@example.com; ruf=mailto:forensic@example.com; fo=1
Partial enforcement with subdomain overridev=DMARC1; p=quarantine; sp=none; pct=25; rua=mailto:reports@example.com
Full enforcement, strict alignmentv=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.

Reviewed by: ToolsNovaHub Editorial Team📅 Last updated: August 2026📜 Sourced from: RFC 7208

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

ResourceTypeLink
DMARC Record GeneratorToolOpen Tool →
Create a DMARC RecordGuideRead Guide →
rua vs rufGuideRead Guide →
DMARC LookupToolOpen Tool →
DMARC Record ExplainedGuideRead Guide →
Try it yourself — 100% free
🚀 Open DMARC Record Generator

🔗 More Guides

FAQ

Only v= and p= are required; every other tag is optional and falls back to a specification-defined default if omitted.
none, quarantine, or reject — no other values are valid, and an invalid value causes the record to be treated as malformed.
100, meaning the policy applies to all mail that fails alignment unless explicitly reduced.
No, sp= only has meaning alongside a valid p= tag, since it specifically overrides the policy for subdomains rather than functioning as a standalone policy tag.
Relaxed (r) for both, meaning organizational-domain-level matching is sufficient for alignment rather than requiring an exact domain match.
Yes, both accept a comma-separated list of mailto: URIs, letting reports go to more than one address or system simultaneously.
No, fo= specifically controls when forensic reports (governed by ruf=) are generated; without ruf=, fo= has no observable effect.
It requests a preferred reporting interval in seconds for aggregate reports, though most major receivers send daily regardless of what ri= requests, making it more of a preference than a guarantee.
Not directly as a separate configurable tag in the same sense as the others — aggregate reports follow a standardized XML schema by specification, and format isn't something the domain owner customizes via a DMARC tag.
Per specification, unrecognized tags are generally meant to be ignored by parsers rather than causing the entire record to fail, though relying on this is risky since not every implementation handles unknown tags identically.
The v= tag must come first, but beyond that, conventional ordering is a readability and compatibility best practice rather than a strict requirement for most tags.
p= controls what happens to mail that fails alignment; adkim=/aspf= control how strictly alignment itself is measured — they answer different questions entirely.
Yes, each tag follows the format tagname=value, and tags are separated by semicolons, with the whole set following v=DMARC1 at the start of the record.
Tag names and most fixed-value options (like p=reject) are conventionally lowercase, though DNS and DMARC parsing is generally case-insensitive for these; email addresses in rua/ruf should be written as actually valid for that mailbox.
ruf=, fo=, and ri= are the most commonly omitted, since forensic reporting is rarely used and the default reporting interval is accepted by most domains without customization.