DMARC setup: from p=none to p=reject without losing mail
DMARC ties SPF and DKIM to the sender address your recipients actually see. It also tells other servers what to do with forgeries.
Updated: 05 November 2026
What DMARC checks
SPF and DKIM each check a domain, but not necessarily the one in the From line. DMARC (RFC 9989, successor to RFC 7489) adds that check. A message passes DMARC if at least one of these holds:
- SPF passes and the envelope domain matches the
Fromdomain. - DKIM passes and the domain in
d=matches theFromdomain.
"Matches" normally means the same organisational domain, so mail.example.com matches example.com. With aspf=s or adkim=s you require an exact match, which is rarely necessary.
If a message fails, your policy applies.
The DMARC record
DMARC is a TXT record at _dmarc under your domain:
_dmarc.example.com. TXT "v=DMARC1; p=reject; rua=mailto:dmarc@example.com"
| Tag | Meaning |
|---|---|
p= |
policy: none (monitor only), quarantine (junk folder), reject |
rua= |
address for the daily aggregate reports |
sp= |
separate policy for subdomains, otherwise p= applies |
pct= |
share of mail the policy applies to (default 100); dropped in RFC 9989, which has t=y for a test mode instead |
adkim= / aspf= |
r (relaxed, default) or s (strict) |
What the reports tell you
With rua, the large mailbox providers send you an XML file every day. It lists which IP addresses sent mail using your domain, how much, and whether SPF and DKIM lined up. Senders nobody remembered turn up, such as the old website or the survey tool. The colleague who writes from a personal account with the company address shows up too, and so do forgers using your domain for phishing.
If the report address lives on another domain, for example with an analysis service, that domain has to accept the reports. It needs a record like example.com._report._dmarc.reports.example containing v=DMARC1. Without it, compliant reporters send no reports there.
Hardly anyone enjoys reading the XML by hand. A tool such as ZwoMailHygiene's DMARC monitoring summarises the reports for you.
Getting to p=reject
Publish p=reject straight away and you may well lock out your own invoices. Going in stages is safer:
- Watch. Publish
p=nonewithruaand collect reports for two to four weeks. - Tidy up. Add every legitimate sender to SPF or, better, have it sign with DKIM for your domain. Chase down anything nobody recognises.
- Tighten. Move to
p=quarantineand keep reading the reports. - Finish.
p=rejectfor all mail.
p=none is meant for the monitoring phase and protects nobody. Since February 2024, Google and Yahoo require bulk senders to publish a DMARC record, and their messages must pass DMARC; p=none is enough for that. Google draws the line at 5,000 messages a day to Gmail accounts, Yahoo gives no number. Only quarantine or reject protects against phishing with your domain.
Common mistakes
- Two DMARC records at
_dmarc. Receivers ignore both. - A missing semicolon, or
p=rejectedinstead ofp=reject. An invalidpvalue removes the protection, and receivers treat the record asp=noneat best. p=rejectwhile the newsletter service still signs with its own domain. Those messages fail and never arrive.- Overlooked subdomains. They inherit the parent domain's policy unless they publish their own
_dmarcrecord orsp=says otherwise. If a subdomain sends mail itself, check its entries in the reports separately.
Checking DMARC
Send a test message to ZwoMailCheck. The result page lists policy, report address and subdomain rule and, more to the point, shows whether your message passes DMARC via SPF, via DKIM or not at all.