SPF, DKIM and DMARC Explained (and How to Check Yours)

What SPF, DKIM and DMARC each do, how they work together, why SPF breaks past 10 DNS lookups, and how to move DMARC from p=none to p=reject safely.

· 4 min read

Anyone can put your domain in the From line of an email. SMTP was designed in the 1980s and never checked. SPF, DKIM and DMARC are the three DNS records that let receiving mail servers tell real mail from forgeries, and since 2024 Gmail and Yahoo require all three from anyone sending in bulk. Here's what each one does, how they fit together, and the mistakes that quietly break them.

You can check all three for any domain with the email authentication checker. It reads the records, follows every SPF include, and explains each problem it finds.

What does SPF do?

SPF (Sender Policy Framework) is a TXT record on your domain that lists the servers allowed to send mail for it:

example.com.  TXT  "v=spf1 include:_spf.google.com include:sendgrid.net -all"

When a message arrives, the receiving server looks up the SPF record for the domain in the envelope sender (the Return-Path, not the visible From) and checks whether the connecting IP address is on the list.

The all at the end decides what happens to everyone else:

EndingNameMeaning
-allFailReject mail from unlisted servers
~allSoftfailAccept it but treat it as suspicious
?allNeutralNo opinion, so no protection
+allPassAnyone may send. Never use this

~all is the common choice, because DMARC (below) is what actually enforces the policy.

Why SPF fails with "too many DNS lookups"

SPF caps a single check at 10 DNS lookups. Every include, a, mx, ptr, exists and redirect counts, and so does every lookup inside the records you include. ip4 and ip6 are free.

That limit is easy to hit without noticing. include:_spf.google.com alone costs 4 lookups, because Google's record includes three more. Add Microsoft 365, a newsletter tool, a CRM and a helpdesk, and you're at 11 or 12. Past 10, receivers return a permerror and SPF fails for all your mail, not just the newest sender.

Ways to get back under the limit:

  • Remove includes for services you no longer use. Old ones pile up over the years.
  • Replace an include with that provider's ip4/ip6 ranges, if they publish stable ones.
  • Send marketing mail from a subdomain like news.example.com, which gets its own SPF record and its own 10 lookups.

The other classic mistake is two SPF records. Adding a second v=spf1 TXT record for a new provider doesn't extend the first; it breaks both. Merge them into one.

What does DKIM do?

DKIM (DomainKeys Identified Mail) signs every outgoing message with a private key. The matching public key sits in DNS under a selector:

google._domainkey.example.com.  TXT  "v=DKIM1; k=rsa; p=MIIBIjANBgkqh..."

The signature travels in a DKIM-Signature header, whose d= tag names the signing domain and s= tag names the selector. The receiver fetches the key and verifies that the signed headers and body weren't altered on the way.

Unlike SPF, DKIM survives forwarding, because the signature travels with the message instead of depending on which server delivered it.

Two things to check:

  • Key size. 1024-bit RSA keys are still common but weak. Use 2048 bits; most providers offer it now.
  • Selector names. There's no way to list a domain's selectors through DNS, so a checker has to guess or be told. If yours isn't found, open a message you sent, find the DKIM-Signature header, and look for s=.

What does DMARC do?

SPF and DKIM each verify a domain, but neither checks the domain people actually see in the From line. A spammer can pass SPF for their own domain while showing yours in From. DMARC closes that gap with alignment: it passes only if SPF or DKIM passes for the same domain as the From address.

DMARC also tells receivers what to do when that check fails, and where to send reports:

_dmarc.example.com.  TXT  "v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com"
TagMeaning
pPolicy: none, quarantine (spam folder) or reject
ruaWhere to send daily aggregate reports
spPolicy for subdomains, if different from p
pctPercentage of failing mail the policy applies to
adkim / aspfr (relaxed, subdomains count) or s (strict, exact match)

How to move DMARC from p=none to p=reject

p=none is monitoring only: spoofed mail is still delivered. It's the right place to start, but plenty of domains never leave it. A safe path:

  1. Publish p=none with a rua address. Receivers start sending aggregate reports listing every server that sends as your domain.
  2. Read the reports for two to four weeks. Look for legitimate senders that fail, such as a billing system or a support desk. Fix each one by adding it to SPF or, better, by setting up DKIM signing with your domain.
  3. Move to p=quarantine. Optionally use pct=25 and raise it gradually.
  4. Move to p=reject once the reports show only forgeries failing.

Reaching p=quarantine or p=reject also unlocks BIMI, which shows your logo next to messages in Gmail, Yahoo and Apple Mail.

What about domains that never send email?

Parked domains are favorite spoofing targets because nobody watches them. Lock them down with three records:

example.org.         TXT  "v=spf1 -all"
_dmarc.example.org.  TXT  "v=DMARC1; p=reject"
example.org.         MX   0 .

The last one is a "null MX". It says the domain accepts no mail at all.

Check your domain

Run your domain through the email authentication checker. It counts SPF lookups across every include, finds DKIM keys under common selectors (or the one you enter), checks your DMARC policy and tags, and scores the setup with a fix for each problem. It also checks MTA-STS and TLS-RPT, which protect mail coming in to your domain. To look at an individual record by hand, use the DNS lookup tool with record type TXT.