DMARC Record Explained: Every Tag, Syntax Rule, and Common Mistake
A field-by-field breakdown of what actually goes into a DMARC TXT record, why each tag exists, and the syntax mistakes that quietly make a record invalid.
Anatomy of a DMARC Record
A DMARC record is, mechanically, nothing more than a DNS TXT record published at _dmarc.yourdomain.com, containing a single line of semicolon-separated tag=value pairs. That simplicity is deceptive — every one of those tags carries specific operational meaning, and getting even one syntax detail wrong can make receivers disregard the whole record. This guide goes through the record field by field, in the order most administrators actually reason about them, with the exact syntax rules RFC 7489 specifies.
A realistic, moderately configured record looks like this:
v=DMARC1; p=quarantine; sp=reject; pct=50; rua=mailto:dmarc-agg@example.com; ruf=mailto:dmarc-forensic@example.com; adkim=s; aspf=r; fo=1;
Every tag in that string is explained individually below, along with which ones are required, which are optional, and what receivers do when a tag is missing entirely versus present but malformed.
v — Version (Required)
The version tag must be the literal string DMARC1 and, by convention, is always the first tag in the record. It signals to a DNS resolver scanning through potentially multiple unrelated TXT records at the same name that this particular one is a DMARC policy. There is currently only one defined version, so in practice this tag never varies — but its presence and exact spelling are mandatory. A record missing v=DMARC1 or misspelling it is not treated as DMARC at all, regardless of what other tags follow.
p — Domain Policy (Required)
The policy tag is the core enforcement instruction and the only other tag besides v that's mandatory. It accepts exactly three values:
| Value | Meaning | Typical Use |
|---|---|---|
none | Take no action; report only | Initial monitoring phase |
quarantine | Treat as suspicious, typically routed to spam | Mid-rollout enforcement |
reject | Refuse delivery outright | Full, mature enforcement |
Any value outside those three — a typo like rejct, a capitalization mismatch some strict parsers won't accept, or an empty value — renders the record invalid in the eyes of a strict receiver. This is the tag most worth double-checking after any manual DNS edit.
sp — Subdomain Policy (Optional)
By default, the policy set in p applies both to the organizational domain and to every subdomain that doesn't publish its own separate DMARC record. The sp tag overrides that inheritance for subdomains specifically, letting an organization run a different — usually stricter — policy on subdomains than on the root domain. This matters because subdomains are a common target for abuse: an attacker registering a throwaway subdomain-style sender or exploiting a forgotten, unused subdomain benefits from any gap between root and subdomain enforcement. A common pattern is p=quarantine; sp=reject; — moderate enforcement on mail from the root domain, strict rejection on anything from a subdomain, since most organizations send far less legitimate mail from subdomains and can afford to be aggressive there sooner.
pct — Percentage of Enforcement (Optional, default 100)
The pct tag lets a domain owner apply the quarantine or reject policy to only a fraction of failing messages, chosen effectively at random by the receiver. It accepts an integer from 0 to 100. This is the mechanism behind gradual rollout: rather than flipping every failing message straight to reject, an administrator can set pct=10 initially, observe the impact, and raise it in stages — 25, 50, 75, 100 — over successive weeks. Because p=none takes no enforcement action regardless, pct has no observable effect until the policy is quarantine or reject; it's purely a rollout throttle for enforcement, not a sampling control for reporting, which continues at full volume from day one regardless of the pct value.
rua — Aggregate Report Address (Optional but strongly recommended)
The rua tag specifies where daily aggregate XML reports should be delivered, formatted as one or more mailto: URIs, comma-separated if there's more than one:
rua=mailto:dmarc-agg@example.com,mailto:reports@monitoring-vendor.com
Technically optional per the specification, omitting it in practice defeats most of DMARC's operational value, since the domain owner then has no visibility into authentication results at all — only the policy is enforced, blind. One subtlety worth knowing: if the address in rua is on a different domain than the one being protected, the receiving domain must publish an authorization record at _report._dmarc. plus the sender's domain, confirming it agrees to receive those reports — a mechanism to prevent DMARC from being used to flood arbitrary third-party mailboxes.
ruf — Forensic Report Address (Optional, limited support)
Where rua requests daily summary statistics, ruf requests per-message forensic reports containing details about individual authentication failures, sent close to real time rather than batched daily. In practice, support for ruf has declined significantly across major mailbox providers because forensic reports can include message content or headers with privacy implications; Gmail and several other large providers no longer send them at all regardless of whether ruf is configured. It's still valid to include, and some smaller providers and internal mail systems do honor it, but a domain owner shouldn't rely on it as a primary monitoring channel. Our dedicated article on DMARC Forensic Reports covers this in more depth.
adkim and aspf — Alignment Mode (Optional, default relaxed)
These two tags independently control how strictly DKIM and SPF alignment are evaluated. Each accepts r (relaxed, the default) or s (strict):
| Setting | Strict/Relaxed Behavior | Example | Security Impact |
|---|---|---|---|
adkim=r (default) | Any subdomain of the signing domain aligns | DKIM signed by mail.example.com aligns with From: example.com | More compatible, slightly more permissive |
adkim=s | Signing domain must exactly match From: domain | DKIM signed by mail.example.com does NOT align with From: example.com | Stronger, may break legitimate subdomain senders |
aspf=r (default) | Any subdomain of the envelope domain aligns | SPF-authorized bounce.example.com aligns with From: example.com | More compatible |
aspf=s | Envelope domain must exactly match From: domain | SPF-authorized bounce.example.com does NOT align with From: example.com | Stronger, may break third-party transactional senders |
The two tags are independent — a domain can run strict DKIM alignment alongside relaxed SPF alignment, or any other combination, depending on how tightly each authentication path is controlled. See DMARC Alignment for a deeper treatment with worked failure scenarios.
fo — Forensic Report Options (Optional, default 0)
The fo tag governs when forensic reports (subject to ruf being configured and honored) are actually generated. It accepts one or more colon-separated values:
| Value | Triggers a Report When… |
|---|---|
0 (default) | The message fails DMARC evaluation overall |
1 | Either SPF or DKIM fails, even if the message still passes DMARC overall |
d | The DKIM signature fails to verify for any reason |
s | The SPF check fails for any reason |
fo=1 is the most commonly chosen non-default value, since it surfaces partial failures that fo=0 would otherwise hide — useful during a diagnostic period even though, again, actual delivery of these reports depends on receiver support.
rf and ri — Rarely Configured Tags
Two additional tags exist but are rarely set manually. rf specifies the format for forensic reports, with afrf (Authentication Failure Reporting Format) as the only value in practical use. ri requests an aggregate reporting interval in seconds, defaulting to 86400 (24 hours); in practice, most large mailbox providers send daily reports regardless of a smaller requested interval, since ri is explicitly a request rather than a binding requirement in the specification.
Syntax Rules That Actually Matter
A Worked Example, Tag by Tag
Take this realistic mid-rollout record apart piece by piece:
v=DMARC1; p=quarantine; sp=reject; pct=50; rua=mailto:dmarc@example.com; adkim=r; aspf=r;
v=DMARC1— declares this as a DMARC policy recordp=quarantine— mail failing DMARC from the root domain is routed to spamsp=reject— mail failing DMARC from any subdomain is refused outright, a stricter stance since subdomains see less legitimate trafficpct=50— only half of failing messages actually receive the quarantine treatment right now, a mid-rollout throttlerua=mailto:dmarc@example.com— daily aggregate reports land in this mailboxadkim=r/aspf=r— both explicitly set to relaxed, matching the default but stated for clarity
Notice there's no ruf here — a deliberate choice given limited provider support, and no fo tag since it only matters when forensic reporting is actually happening.
Verifying a Record After Publishing
DNS propagation delay means a freshly published or edited record won't be visible everywhere instantly — typically within an hour depending on the record's TTL, though caching resolvers may hold an old value briefly longer. Once propagated, the fastest way to confirm every tag parsed the way you intended is a direct check with DMARC Lookup, which parses the live record exactly the way a receiving mail server would and flags missing required tags, unrecognized values, or multiple conflicting records automatically.
Building a Record Incrementally, Not All at Once
A common instinct when first learning DMARC syntax is to write out every tag at once — full alignment settings, forensic reporting, a specific pct value — before ever publishing anything. In practice, the more reliable approach is the opposite: start with the smallest working record, confirm it parses and reports correctly, then add complexity one tag at a time. Each addition is a small, individually verifiable change rather than a single large edit where, if something breaks, there are five possible culprits instead of one.
Step 1: v=DMARC1; p=none; rua=mailto:dmarc@example.com; Step 2: + sp=quarantine; (extend coverage to subdomains) Step 3: + adkim=r; aspf=r; (make default alignment explicit) Step 4: + pct=25; (once ready to begin enforcement)
Each of these intermediate states is a fully valid, independently checkable DMARC record — there's no requirement to reach a "final" configuration in one edit, and treating the record as something that evolves in small steps makes both DNS-side troubleshooting and enforcement rollout considerably less risky.
What Receivers Do With an Invalid Record
It's worth being specific about what actually happens when a DMARC record fails to parse, since the consequence is easy to underestimate. Most receivers don't reject the message outright or treat a malformed record as a policy failure — instead, they typically fall back to treating the domain as though it had no DMARC record published at all. That means all the intended protection silently evaporates: no alignment enforcement, no reporting, nothing — while the domain owner may still believe DMARC is active because a record technically exists in DNS. This is exactly why re-verifying syntax after every edit isn't optional caution; it's the only way to know the record is doing anything at all.
Comparing DMARC Syntax to SPF and DKIM Syntax
Anyone already comfortable with SPF or DKIM syntax will notice DMARC's tag=value structure is deliberately similar, though the underlying rules differ in ways worth being explicit about. SPF records are a single space-separated string of mechanisms evaluated left to right with no equals signs for most terms. DKIM selector records also use tag=value pairs but focus on cryptographic material (the p= tag there holds a public key, not a policy). DMARC's tag=value format most closely resembles DKIM's own record syntax, which isn't a coincidence — both were designed by overlapping working groups aiming for consistency across the broader email authentication ecosystem.
Checking TTL Before Making Frequent Changes
The TTL (time to live) value on the DMARC TXT record determines how long resolvers cache it before re-checking DNS, and it's worth checking before making several changes in quick succession during an active rollout. A long TTL — several hours or more — means changes propagate slowly, and testing the effect of a pct adjustment might not be visible everywhere for some time. Temporarily lowering the TTL during an active rollout period, then raising it again once the configuration stabilizes, is a common practice that makes iterative testing considerably faster without any downside once the record reaches its intended final state.
Related Reading in This Series
For the conceptual overview of why DMARC exists and how it fits with SPF and DKIM, start with What Is DMARC?. For the enforcement rollout across policy levels, read DMARC Policies (None, Quarantine, Reject). For how to interpret the reports generated along the way, see DMARC Aggregate Reports. To check your own domain's live record, open DMARC Lookup.
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 Lookup | Tool | Open Tool → |
| SPF Lookup | Tool | Open Tool → |
| DKIM Lookup | Tool | Open Tool → |
| What Is DMARC? | Guide | Read Guide → |
| DMARC Policies (None, Quarantine, Reject) | Guide | Read Guide → |