SPF, DKIM, and DMARC explained: what each one actually verifies
Email's original design lets anyone put any address in the From field. Three DNS based protocols were layered on to fix that, and they are routinely misunderstood because each one verifies something narrower than people assume. SPF does not check the From address. DKIM does not check who sent the message. Only DMARC ties anything to the address a recipient actually sees, and it cannot work without at least one of the other two. Here is what each one really proves, and how to set up all three correctly.
SPF: is this IP allowed to send for this domain
SPF is a TXT record on your domain listing the IP addresses permitted to send mail for it:
yourdomain.com. TXT "v=spf1 ip4:203.0.113.10 include:_spf.google.com ~all"
When a server receives a message, it looks at the domain in the envelope sender (the SMTP MAIL FROM, visible later as the Return-Path header) and checks whether the connecting IP appears in that domain's SPF record. The ~all at the end says how to treat everything unlisted: ~all (softfail) is the conventional choice, -all (hard fail) is stricter.
The crucial limitation: SPF checks the envelope sender, not the From header. A spammer can pass SPF cleanly by using their own domain in the envelope while displaying yours in the From field. SPF also breaks when mail is forwarded, because the forwarder's IP is not in your record. SPF alone has never stopped From spoofing; it was never built to.
DKIM: was this message signed by this domain and left unmodified
DKIM is cryptographic rather than path based. Your sending server signs each outgoing message with a private key, covering a hash of the body and a chosen set of headers (From is always included). The signature travels in a DKIM-Signature header:
DKIM-Signature: v=1; a=rsa-sha256; d=yourdomain.com; s=mail2026;
h=from:to:subject:date; bh=...; b=...
The receiver takes the selector (s=) and domain (d=), fetches the public key from DNS at mail2026._domainkey.yourdomain.com, and verifies the signature. A pass proves two things: a server holding the private key for d=yourdomain.com signed this message, and the signed parts were not altered in transit. Because the proof rides inside the message, it survives forwarding, which SPF does not.
The limitation mirrors SPF's: nothing requires the d= domain to match the From header. A message can carry a valid DKIM signature from bulksender.example while displaying From: ceo@yourdomain.com. A real pass, for an irrelevant domain.
DMARC: does an authenticated domain match the visible From
DMARC closes the loop. It is a TXT record at _dmarc.yourdomain.com:
_dmarc.yourdomain.com. TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc@yourdomain.com"
A message passes DMARC when at least one of SPF or DKIM passes and the domain it validated aligns with the domain in the From header. SPF passing for the envelope domain only counts if that domain matches the From domain; DKIM passing only counts if d= matches. This alignment requirement is the entire point: it is the first time anything verifies the address a human reads.
DMARC then adds two things neither predecessor had. A policy (p=) telling receivers what to do with failures: none (deliver, just report), quarantine (spam folder), or reject (refuse outright). And a reporting channel (rua=) through which receivers send daily aggregate reports of everything claiming to be your domain. Those reports are how you discover senders you forgot about before a strict policy starts blocking them.
Why you need all three
Each protocol covers another's blind spot. SPF is trivial to deploy but dies on forwarding and ignores the From header. DKIM survives forwarding and proves integrity but also ignores the From header, and breaks when mailing lists modify messages. DMARC checks the From header but produces nothing on its own; it needs an aligned SPF or DKIM pass as raw material, and it deliberately requires only one so that forwarding (which kills SPF) and list rewriting (which kills DKIM) do not each take down legitimate mail.
There is also a blunt commercial reason: Google and Yahoo require SPF or DKIM from all senders, and both plus DMARC from bulk senders. Domains without the full set increasingly land in spam regardless of content.
The record mistakes that break delivery
Multiple SPF records. A domain must have exactly one TXT record starting with v=spf1. Adding a second one (a new email provider's docs often say "add this record" without saying "merge") produces a permanent error, and receivers treat it as no SPF at all. Merge everything into one record.
Exceeding 10 DNS lookups. Every include:, a, mx, redirect, and exists mechanism in your SPF record costs a DNS lookup, recursively through nested includes, with a hard limit of 10. Past it, evaluation fails with permerror. This bites domains that accumulate providers over the years: a CRM, a marketing platform, a helpdesk, each pulling in nested includes. The SPF generator counts lookups as you build the record.
Weak or stale DKIM keys. 1024 bit RSA keys are below current standards; use 2048. And rotate selectors occasionally: a selector created in 2018 and never touched is a quiet liability, since anyone who ever obtained that private key can still sign as you.
A DMARC policy with no monitoring. Publishing p=reject on day one, before reading a single aggregate report, is how organizations discover their invoicing system by way of its mail being refused.
A minimal correct setup
For a domain sending through one provider, the whole thing is four DNS records and a waiting period.
- SPF. One TXT record at the domain root:
v=spf1 include:<your provider's include> ~all. Build and validate it with the SPF generator. - DKIM. Generate a 2048 bit key pair with the DKIM generator, publish the public key at
<selector>._domainkey.yourdomain.com, and configure the private key in your mail provider. Most hosted providers generate the pair for you and just hand you the DNS record; use theirs when offered. - DMARC. Start observational:
v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com, built with the DMARC generator. Nothing about delivery changes yet; you are collecting evidence. - Read the reports for a few weeks, align every legitimate source you find, then tighten to
p=quarantineand eventuallyp=reject.
After publishing, verify the records resolve correctly from the outside; the email health checker checks all three in one pass. The end state is a domain where receivers can verify your mail cryptographically, refuse forgeries outright, and tell you about every attempt. Three records, none of them complicated, and most of the work is the patience between steps.