The Bouncer's Guide to DMARC: Securing Your Email Domain
DMARC is the bouncer for your email domain. A practical guide to SPF, DKIM, DMARC alignment, and the policy escalation from p=none to p=reject.
TL;DR
DMARC is the bouncer at your domain’s door. SPF is the guest list of IP addresses you’ve vouched for. DKIM is the wax seal, a cryptographic signature only you can forge. The bouncer checks both, applies your policy, and either waves the message through, sends it to junk, or refuses entry. Here’s what each role does at the door and where things typically go wrong.
What the bouncer is doing
Picture a private club. The guest list is on a clipboard. The invitations have a wax seal only the club owner’s iron can make. At the door: is this person on the list, and does the seal match our iron? Either clears them. Both failing? They’re out.
That’s DMARC.
The clipboard is SPF: a DNS record listing the IP addresses allowed to send mail as you. The wax seal is DKIM: a cryptographic signature on the message that the receiver verifies against a public key in your DNS. DMARC is the policy on the door: what to do when a message claiming to be from your domain fails both checks. Wave through (p=none), send to junk (p=quarantine), or refuse entry (p=reject).
SPF: the guest list
SPF is a single TXT record at your apex domain. Something like v=spf1 include:spf.protection.outlook.com include:_spf.google.com ~all. Each include: is a sub-list maintained by a sending platform. Microsoft adds Exchange Online IPs. Google adds Workspace IPs. You add Mailchimp, your CRM, your invoicing tool, and any other sending platform.
Two things go wrong here consistently.
Alignment. SPF passes when the delivering IP is on your list. But DMARC also requires that the domain in the SMTP envelope sender lines up with the visible From: header. That’s alignment: the difference between “this IP is allowed to send for somebody” and “for you.” Mailchimp historically broke this because their envelope sender used mcsv.net, not your domain. The fix is to sign with your DKIM and take alignment from there instead.
The 10-lookup limit. SPF caps at ten DNS lookups. Microsoft 365 burns three by itself. Add Google Workspace, Mailchimp, and a transactional relay and help desk platform, and you’re past the ceiling. Past 10, receivers return PermError and SPF fails entirely. The fix is SPF flattening: replacing include: chains with actual IP ranges.
DKIM: the wax seal
DKIM is the cryptographic seal. The sending server signs the message headers with a private key. The receiver fetches your public key from DNS (at something like selector1._domainkey.yourdomain.co.za) and verifies the signature.
The selector is the name in the DNS path. M365 publishes two: selector1 and selector2, as CNAMEs to Microsoft-hosted targets. The two-selector setup allows key rotation without breaking signing. Google Workspace defaults to the google selector. Mailchimp uses k1._domainkey. Every platform publishes its own, and all need to be live simultaneously.
Alignment: the signing domain in the DKIM signature (the d= tag) has to line up with the visible From: header. Sign as mcsv.net and alignment fails for your domain.
The most common Google Workspace failure we see: DKIM generated in the Admin Console but never enabled. The public key is in DNS, the platform isn’t actually signing. Two clicks fix it. The M365 equivalent is forgetting to turn signing on in the Defender portal after adding a new custom domain. Easy to miss, happens a lot.
When the bouncer turns someone away
A message authenticates if SPF passes and aligns, or DKIM passes and aligns. Either is enough. Both failing triggers the policy.
p=none is observation mode. The bouncer notes failures and sends you reports, but lets everyone through. Useful in the audit phase. Useless as a security control. If your domain sits at p=none permanently, spoofers can send as you and receivers will deliver it without complaint.
p=quarantine sends failing mail to junk. The recipient might still find it. Useful as a step, not a destination.
p=reject is the real bouncer. Failing mail gets refused at the SMTP layer before it lands. The spoofer gets a bounce; the recipient never sees the message.
The escalation from p=none to p=reject
Weeks 1–2: p=none with reporting on. Publish the record with an rua= address pointing at a reporting endpoint that parses the XML. The point is to harvest reports. Receivers send data on every IP claiming your domain. Marketing will be in there. So will at least one tool nobody remembers.
Weeks 3–6: alignment work. Walk every sender in the reports. Get SPF includes right. Turn on DKIM signing at every platform. Rotate any 1024-bit DKIM keys to 2048. Trim or flatten SPF if you’re near the ceiling.
Weeks 7–8: p=quarantine with pct=10. The pct= tag tells receivers to apply the policy to only 10% of failing mail. If something legitimate is still failing, only one in ten gets junked and you catch it in the next report. Step it up: pct=10, pct=50, pct=100.
Week 9 onwards: p=reject. Full enforcement. Add sp=reject so subdomains can’t be exploited. Tighten aspf=s and adkim=s if your sender estate is clean.
A small business with three to five senders can run this in four to six weeks. Mid-market with ten or more senders: three to six months. The bottleneck is almost never DNS. It’s getting straight answers from third-party vendors.
When legitimate mail gets bounced
The Christmas marketing send. A retail client moved off Mailchimp eighteen months before their DMARC deployment. Marketing kept the API key for one annual loyalty mailer (nobody mentioned it during the sender inventory). November arrived, 12,000 messages hit p=reject because Mailchimp’s SPF includes had been pulled months earlier. Fix took two hours. Ask about every annual send, not just the monthly ones.
The Sage payroll send. Finance used Sage to send payslips via SMTP relay through a gateway nobody added to SPF. Day one of p=quarantine: every payslip to junk. Two weeks of back-and-forth before payslips authenticated cleanly.
Things break at the edges. Sender drift is real and continuous. The reporting catches it, if someone is actually reading the reports.
Platform specifics
Microsoft 365. SPF: include:spf.protection.outlook.com. DKIM: selector1._domainkey and selector2._domainkey as CNAMEs. Signing must be turned on per-domain in the Defender portal.
Google Workspace. SPF: include:_spf.google.com. DKIM: the google selector, generated in Admin Console under Apps → Google Workspace → Gmail → Authenticate email. Generate, publish the key, then go back and click “Start authentication”. That second click is the one everyone forgets.
FAQ
Is p=none enough? No. Spoofers can still send as you and receivers will deliver it.
Will DMARC break my marketing emails? Only if marketing sends from a platform that isn’t authenticated. The inventory phase exists to find and fix that before policy enforces.
How long does a rollout take? Three to five senders: four to six weeks. Ten or more: three to six months.
Can I run DMARC on a domain I don’t send from? Yes, and you should. Publish v=DMARC1; p=reject; sp=reject; plus v=spf1 -all. Stops anyone using idle domains to spoof.
The bouncer needs someone watching the door
A DMARC deployment with no ongoing monitoring goes to seed within twelve months. Vendors rotate IPs without telling you. Marketing buys new tools. DKIM keys age out. Reports pile up unread and the first sign of trouble is a customer complaining their invoice didn’t arrive.
OSH offers a managed DMARC service: deployment from p=none to p=reject without losing legitimate mail, hosted RUA endpoints, alerting on new senders, and a monthly summary written for humans, not log parsers. Details at /dmarc/.
The bouncer doesn’t take Fridays off. Neither should the people watching the door.