SPF, DKIM and DMARC are three small records you publish in your domain's DNS, and together they answer one question for every mail server that receives a message claiming to be from you: is this real? SPF publishes the list of servers allowed to send on your behalf. DKIM attaches a cryptographic signature that proves the message came from your domain and was not altered on the way. DMARC ties the first two to the address the reader actually sees, tells receiving servers what to do when that link fails, and sends you a daily report of everything sent in your name. You do not need all three to send email, but without them your mail is unproven and anyone can put your domain in the From line of theirs.
If you only ever use Gmail, Outlook or iCloud, your provider has set these up already. Understanding them is still worth a few minutes, because they are the only part of an email that is genuinely hard to fake. If you own a domain — for a business, a side project, or an app that sends verification emails — they are the difference between the inbox and the spam folder.
The problem all three solve
SMTP, the protocol that moves mail between servers, has no built-in way to check who a message is from. The From line you see is plain text the sender writes, exactly like the return address on a paper envelope: you can put anything there and the post will still deliver the letter.
There is a second, hidden sender address too: the envelope sender, also called the Return-Path, which the servers negotiate with and where bounces go. It is often not the address in the From line you read, and that gap is the one SPF alone cannot close.
SPF: the list of servers allowed to send
SPF, the Sender Policy Framework, is a single TXT record naming every server that may send mail for your domain. A simple one looks like this:
v=spf1 include:_spf.google.com include:sendgrid.net ~all
How to read it
Each include: pulls in the list published by a service you use, so you need not edit anything when that provider changes its own servers; you can also list addresses directly with ip4: and ip6:. The final word covers everything not listed: -all means reject it, ~all means treat it as suspect but deliver it, and ?all means no opinion, which is the same as no policy at all.
The two things that break it
SPF has a hard limit of ten DNS lookups per evaluation, and every include: costs at least one — the services you include have includes of their own. Pile up five or six vendors and the record silently stops working: receivers get an error rather than a pass, which is harder to spot than a plain failure.
The second limitation is structural. SPF checks the sending server's address against the envelope sender's domain, not against the From header. When a message is forwarded, the forwarding server becomes the sender and is almost never in the original domain's SPF list, so a perfectly genuine message fails. That is why SPF on its own was never enough.
DKIM: the signature that travels with the message
DKIM, DomainKeys Identified Mail, works the other way around. Your sending server signs each message with a private key and adds a DKIM-Signature header; you publish the matching public key in DNS, and any receiver can verify the signature itself.
The public key lives at a name built from a label called the selector: selector._domainkey.example.com. The signature header carries that selector in s= and the signing domain in d=, so the receiver knows which key to fetch, and it covers the body plus a chosen list of headers, normally From, Subject and Date.
Because the proof is inside the message, DKIM survives forwarding — which is exactly where SPF falls over. It only breaks if something changes the signed parts, and one common thing does: mailing lists that append a footer or prefix the subject invalidate the body hash.
The part to remember is d=: a valid signature can belong to a domain that has nothing to do with the brand in the From line.
DMARC: alignment, policy and reports
DMARC is the record that makes the other two mean something. It lives at _dmarc.example.com and reads like this:
v=DMARC1; p=none; rua=mailto:dmarc@example.com
Alignment is the real idea
Everything above can pass while the message is still a forgery, because SPF and DKIM both apply to domains the reader never sees — the envelope sender and the signing domain. DMARC closes that gap by requiring that at least one of them passes and matches the domain in the visible From header. By default the match is relaxed, so a subdomain counts; set aspf=s or adkim=s and it must be exact.
The policy
p=none changes nothing and only asks for reports. p=quarantine asks receivers to put failing mail in spam, and p=reject asks them to refuse it. Add sp= for a different subdomain policy, which matters because attackers like inventing subdomains.
The reports are the point of starting at none
The rua address receives aggregate XML reports once a day from the large receivers; free and paid tools turn them into a readable table. They tell you which servers are sending as your domain and whether each authenticates — including the ones you forgot, such as the invoicing tool or the marketing platform someone set up two years ago. Finding those before you enforce anything is the whole reason p=none exists.
If you are just reading email, not sending it
Your provider handles all of this, so the use of knowing it is diagnostic. Every message records the verdict in an Authentication-Results header, so when something claims to be from your bank you can check whether it authenticated and which domain it authenticated as. Paste a raw message into the email header analyzer to see the three results and the signing domain side by side; reading email headers covers the rest of what is in there.
One warning, because it catches careful people: a pass means the sender is who they claim to be, not that they are honest — a lookalike domain registered yesterday can publish perfect records for itself and pass every check. The domain name still has to be the right one, which is why the checks in spotting a phishing email start with the address rather than the headers.
If you own a domain, do it in this order
- Publish one SPF record listing every service that sends for you, ending in
~all. One record only — two SPF records on the same domain is an error, not a merge. - Turn on DKIM signing in each of those services and publish the public keys they give you.
- Publish DMARC at
p=nonewith anruaaddress and leave it for two or three weeks. - Read the reports, fix whatever is sending unauthenticated, then move to
p=quarantine, and later top=reject. - Do the same for domains you own but never send from: a parked domain should publish
v=spf1 -alland DMARCp=reject, because a domain with no mail is an easy thing to spoof.
The large mailbox providers began requiring authentication from bulk senders in 2024, with Google's threshold starting at 5,000 messages a day to Gmail addresses. Below that volume nothing is enforced, but the direction is clear.
Why mail can still go to spam with all three in place
Authentication is a floor, not a boost. Passing all three gets your message considered on its merits; it does not earn goodwill. Filters also weigh your domain's reputation and age, how many recipients mark you as spam, how many addresses bounce, and what the message looks like. A new domain that suddenly sends a thousand messages will struggle regardless of its DNS.
Two traps are worth naming. If staging sends from the production domain with no signing of its own, test mail quietly damages the reputation of the real thing and muddies your reports; give it a separate sending subdomain, as we argue in testing signup emails as a developer. And if recipients forward your mail, expect SPF to fail and DKIM to carry the pass — which only works if DKIM is actually on.
The short version
- SPF says which servers may send for your domain, checked against the hidden envelope sender. It breaks on forwarding and after ten DNS lookups.
- DKIM signs the message so the proof travels with it. Check
d=, not just whether it passed. - DMARC requires one of the other two to pass and match the From address the reader sees, sets the policy for failures, and sends you the reports.
- Start at
p=none, read the reports, then tighten. Protect your parked domains too. - A pass means the sender is genuine, not that they are trustworthy. Read the domain name first.