SPF, DKIM, and DMARC: Stop People Sending Email as Your Domain
TL;DR
Without SPF, DKIM, and DMARC, anyone on the internet can send email that looks like it came from your domain. That is exactly how invoice fraud, supplier scams, and staff phishing get their credibility. These three DNS records fix it: SPF lists who is allowed to send for you, DKIM cryptographically signs your mail, and DMARC ties the two together, tells the world what to do with fakes, and reports who is trying.
- Set up properly, criminals can no longer convincingly spoof your domain. Left unset, they can, trivially.
- SPF = your list of approved senders. DKIM = a tamper-proof signature. DMARC = the enforcement policy plus reporting.
- The concept that trips everyone up is alignment: the checks have to match your visible From domain, or DMARC still fails.
- Do not leap to enforcement. The safe path is
p=nonewhile you monitor, thenp=quarantine, thenp=reject, checking your real mail flows at every step.
Now for the more technical explanation
The problem these solve
Plain email has no built-in proof of who sent it. The “From” address you see is just text an attacker can type. So without authentication, anyone can send a message that appears to come from [email protected], and the receiving server has no way to know it is fake. SPF, DKIM, and DMARC add that missing proof, published as DNS records on your domain.
SPF: who is allowed to send
SPF (Sender Policy Framework) is a DNS TXT record listing the servers and services permitted to send email for your domain. A receiving server checks whether the sending server’s IP is on that list.
- It looks like:
v=spf1 include:spf.protection.outlook.com include:_spf.yoursender.com -all. - The
-allat the end means “anything not listed, fail.” Use-all(hard fail). Avoid~all(soft fail) long term, and never+all(which authorises the whole internet). - SPF checks the envelope sender (the hidden return-path), not the visible From, which matters for alignment later.
The big SPF trap: the 10-lookup limit. SPF is only allowed 10 DNS lookups to resolve all those include: mechanisms. Stack up a few cloud senders and you blow past it, at which point SPF returns a permerror and effectively stops working. Keep your includes lean, flatten where you must, and audit them.
Other SPF mistakes: more than one SPF record on a domain (invalid, only ever have one), and forgetting a legitimate sender so its mail fails.
DKIM: a tamper-proof signature
DKIM (DomainKeys Identified Mail) cryptographically signs each outgoing message. Your mail server signs with a private key; the matching public key is published in DNS under a selector (like selector1._domainkey.yourdomain.com). The receiver verifies the signature.
- It proves the message genuinely came from your domain and was not altered in transit.
- Use 2048-bit keys where supported, and rotate keys periodically.
- Because DKIM signs the message itself rather than checking the sending IP, it survives forwarding, which SPF does not (more on that below). That makes DKIM the more robust of the two.
DMARC: the policy and the reports
DMARC (Domain-based Message Authentication, Reporting and Conformance) is where it all comes together. It is a DNS TXT record at _dmarc.yourdomain.com that does three things:
- Requires that SPF and/or DKIM pass with alignment (below).
- Tells receivers what to do when a message fails:
p=none(do nothing, just report),p=quarantine(junk it), orp=reject(refuse it). - Sends you reports so you can see who is sending as your domain, legitimate or not.
A record looks like: v=DMARC1; p=none; rua=mailto:[email protected]; fo=1.
The concept everyone misses: alignment
This is the part that catches people out. DMARC does not just want SPF or DKIM to pass; it wants them to pass for the domain in the visible From address.
- SPF alignment: the envelope-sender domain matches the From domain.
- DKIM alignment: the domain in the DKIM signature matches the From domain.
You need at least one of them to pass and align. This is why “SPF passes” on its own is not enough: a message can pass SPF for some other domain while spoofing yours in the From line. Alignment is what closes that gap, and it is the reason DMARC is the piece that actually stops spoofing.
How do you set up DMARC without breaking your own email?
Do not turn on p=reject and hope. Do not park at p=none forever either (which is the single most common failure, a DMARC record that never actually enforces anything). The disciplined path, and the one I recommend, is three stages:
Stage 1: p=none, and monitor thoroughly for a few weeks.
Publish DMARC at p=none with an rua reporting address. Nothing is blocked yet. Spend the time reading the aggregate reports and building a complete picture of every legitimate sender: your mail platform (for example Microsoft 365), marketing tools, CRM, helpdesk and ticketing, accounting software, scan-to-email devices, and anything else that sends as you. For each one, make sure it passes SPF or DKIM with alignment. Fix the ones that do not.
Stage 2: once the reports are clean, move to p=quarantine for a few weeks, and keep a close eye.
When your legitimate mail is all authenticating and aligning, and you understand the failing traffic, step up to p=quarantine. Now failing mail lands in junk rather than the inbox. Watch closely for anything legitimate that slips into quarantine (a forgotten sender, a forwarding path) and fix it. If you want to ease in, pct= lets you apply the policy to a percentage of mail first.
Stage 3: p=reject.
Once quarantine has been quiet and clean, move to p=reject. Failing mail is now refused outright. This is the goal, because it is the only setting that genuinely stops criminals delivering mail as your domain. Everything before it is preparation.
The whole point of the staged approach is to reach p=reject without ever blocking your own legitimate email, and to do it with evidence rather than guesswork.
The pitfalls that break it
- The SPF 10-lookup limit (covered above): the silent killer once you add a few cloud senders.
- Forgotten third-party senders: the marketing platform, the CRM, the invoicing tool, the helpdesk. Each one sends as you and must be authenticated, or it fails once you enforce. The
p=nonemonitoring stage exists precisely to find these. - Forwarding breaks SPF. When a message is forwarded, the forwarding server becomes the new sender, so SPF fails at the destination. DKIM survives forwarding because it signs the message itself, which is why you want DKIM aligned, not just SPF.
- Subdomains: DMARC applies to subdomains too. Use
sp=to set a policy for subdomains, and do not forget domains you own but do not send from (park them atp=rejectwith an empty SPF so nobody can spoof them). - Multiple SPF records or
+all: both quietly defeat the point.
Reading the reports
DMARC’s rua aggregate reports are XML and not pleasant to read by hand, so use an analyser (there are several free and paid DMARC reporting services) to turn them into readable dashboards of who is sending as you, what is passing, and what is failing. This is how you find your legitimate senders during p=none, and how you keep an eye on things through p=quarantine. For quick spot checks of your own records, a DNS lookup tool or a simple DKIM selector check does the job.
The bonus round: MTA-STS, TLS-RPT, and BIMI
Once you are at p=reject, a few extras are worth adding:
- MTA-STS: tells sending servers to require TLS when delivering to you, closing off downgrade attacks on inbound mail.
- TLS-RPT: reporting for TLS delivery problems, so you find out when encrypted delivery is failing.
- BIMI: the reward for reaching enforcement. With DMARC at quarantine or reject, BIMI lets your verified logo show next to your messages in supporting mail clients, which is both a trust signal and a nudge to finish the job.
The short version
Set all three: SPF for approved senders, DKIM for a signature that survives forwarding, and DMARC to tie them together with alignment and reporting. Then walk the staged path: p=none while you monitor for a few weeks and fix every legitimate sender, p=quarantine for a few weeks with a close eye, then p=reject. Reaching reject is the whole point, because it is the only setting that actually stops people sending email as you, and the staging is what gets you there without breaking your own mail.
Related
- Checking your DKIM selectors quickly (a ready-made PowerShell script)
- The Conditional Access policies every Microsoft 365 tenant should have
Written by Tom Langston, IT Infrastructure and Cybersecurity.