DMARC
TXT recordRFC 7489Domain-based Message Authentication, Reporting, and Conformance
DMARC (RFC 7489) builds on SPF and DKIM to give domain owners control over what receiving servers do with mail that fails authentication. A DMARC record at _dmarc.domain specifies a policy (p=none, p=quarantine, p=reject) and a reporting address (rua=). DMARC requires alignment: the From header domain must match the SPF envelope domain or the DKIM d= domain. DMARC with p=reject stops spoofing of the visible From address.
How it works
After SPF and DKIM checks complete, the receiving server reads the DMARC record from _dmarc.{From header domain}. It evaluates: did SPF pass AND is the envelope From aligned with the From header? OR did DKIM pass AND is the d= domain aligned with the From header? If at least one passes with alignment, DMARC passes and the message is delivered normally. If both fail alignment, the DMARC policy (p=) is applied. The result is written to the Authentication-Results header.
Details
DMARC connects SPF and DKIM to the From header and adds policy enforcement and reporting.
The alignment requirement is what makes DMARC powerful: SPF alignment: the envelope From domain (SMTP MAIL FROM) must match the From header domain. DKIM alignment: the d= domain in the DKIM signature must match the From header domain. A message passes DMARC if at least one of SPF or DKIM passes AND is aligned with the From header.
Alignment modes: relaxed (default): organizational domain match is sufficient. mail.example.com aligns with example.com. strict: exact domain match required. mail.example.com does NOT align with example.com.
Policies: p=none: Monitor only. No action on failures. Collect reports to understand mail flows. p=quarantine: Failed messages go to spam/junk folder. p=reject: Failed messages are rejected outright. The strongest protection.
Sub-domain policy: sp= tag overrides p= for sub-domains. Useful when the main domain sends marketing mail (p=quarantine) but sub-domains are untrusted (sp=reject).
Reporting: rua= tag: aggregate report destination (daily XML reports from ISPs). Shows pass/fail counts by source IP. ruf= tag: forensic report destination (full message samples on failure). Privacy-sensitive; many receivers do not send ruf reports.
Deployment sequence: 1. Deploy SPF with ~all 2. Deploy DKIM on all sending sources 3. Publish DMARC with p=none + rua= 4. Monitor aggregate reports for unauthorized sources 5. Move to p=quarantine once legitimate mail is 95%+ passing 6. Move to p=reject
DMARC does not protect against lookalike domains (exampl3.com vs example.com). It only protects the exact From domain listed in the DMARC record.
DNS record example
; DMARC record
; Format: _dmarc.{domain}
_dmarc.example.com. IN TXT "v=DMARC1; p=reject; rua=mailto:[email protected]; ruf=mailto:[email protected]; adkim=r; aspf=r; pct=100"
; Tag reference:
; v=DMARC1 – version (required)
; p=reject – policy: none | quarantine | reject
; sp=quarantine – subdomain policy (overrides p= for sub-domains)
; rua= – aggregate report email (daily XML digest)
; ruf= – forensic report email (individual failures, rarely sent)
; adkim=r – DKIM alignment: r=relaxed (default), s=strict
; aspf=r – SPF alignment: r=relaxed (default), s=strict
; pct=100 – apply policy to 100% of failing mail (use lower % during rollout)
; fo=1 – forensic options: 0=all fail, 1=any fail, d=DKIM fail, s=SPF failOn failure
p=none: message is delivered normally, failure is logged for reporting. p=quarantine: message is delivered to junk/spam folder. p=reject: message is refused during SMTP (550 5.7.1 Message failed DMARC policy). Many large receivers (Gmail, Outlook, Yahoo) honor p=reject strictly. Since 2024, Google and Yahoo require DMARC p=none or higher for bulk senders (>5000 emails/day) to a single domain.
Limitations
- !Does not protect against lookalike domain attacks (examp1e.com, example.org)
- !Mailing lists that rewrite From: to a list address break DMARC alignment for the original sender
- !Forensic reports (ruf=) are rarely sent by major receivers for privacy reasons
- !pct= rollout is useful but creates inconsistent behavior during transition
- !ARC (RFC 8617) was designed to preserve authentication results through legitimate forwarding, but adoption is incomplete