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 DMARCbisafrf 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

  1. 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.

  2. p=quarantine. Once alignment is clean, move to quarantine. DMARCbis recommends adding t=y at 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.

  3. p=reject. Remove t=y and 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.