DMARC: From p=none to p=reject, Safely
The alignment work between p=none and p=reject is the real DMARC project.
Loading...
The alignment work between p=none and p=reject is the real DMARC project.
SPF answers 'is this sending IP authorised?' DKIM answers 'has this message been tampered with since it was signed?' DMARC is the glue: it requires that at least one of those checks pass AND that the authenticated identity aligns with the From: header domain the user sees. That alignment step is the part that defeats spoofing - an attacker who owns attacker.com can sign their mail with DKIM and send from a permitted IP, but they cannot align either signature with your From: domain.
DMARC then publishes a policy - none, quarantine, or reject - telling receiving servers what to do when alignment fails. And it publishes a reporting address so you see what is happening.
Ship DMARC in monitor mode first. p=none applies no enforcement but mandates reports. Once you have two to four weeks of aggregate reports, you know every system that sends from your domain.
_dmarc.example.com. IN TXT "v=DMARC1; p=none; rua=mailto:[email protected]; adkim=r; aspf=r; pct=100"Your first two weeks of DMARC reports will surprise you. They will list marketing platforms you forgot about (Mailchimp, Klaviyo, Customer.io), transactional senders (SendGrid, Postmark, SES), HR and payroll systems, expense tools, monitoring alerts - every system that was configured years ago to send 'from' your domain.
For each sender, answer:
DKIM is the more forgiving of the two authentication mechanisms - it survives forwarding, mailing lists often preserve it, and it provides an aligned identity without requiring you to declare every IP. Aim for 100% DKIM coverage before tightening the DMARC policy.
selector1._domainkey.example.com. IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..."Rotate DKIM keys at least annually. 2048-bit RSA is the current minimum; Ed25519 is supported by a growing share of receivers and produces smaller DNS records.
SPF has a 10-DNS-lookup limit. Every include: counts. Every a and mx counts. Exceed ten and the record evaluates to permerror, which DMARC treats as a fail. An SPF record accumulated over years almost certainly exceeds the limit.
dig +short TXT example.com | grep spf1
# Then walk each include: recursively and count lookups.
# Tools: spflint, dmarcian SPF Surveyor, MxToolbox SPF check.Options to stay under 10:
Use pct= to apply the policy to a fraction of failing mail. Start at pct=10 - 10% of alignment failures go to quarantine, 90% go through. Check reports. Ramp up over weeks.
; Stage 4a
_dmarc TXT "v=DMARC1; p=quarantine; pct=10; rua=mailto:[email protected]; adkim=r; aspf=r"
; Stage 4b
_dmarc TXT "v=DMARC1; p=quarantine; pct=50; rua=mailto:[email protected]; adkim=r; aspf=r"
; Stage 4c
_dmarc TXT "v=DMARC1; p=quarantine; pct=100; rua=mailto:[email protected]; adkim=r; aspf=r"Once you have been on p=quarantine; pct=100 for at least two weeks with no new senders appearing in reports and no complaints from users, promote to p=reject. You can ramp through pct= again if you want a safety margin, but the conservative path is: if quarantine was clean, reject will be too.
_dmarc.example.com. IN TXT "v=DMARC1; p=reject; rua=mailto:[email protected]; adkim=s; aspf=s; pct=100"Rarely. ruf reports include full message headers of failing messages, which most large senders don't emit (privacy). The useful signal is in rua aggregate reports. Skip ruf unless you have a specific incident to investigate.
For a small domain with one or two senders, a week is enough. For a mid-sized company with accumulated sender sprawl, six to twelve weeks is typical. The slowness is almost always on the SPF/DKIM side - finding and fixing every legitimate sender.
Yes. sp= sets the policy for subdomains that do not publish their own _dmarc record. Typical pattern is p=reject; sp=reject once you are mature. While ramping, you can keep sp=none so subdomain experimentation does not get hard-rejected.