SPF vs DKIM vs DMARC: what each one proves.

Three acronyms that get listed together as if they were one thing. They answer three different questions, each has a hole the others cover, and the order you set them up in matters.

Published 2026-09-16 · 7 min read · Kirk Diamond

The one-line version

MechanismQuestion it answersChecked againstLives in
SPFIs this server allowed to send mail for this domain?The connecting IP address and the SMTP envelope sender (MAIL FROM)A TXT record on the domain
DKIMWas this message signed by someone holding the domain's key, and is it unchanged?A signature in the headers, verified with a public key in DNSA TXT record under selector._domainkey
DMARCDo SPF or DKIM line up with the address the reader sees, and what should happen if not?The From: header domainA TXT record at _dmarc

SPF: the sending server

SPF is a list of IP addresses (directly, or via include and mx terms that resolve to addresses) that are allowed to deliver mail claiming to be from your domain. The receiver looks at the IP that connected to it and the domain in the SMTP envelope's MAIL FROM (also called the return path or bounce address), and checks whether the one is in the other's list.

Two holes. First, SPF says nothing about the From: header, which is the address a person actually sees. A spammer can pass SPF for their own domain in the envelope and put your domain in the header, and SPF alone is satisfied. Second, SPF breaks on forwarding. When a mailing list or a personal forwarding rule passes your message on, the connecting IP is now the forwarder's, not yours, and SPF fails through no fault of the sender. There is also the practical hole: the ten lookup limit, which turns a valid-looking record into a PermError.

DKIM: the message itself

DKIM signs the message. The sending server computes a hash over the body and a chosen set of headers (From, Subject, Date and so on), signs it with a private key, and adds the signature as a DKIM-Signature header along with the domain (d=) and the selector (s=). The receiver fetches the public key from selector._domainkey.domain and verifies. A pass means the message was signed by someone with the key and the signed parts have not been altered since.

Because the signature travels with the message, DKIM survives forwarding, which is exactly where SPF falls over. Its holes are different. It proves the d= domain signed the message, but nothing forces d= to match the From: header; a spammer can sign with their own domain and put yours in the header. And a mailing list that rewrites the subject or appends a footer breaks the signature, unless the list re-signs with its own domain (most now do, which is why DMARC has to think about alignment rather than just pass or fail).

DKIM also has an operational hole that SPF does not: the key is per sending service. Your own mail server, your marketing platform, your helpdesk and your billing system each need their own selector and key published, and each one someone forgets is a service whose mail fails DMARC. The DKIM checker probes the common selector names; custom ones you will find in the s= tag of a real message.

DMARC: alignment and policy

DMARC is what ties the first two to the address the reader sees. It asks two things. Does at least one of SPF and DKIM pass and align, meaning the domain it authenticated matches the From: header domain? And if neither does, what does the domain owner want the receiver to do: nothing (p=none), send it to spam (quarantine) or refuse it (reject)?

Alignment is the part people miss. SPF can pass for the envelope domain and still fail DMARC because the envelope domain is your marketing provider's bounce domain, not yours. DKIM can pass for d=mailprovider.com and fail DMARC because the header says @yourdomain.com. Getting DMARC to pass means configuring each service to use your domain (or a subdomain of it, in relaxed mode) for the return path or the DKIM d=, which is the "custom domain" or "domain authentication" step every provider offers and many people skip.

DMARC also gives you the reports. The rua= address receives a daily aggregate from every large receiver saying which IPs sent mail as your domain and whether it passed. This is how you find the service nobody told you about, and it is why you start at p=none: not because none is a policy worth having, but because the reports are. DMARC none vs quarantine vs reject covers moving up.

How they cover for one another

The order to set them up

  1. DKIM for every service that sends. This is the one that survives everything and the one that takes longest to get complete. Do it first.
  2. SPF for the services where you can. Keep the lookup count comfortably under ten; do not chase completeness at the expense of a PermError.
  3. DMARC at p=none with a rua address and read the reports for two or three weeks. Fix the alignment gaps they show.
  4. Move to quarantine, then reject, using pct= to ramp if the volume is large.

The email deliverability checker reports all three for a domain with the reasoning behind each finding, and the domain health checker includes the same email pillar alongside DNS, TLS and HTTP if you want the wider picture.

All guides · All tools