Spec note: DMARC was originally specified in RFC 7489 (2015). As of this writing, that’s been obsoleted by DMARCbis — RFC 9989 (core protocol), RFC 9990 (aggregate reporting) and RFC 9991 (failure reporting), published in 2026. The guidance below reflects RFC 9989–9991. Where it changes long-standing RFC 7489 advice, that’s called out explicitly rather than left implicit. See what DMARCbis is for the full picture of what changed and why.
The record
Publish a TXT record at _dmarc.example.com:
_dmarc.example.com. TXT "v=DMARC1; p=quarantine; rua=mailto:[email protected]"
v must be DMARC1 and must come first. p and rua are the two tags
that matter for almost every domain; everything else refines behavior
from there.
The tags
| Tag | Meaning | Default | Status |
|---|---|---|---|
v |
Protocol version, must be DMARC1 |
— | required |
p |
Policy for the domain itself | none |
current |
sp |
Policy for existing subdomains, if different from p |
inherits p |
current |
np |
Policy for non-existent subdomains | inherits sp/p |
current, new in DMARCbis |
adkim |
DKIM alignment mode: r (relaxed) or s (strict) |
r |
current |
aspf |
SPF alignment mode: r or s |
r |
current |
fo |
Failure report options (0, 1, d, s) |
0 |
current |
rua |
Aggregate report destination(s), mailto: URIs |
none sent | current |
ruf |
Failure report destination(s) | none sent | current |
t |
Testing-mode flag (y/n) |
n |
current, new in DMARCbis |
psd |
Marks a Public Suffix Domain record (y/n/u) |
u |
current, new in DMARCbis |
pct |
Percentage of failing mail the policy applied to | 100 | removed in DMARCbis |
ri |
Requested aggregate report interval, in seconds | 86400 | removed in DMARCbis |
rf |
Failure report format | afrf |
removed in DMARCbis — afrf was the only value ever defined |
If you’ve read older DMARC guidance, the three removed tags are the
main thing that’s changed. pct in particular was the standard advice
for years — “start at pct=10 and raise it” — and that mechanism is gone.
DMARCbis replaces gradual percentage rollout with the t=y testing-mode
flag (see below) and receiver-side judgement, rather than a
domain-owner-set sampling rate. ri was already ignored by most
receivers in practice, who defaulted to daily reports regardless of what
it requested; RFC 9990 formalizes that as the expected behavior. rf had
exactly one defined value its entire life and was redundant.
If your record still has pct, ri, or rf set from years ago, they’re
harmless to leave — current receivers ignore unknown/removed tags — but
don’t add them to a new record and don’t rely on pct for a gradual
rollout.
The rollout: none → quarantine → reject
-
p=none. Publish the record, change nothing about mail flow, and start collecting aggregate reports. Stay here until every legitimate source — your own infrastructure, every ESP, every third-party sender — shows as SPF- or DKIM-aligned in the reports. This is usually weeks, not days; wait for a full billing-cycle’s worth of senders to show up, not just daily transactional mail. -
p=quarantine. Once alignment is clean, move to quarantine. DMARCbis recommends addingt=yat this stage — it signals to receivers that you’re in a testing phase and gives some of them a basis for going easier on edge cases while you confirm nothing legitimate is being caught. Stay at quarantine for at least a full reporting cycle (RFC 9989 suggests a minimum of a month) watching for any aligned source suddenly showing failures. -
p=reject. Removet=yand move to reject once quarantine has run clean. This is enforcement: mail that fails DMARC is refused outright rather than filed as spam.
The signal to advance at each stage is the same: aggregate reports show 100% alignment for every source you recognize, for a full cycle, with no new unrecognized senders appearing. Advancing before that just moves your own legitimate mail into spam or rejection.
The destination authorization record people miss
If your rua (or ruf) address is on a different domain from the
one publishing the DMARC record — for example a monitoring vendor’s
domain — the receiving mail server won’t send reports there unless the
destination domain explicitly authorizes it. This got stricter in
DMARCbis: RFC 7489 said this verification should happen; RFC 9990 now
says receivers must check it before sending reports.
If example.com wants reports sent to reports.example.net, the
destination needs:
example.com._report._dmarc.reports.example.net. TXT "v=DMARC1"
Miss this record and reports to a third-party or subdomain address don’t arrive — silently, with no error visible to the domain owner. This is the single most common reason someone publishes a correct-looking record and still sees zero data three weeks later.
Copy-paste examples
Cloudflare — DNS → Add record → Type TXT, Name _dmarc, Content:
v=DMARC1; p=none; rua=mailto:[email protected]
GoDaddy — DNS Management → Add → Type TXT, Host _dmarc, TXT Value:
v=DMARC1; p=none; rua=mailto:[email protected]
Route 53 — Hosted zone → Create record → Record name _dmarc,
Record type TXT, Value (quotes required):
"v=DMARC1; p=none; rua=mailto:[email protected]"
Use the DMARC Record Wizard to build a record with the tags above without assembling the string by hand, and the DMARC Inspector to confirm what’s actually published once it propagates.