SPF, DKIM and DMARC: what each one actually does

Updated 2026-08-30 9min read

Three records, three different jobs. What each one proves, why DMARC needs the other two, and a rollout order that will not break delivery.

Three records, three different jobs

The three are constantly lumped together, which hides the fact that they answer completely different questions. Getting the distinction straight is most of the work:

What each record proves
RecordQuestion it answersSurvives forwarding?
SPFWas this message sent from a server the domain authorised?No
DKIMWas this message signed by the domain, and unaltered since?Usually
DMARCWhat should the receiver do when the other two fail — and where should it report?n/a

SPF checks the envelope sender against an IP list. DKIM checks a cryptographic signature. DMARC checks that whichever of those passed refers to the same domain the recipient sees in the From header, and then tells the receiver what to do about it.

SPF: which servers may send

SPF is a single TXT record at your domain apex listing the sources allowed to send mail for it. A minimal one looks like:

v=spf1 include:_spf.google.com ~all

Reading it left to right: use SPF version 1; treat anything in Google's published list as authorised; for everything else, soft-fail.

The last mechanism is the one worth deciding deliberately:

  • -all (fail) — anything not listed should be rejected. The strongest setting, and the one to reach eventually.
  • ~all (softfail) — accept but mark as suspicious. The right setting while you are still discovering senders.
  • ?all (neutral) — says nothing, which is barely better than having no record.
  • +all — authorises the entire internet. Never correct.

SPF's fundamental weakness is forwarding. When a mailing list or a forwarding address relays your message, the receiving server sees the forwarder's IP, which is not in your record, and SPF fails through no fault of yours. This is exactly the gap DKIM covers.

DKIM: proof the message was not altered

DKIM adds a cryptographic signature to each outgoing message, covering the body and a chosen set of headers. The receiver fetches your public key from DNS and verifies it.

The key lives at a selector-scoped name — selector1._domainkey.example.com — because a domain can have several keys in use at once. That is deliberate: it is what makes key rotation possible, and it is why you cannot check DKIM without knowing the selector your provider uses.

Because the signature travels with the message, DKIM normally survives forwarding. It breaks when something modifies the signed parts in transit — a mailing list appending a footer or rewriting the subject is the classic case.

Alignment: the part that ties them together

This is the concept that makes DMARC more than a wrapper, and the one most explanations skip.

A message has two "from" addresses. The envelope sender (Return-Path) is what SPF checks. The From header is what the recipient actually sees. They do not have to match — and for a long time, that was the whole problem: an attacker could pass SPF for a domain they control while putting your domain in the visible From.

DMARC closes it by requiring alignment: the domain that passed SPF or DKIM must match the From-header domain.

  • Relaxed alignment (the default) — the organisational domain must match, so mail.example.com aligns with example.com.
  • Strict alignment — the domains must match exactly.

This is why a message can pass SPF and still fail DMARC, which is one of the more confusing results to debug. The SPF check succeeded — for a different domain than the one in the From header.

DMARC: what to do when a check fails

DMARC is a TXT record on the _dmarc subdomain:

v=DMARC1; p=none; rua=mailto:[email protected]; pct=100; adkim=r; aspf=r

The tags that matter:

DMARC tags worth understanding
TagMeaning
pPolicy for failures: none (monitor), quarantine (spam folder), reject (refuse).
ruaWhere to send aggregate reports. Without this, DMARC tells you nothing.
pctPercentage of failing mail the policy applies to — the lever for a gradual rollout.
spPolicy for subdomains. Defaults to p; set it explicitly if subdomains differ.
adkim / aspfAlignment mode, r (relaxed, default) or s (strict).

A record with p=none and no rua is the worst of both worlds: it looks like you have DMARC, enforces nothing, and reports nothing. If you publish only one thing today, publish p=none with a reporting address.

A rollout order that will not lose mail

The order matters, because enforcing before you have an inventory of your senders is how legitimate mail starts disappearing.

  1. Inventory what sends as you. Marketing platform, helpdesk, invoicing, CI notifications, the CRM someone set up years ago. This list is always longer than expected.
  2. Publish SPF with ~all, covering every source you found. Soft-fail, not hard-fail, at this stage.
  3. Enable DKIM signing on every platform that supports it, and publish each key.
  4. Publish DMARC with p=none and a rua address. Nothing is enforced; reports start arriving.
  5. Read the reports for two to four weeks. They will surface senders that fail — some of which are legitimate systems you missed. Fix those before enforcing anything.
  6. Move to p=quarantine, optionally with pct=10 first and raising it as it stays quiet.
  7. Move to p=reject once quarantine has been clean for a few weeks.
  8. Tighten SPF to -all last, when you are confident the source list is complete.

Every step is reversible until p=reject. Do not skip the reporting stage to get there faster — that stage is the entire reason the process is safe.

The mistakes that actually break delivery

  • Two SPF records. Adding a provider's suggested record alongside an existing one, instead of merging its include into it. This is a PermError, and it fails everything.
  • Blowing the 10-lookup limit. Four or five providers, each nesting their own includes, gets there quickly. Flatten what you can, and drop senders you no longer use.
  • Publishing DMARC at the wrong name. It belongs at _dmarc.example.com, not at the apex.
  • Jumping straight to p=reject. Enforcement without an inventory silently rejects your own invoices.
  • Forgetting subdomains. Without sp, subdomains inherit p — which is usually right, but check it rather than assume it.
  • Using ptr in SPF. Deprecated, slow, and unreliable. Remove it.
  • No rua address. You are flying blind, and you will not find out about a broken sender until someone complains.

Frequently asked questions

Do I need all three, or is SPF enough?
SPF alone is not enough. It breaks on forwarding, and on its own it says nothing about the address a recipient actually sees. DMARC is what turns SPF and DKIM into a policy a receiver can act on, and DMARC requires at least one of them to pass in alignment. In practice you want SPF and DKIM both, with DMARC on top.
What is the SPF 10-lookup limit?
Evaluating an SPF record must not require more than 10 DNS lookups. Each include, a, mx, ptr, exists and redirect counts, and includes nest — one provider’s include can consume several on its own. Exceeding it is a PermError, and many receivers treat that as an SPF failure rather than ignoring it.
Can I publish two SPF records?
No. A domain must publish exactly one TXT record starting v=spf1. Two is a PermError, and it is the single most common SPF misconfiguration — usually caused by adding a second provider’s record instead of merging its include into the existing one.
Where does the DKIM record live?
At <selector>._domainkey.<domain>. The selector is chosen by whoever signs your mail, so you have to get it from your provider — there is no way to discover it from DNS alone, which is why a DKIM check needs you to supply it.
Is p=none pointless?
No — it is the reporting stage. At p=none nothing is rejected, but you start receiving aggregate reports showing every source sending as your domain, including ones you had forgotten. That inventory is what makes it safe to move to quarantine later.

Check it on your own domain

Everything above is only useful if you can see the current state of your own setup. These tools do exactly that:

Spotted an error in this guide? Tell us at [email protected] — corrections are made and the updated date above changes with them.