DMARC (Domain-based Message Authentication, Reporting and Conformance) is a DNS TXT record, published at _dmarc.yourdomain.com, that tells receiving mail servers what to do with a message that claims to come from your domain but fails SPF and DKIM alignment, and where to send reports about it. It was defined in RFC 7489, an IETF Informational document from March 2015, and is now specified by RFC 9989, published as a Proposed Standard in May 2026. A domain without DMARC can have valid SPF and DKIM and still be spoofed in the From address a recipient reads.
At a glance
- Policy (
p=): Deliver, quarantine or reject mail that fails alignment - Alignment (
adkim=,aspf=): How closely the SPF or DKIM domain must match the From header domain - Reporting (
rua=,ruf=): XML summaries, typically daily, of every source sending as the domain, plus optional per-message failure reports
What is DMARC for: stopping From-header spoofing that SPF and DKIM alone do not stop
DMARC exists because SPF and DKIM each authenticate a domain the recipient never sees, and neither one says what to do when the check fails. SPF (RFC 7208) checks the sending server's IP against the domain in the SMTP envelope sender, the MAIL FROM address used in the server-to-server handshake. DKIM (RFC 6376) verifies a signature tied to whatever domain the signer names in its d= tag.
A phishing message can pass both while showing a different domain in the From header, because nothing in SPF or DKIM requires those domains to match. DMARC adds identifier alignment, which requires the authenticated domain to match the visible From domain, and a published policy for mail where neither identifier aligns. The sibling post on how SPF, DKIM and DMARC work together covers the interplay across all three.
Key insight
Without DMARC, SPF and DKIM produce a result but no instruction.
A receiver that sees an SPF fail on mail from a domain with no DMARC record has no published guidance from the domain owner and falls back to its own filtering. DMARC turns that silent result into a decision the receiver is asked to act on.
How a DMARC record is built, tag by tag
A DMARC record is a single TXT record at _dmarc.<domain> made of semicolon-separated tag=value pairs, and only two of them, v and p, are required. An enforcing record with both report types looks like this:
_dmarc.example.com. IN TXT "v=DMARC1; p=reject; sp=reject; rua=mailto:dmarc-agg@example.com; ruf=mailto:dmarc-fail@example.com; pct=100; adkim=s; aspf=r; fo=1"
v=DMARC1 must come first. Every other tag has a default in RFC 7489 (and in RFC 9989, which keeps the same record format), so the minimal record v=DMARC1; p=none; rua=mailto:reports@example.com is valid and is the usual starting point.
| Tag | Purpose | Values | RFC 7489 default |
v | Protocol version; must be the first tag | DMARC1 | Required |
p | Policy for the domain itself | none, quarantine, reject | Required |
sp | Policy for subdomains of the organizational domain | none, quarantine, reject | Same as p |
rua | Where aggregate (XML summary) reports are sent | One or more mailto: URIs, comma-separated | No reports sent |
ruf | Where per-message failure reports are sent | One or more mailto: URIs | No reports sent |
pct | Percentage of the domain's mail stream the policy is applied to; removed in RFC 9989 | Integer 0 to 100 | 100 |
adkim | DKIM alignment mode | r (relaxed), s (strict) | r |
aspf | SPF alignment mode | r (relaxed), s (strict) | r |
fo | Which failures trigger a failure report; ignored unless ruf is set | 0, 1, d, s (colon-separated to combine) | 0 |
Three details in the table cause trouble. The sp tag is ignored in a record published on a subdomain: a receiver looks up the exact From domain first and uses that record's p as-is, and only consults the organizational domain (the registered domain, such as example.com) when the subdomain has no record of its own. The fo values decide when a failure report is generated: 0 reports only when neither SPF nor DKIM produced an aligned pass, 1 reports when either one did not, d reports any DKIM signature that failed verification and s any SPF failure, regardless of alignment. Receivers may ignore the requested options.
The third detail concerns reporting addresses: a rua address at a different domain than the one publishing the record requires that other domain to publish an authorization TXT record at <yourdomain>._report._dmarc.<reportdomain>, or receivers drop the reports. The DMARC record generator assembles the TXT string from the tags selected, and the domain owner copies the result into DNS; it also supports the np tag (policy for non-existent subdomains, from RFC 9091 and now RFC 9989) and the t tag (test mode, new in RFC 9989), neither of which is in RFC 7489.
The three DMARC policy levels: none, quarantine and reject
A DMARC policy is the value of the p tag, and it is the only part of the record that changes what happens to a failing message.
| DMARC policy | What the receiver is asked to do with failing mail | Does it stop spoofing? |
p=none | Deliver normally; take no action based on DMARC; send reports if rua is set | No. Monitoring only |
p=quarantine | Treat as suspicious, typically by placing it in spam or junk | Partly. Handling varies by receiver |
p=reject | Refuse the message, normally during the SMTP transaction; it is not delivered | Yes, at receivers that honor the policy |
p=none is a monitoring mode. It changes nothing about delivery, which makes it the safe first step for a domain that has never published DMARC: reports arrive, the owner learns which systems send in its name, and no legitimate mail is at risk. It provides no protection while it stays in place.
p=quarantine asks receivers to treat failing mail as suspicious. RFC 7489 lists spam-folder placement, closer scrutiny or a suspicious flag as acceptable ways to do that, and spam-folder placement is the common outcome. Because each receiver decides what quarantine means, some spoofed mail can still reach an inbox.
p=reject asks receivers to refuse the message outright, usually during the SMTP transaction, so it never reaches a mailbox. Reject is the only level that consistently stops a spoofed message, and it is also the level where a misconfigured legitimate sender stops delivering entirely, which is why the rollout takes weeks rather than minutes.
Key insight
Only quarantine and reject stop spoofing; p=none is a listening post.
A domain that has been at p=none for a year has a DMARC record and no DMARC protection. Truvo's domain scan flags p=none as a gap for that reason, and security questionnaires commonly ask which policy is enforced.
How DMARC alignment works: relaxed vs strict, and why either SPF or DKIM is enough
DMARC alignment connects the domain a recipient sees to the domain that was authenticated, and a message passes DMARC when at least one of SPF or DKIM both passes and aligns. Both are not required. This is a frequently misread part of the specification and the reason forwarded mail can still pass.
Two identifiers are compared against the From header domain:
- SPF's identifier is the domain in the SMTP envelope sender (
MAIL FROM, also seen as the Return-Path). SPF must pass for that domain, and that domain must align with the From header. - DKIM's identifier is the domain in the
d=tag of a DKIM signature that verified. That domain must align with the From header.
| Alignment mode | Rule | Passes | Fails |
Relaxed (r, default) | Authenticated domain and From domain share the same organizational domain | From example.com, DKIM d=mail.example.com | From example.com, DKIM d=example.net |
Strict (s) | Authenticated domain and From domain match exactly | From example.com, DKIM d=example.com | From example.com, DKIM d=mail.example.com |
The organizational domain is the registered domain: RFC 7489 finds it with the Public Suffix List, and RFC 9989 replaces that with a DNS tree walk up from the From domain, but in both cases newsletter.example.com and example.com share one, while example.co.uk and example.com do not. Relaxed is where many domains stay, because third-party senders (marketing platforms, help desks, invoicing tools) often sign or send with a subdomain. Strict alignment is a hardening step for domains that control every sender.
Forwarding shows why the either-mechanism rule matters. A forwarding server's IP is not in the original domain's SPF record, so SPF fails or does not align; the DKIM signature travels with the message, still verifies and still aligns, so DMARC passes.
An SPF checker shows which senders a domain's SPF record authorizes and how the record terminates, which is the first thing to review when reports show SPF failures from a known sender. The companion posts on what an SPF record is and what DKIM is cover each mechanism's own rules.
What DMARC aggregate and failure reports contain
DMARC aggregate reports (rua) are what make enforcement safe to reach, because they list every source sending as the domain along with its authentication results. Without them, a domain owner is guessing which systems send in its name.
An aggregate report is an XML file, usually gzipped and emailed by each reporting receiver at a default interval of one day (hourly can be requested), containing:
- Report metadata: the receiver, the date range and a report ID.
- The policy the receiver saw: the
p,sp,pct,adkimandaspfvalues it applied. - One record per sending source: the sending IP, the message count, the disposition applied, and the raw and aligned SPF and DKIM results, including the domain each one authenticated.
A few weeks of aggregate reports answer the rollout questions: which IPs send as this domain, which pass aligned SPF or DKIM, which are misconfigured legitimate services, and which are spoofers.
Failure reports (ruf) are per-message reports containing some or all of a failing message. The specification leaves failure reporting to each receiver's privacy policy, and in practice few receivers send them and those that do may redact content. They help debug one sender's DKIM setup; they are not a primary data source.
The DMARC rollout playbook: from p=none to p=reject with pct staging
Moving a domain from no DMARC to p=reject is a staged process that uses reports to find every legitimate sender before any mail is blocked, and it typically takes several weeks because the reports have to cover a full cycle of sending.
- Publish SPF and DKIM for every legitimate sender first. With neither in place, every message fails alignment. The mail platform, marketing tool, support desk, billing system and any application that sends email all count.
- Publish
v=DMARC1; p=none; rua=mailto:.... Delivery does not change. Reports usually start arriving within a day or two. - Read the reports long enough to cover monthly and quarterly sending. Inventory every source. For each legitimate one, fix alignment: add it to SPF if it uses the domain in the envelope, or configure DKIM signing with a
d=on the organizational domain. - Move to
p=quarantine; pct=10. Ten percent of failing mail is quarantined; the rest is handled under the next lower policy (none). Raisepctin steps (25, 50, 100) as reports stay clean. - Move to
p=reject; pct=10and repeat the climb. With reject and a partialpct, the sampled share is rejected and the remainder is quarantined. End atp=rejectwithpct=100, or with the tag removed since 100 is the default. RFC 9989 dropspctin favor of at=ytest-mode flag, so receivers that have adopted the new specification ignore the percentage; treat the staged climb as best-effort and let the reports, not the sampling, decide when to move. - Set
sp=deliberately. Subdomains that never send mail can go straight tosp=reject; subdomains that do send need the same inventory work. - Keep reading the reports after reject. New SaaS tools get added, vendors change sending infrastructure, and a sender that stops aligning starts bouncing.
Key insight
Publish the record, then confirm it resolves.
After each change, a passive lookup with a DMARC checker confirms the record exists at _dmarc.<domain>, shows which policy it declares and whether a rua address is present, without sending any mail. A typo in the tag syntax leaves a domain with no effective DMARC and no error message.
When a DMARC reporting vendor is worth paying for
A DMARC reporting vendor turns raw aggregate XML into a dashboard, and whether that is worth paying for depends mainly on how many sending sources a domain has. Aggregate reports arrive daily from every reporting receiver; a domain with moderate mail volume can receive dozens per day, and nobody reads that by hand for long.
Vendors parse the XML, resolve sending IPs to named services, chart pass and fail rates over time and flag new sources. Some add hosted DMARC, where the _dmarc record is delegated to the vendor so policy changes happen in a console rather than in DNS.
A domain with one mail platform and two or three SaaS senders can reach p=reject with a free or low-cost parser, of which several exist. A domain with many subdomains, regional mail platforms, acquisitions and a long tail of transactional senders benefits from a paid tool, because source identification and change alerting are continuous work. The record and the policy cost nothing either way.
Common DMARC mistakes that leave a domain unprotected or block real mail
The mistakes below come up repeatedly in the domain scans Truvo runs and in DMARC rollouts that stalled.
- Staying at
p=noneindefinitely. The record exists, reports go unread, and spoofing is not stopped. - Publishing
p=rejectwith no reports and no sender inventory. Legitimate mail from an unlisted sender is bounced. - Publishing the record at the wrong name. DMARC lives at
_dmarc.example.com, not atexample.com. A record at the apex is ignored. - Assuming SPF alone will align. Forwarded mail and many third-party senders fail SPF alignment; DKIM signing on the organizational domain carries them through.
- Sending
ruato another domain without the authorization record. Reports are dropped and the owner concludes nobody is sending. - Ignoring subdomains.
spunset means subdomains inheritp, which is fine at reject and a hole at none.
For companies under SOC 2 or ISO 27001 review, the DMARC checker maps each finding to SOC 2 CC6.1, CC6.7 and CC7.2 and to ISO 27001:2022 A.5.14 and A.8.20; an enforcing record with reporting is evidence for those controls, and a missing or p=none record is a gap an auditor is likely to ask about. The guide to SOC 2 CC6.7 on data transmission covers what that criterion expects more broadly.
DMARC and the standards around it: RFC 7489, RFC 9989 and BIMI
RFC 7489 defined DMARC in March 2015 as an Informational RFC, and RFC 9989 replaced it in May 2026 as a Proposed Standard. RFC 7489 was Informational rather than Standards Track because it described a protocol already deployed by large mailbox providers before the IETF took it up. The successor, developed under the name DMARCbis, was published as three documents: RFC 9989 for the core mechanism, RFC 9990 for aggregate reporting and RFC 9991 for failure reporting. RFC 9989 obsoletes both RFC 7489 and RFC 9091.
The record format is unchanged, so a record written for RFC 7489 keeps working. The changes that matter to a domain owner are the removal of pct, the addition of np (a policy for non-existent subdomains) and t (a test-mode flag that replaces pct sampling), and the switch from the Public Suffix List to a DNS tree walk for finding the organizational domain. Receivers are moving to the new specification at their own pace, so both sets of rules are in play for now.
BIMI is the visible payoff of an enforcing DMARC policy: it lets a mailbox provider display a verified brand logo next to authenticated mail, and it requires quarantine or reject first. The post on what BIMI is covers its requirements. The Truvo free security tools hub collects the DMARC, SPF, DKIM and MX lookups referenced in this guide.
Move DMARC to reject without breaking mail
Truvo runs the rollout as part of an effective security program and hands over the evidence.
Frequently asked questions about DMARC
What is the difference between DMARC none and quarantine?
p=none tells receivers to deliver failing mail normally and only send reports, so the domain owner sees spoofing attempts without stopping any. p=quarantine tells receivers to treat failing mail as suspicious, which usually means the spam folder. None is for discovering senders; quarantine is the first level that changes what a recipient experiences.
Does DMARC require both SPF and DKIM to pass?
No. A message passes DMARC when either SPF or DKIM passes and the domain it authenticated aligns with the From header domain. Publishing both is still the norm, because SPF breaks on forwarded mail and DKIM depends on every sender signing correctly.
What is RFC 7489, and has it been replaced?
RFC 7489 is the IETF document that first defined DMARC. It was published in March 2015 as an Informational RFC and specifies the _dmarc TXT record, its tags, the alignment rules and the report formats. In May 2026 the IETF published RFC 9989 as a Proposed Standard that obsoletes RFC 7489, with reporting split into RFC 9990 and RFC 9991. The record format is the same; pct is removed and np and t are added.
How long should a domain stay at p=none?
Long enough for aggregate reports to show every legitimate sending source, including the ones that send monthly or quarterly, and for each source to be fixed so it passes aligned SPF or DKIM. For many domains that is a few weeks to a couple of months. Staying at p=none after the inventory is clean provides no protection.
What does pct do in a DMARC record?
pct sets the percentage of failing messages the declared policy is applied to, from 0 to 100, with 100 as the default. Messages outside the sampled share receive the next lower policy: under p=reject; pct=25, one quarter of failing mail is rejected and the rest is quarantined.
Ready to Start Your Compliance Journey?
Get a clear, actionable roadmap with our readiness assessment.
Contact Us
Free Report: The CPCSC Compliance Playbook
Join the waitlist for a free copy when it's released.
About the Author
Former security architect for Bank of Canada and Payments Canada. 20+ years building compliance programs for critical infrastructure.