Email8 min read

SPF, DKIM and DMARC: What Each One Actually Proves

Three records, three different claims — and only one of them protects the address your recipients actually see. A precise explanation of what each record proves, why SPF and DKIM are not enough on their own, and what alignment really means.

By ShipReady

SPF proves that a particular server was authorised to send mail for a domain. DKIM proves that a message was signed by a domain and has not been altered in the parts it signed. Neither one says anything about the From: address a recipient actually sees. DMARC is the record that connects them to that visible address — it requires that a passing SPF or DKIM result be aligned with the From: domain, and it tells receivers what to do when neither is.

That last sentence is the whole subject. Most explanations describe the three records as a progression — SPF is basic, DKIM is stronger, DMARC is advanced — which is tidy and wrong. They authenticate different things, and two of them authenticate something a human never sees.

The address problem

An email has two sender addresses, and they do not have to match.

  • The envelope sender, also called MAIL FROM or the Return-Path. This is part of the SMTP conversation between servers. It is where bounces go, and your recipient never sees it.
  • The header From:. This is the address rendered in a mail client, next to a display name. It is the one a person reads and the one they trust.

A legitimate mailing list uses different values for the two on purpose. So does a forwarding service. This flexibility is useful, and it is also the gap that makes spoofing trivial: anyone can put anything in the header From:, because nothing in SMTP checks it.

RecordAuthenticatesDoes not authenticate
SPFThe sending IP address, against the envelope sender’s domainThe From: header a recipient sees
DKIMThe signing domain (d=) and the integrity of the signed headers and bodyThe From: header, unless it is among the signed headers and the policy checks it
DMARCThat a passing SPF or DKIM result belongs to the same domain as the visible From:The content, the display name, or whether the sender is honest
What each mechanism actually authenticates.

SPF: which servers may send for this domain

SPF (RFC 7208) is a TXT record at your domain listing the servers permitted to send mail on its behalf. A receiving server takes the envelope sender’s domain, looks up its SPF record, and asks whether the connecting IP is authorised.

dns
yourdomain.com.  IN  TXT  "v=spf1 include:_spf.google.com include:sendgrid.net ~all"

Read left to right: start with version 1, authorise everything Google Workspace authorises, authorise everything SendGrid authorises, and for anything else return a soft fail. That final mechanism matters more than people expect — what `~all`, `-all` and `?all` actually do is its own article, because getting it wrong makes the entire record advisory.

Where SPF fails

  • It breaks on forwarding. When a recipient auto-forwards your message, the forwarding server connects from its own IP, which your record does not list. SPF fails through no fault of yours. This is the single biggest reason SPF alone is not a sufficient basis for rejecting mail.
  • It has a hard limit of ten DNS lookups during evaluation (RFC 7208 §4.6.4). Each include: costs at least one, and a nested include costs more. Exceed it and evaluation returns permerror, which most receivers treat as no SPF at all. ShipReady reports an SPF record over the lookup limit for exactly this reason.
  • You may publish only one SPF record. Two records is the same as none — receivers must treat it as a permanent error rather than merging them.
  • It says nothing about the From: header, which is the address the spoofing actually targets.

DKIM: this message was signed by this domain

DKIM (RFC 6376) works differently. Your sending service holds a private key and adds a DKIM-Signature header to each outgoing message — a cryptographic signature over the body and a chosen set of headers. You publish the matching public key in DNS. A receiver fetches the key and verifies the signature.

dns
resend._domainkey.yourdomain.com.  IN  TXT  "v=DKIM1; k=rsa; p=MIIBIjANBgkq..."

The resend part is the selector. It lets one domain hold several keys at once — one per sending service, or an old and a new key during rotation — which is why your provider gives you a selector-specific record rather than a single well-known name.

A valid DKIM signature proves two things: the domain in the d= tag authorised this message, and the signed parts arrived unmodified. It survives forwarding, because the signature travels with the message rather than depending on the connecting IP. That property is why DKIM is the more durable of the two.

Where DKIM fails

  • The d= domain does not have to be yours. A bulk sender can sign with its own domain and still pass DKIM. The signature is valid; it just does not vouch for you.
  • Mailing lists that rewrite subjects or append footers break the body hash, and the signature fails.
  • A key can be published, then revoked by emptying its p= tag, and mail keeps being signed against it. ShipReady reports a revoked DKIM key and a malformed one separately, because they fail in different ways.
  • Like SPF, on its own it says nothing about the From: header.

DMARC: alignment, policy, and reporting

DMARC (RFC 7489) is published at _dmarc.yourdomain.com and does three jobs that neither other record can.

dns
_dmarc.yourdomain.com.  IN  TXT  "v=DMARC1; p=reject; rua=mailto:dmarc@yourdomain.com; adkim=s; aspf=s"

1. Alignment — the part that matters

DMARC requires that a passing authentication result belong to the same domain as the visible From: header. That is alignment, and it is what closes the gap the first two records leave open.

  • SPF is aligned when the envelope sender’s domain matches the From: domain.
  • DKIM is aligned when the signature’s d= domain matches the From: domain.
  • DMARC passes if either aligned check passes. Not both — either.

The adkim and aspf tags choose how strictly to compare. Relaxed (the default, r) accepts an organisational-domain match, so a signature from mail.yourdomain.com aligns with a From: at yourdomain.com. Strict (s) requires an exact match. Start relaxed; most providers sign with a subdomain.

2. Policy — what receivers should do

PolicyAsks receivers toUse when
p=noneDo nothing differently, but send reportsYou are still discovering which of your services send mail
p=quarantineTreat failing mail as suspicious — usually spam folderReports are clean and you want a reversible first step
p=rejectRefuse failing mail at the SMTP conversationYou are confident every legitimate source is authenticated

A record with p=none gives you visibility and no protection: forged mail claiming to come from your domain is still delivered. It is the correct starting point and a poor resting point — moving from `p=none` to `p=reject` without losing your own mail is the procedure for getting off it.

3. Reporting

The rua tag names an address to receive aggregate reports: daily XML summaries from receiving providers describing which IPs sent mail claiming to be you, and whether it aligned. This is the only mechanism that tells you what your own sending footprint actually looks like, and a DMARC record without one is largely decorative — ShipReady reports a DMARC record with no reporting address for that reason.

Putting it together

A concrete example. An attacker sends a password-reset email with From: support@yourdomain.com from a server they control.

  1. They set the envelope sender to their own domain, so SPF passes — for their domain. It is not aligned with your From:, so it does not count for DMARC.
  2. They sign with their own key, so DKIM passes — for their domain. Again unaligned.
  3. DMARC evaluates: is there an aligned pass? No. Your policy says p=reject. The receiving server refuses the message.

Now run the same three steps with p=none. Everything is identical until the last line, where the receiver notes the failure in a report and delivers the message anyway. That is the difference the policy makes, and it is why the three records are not a progression from weak to strong: without DMARC at enforcement, the first two protect a domain nobody looks at.

A minimum viable setup

  1. Publish one SPF record listing every service that sends for you, ending in ~all while you are still finding them.
  2. Publish the DKIM record your sending provider gives you, on the selector they specify. If you use several providers, publish several selectors.
  3. Publish v=DMARC1; p=none; rua=mailto:you@yourdomain.com and leave it for two weeks.
  4. Read the reports. Confirm every legitimate source shows an aligned pass.
  5. Move to p=quarantine, then p=reject.
  6. Separately, confirm the domain can receive mail at whatever address your site publishes. Sending and receiving are configured independently and people routinely do only the first.

The pre-launch DNS checklist puts this alongside the rest of the records worth confirming before you point a domain at production.

How ShipReady checks this

ShipReady resolves these records live for the domain you scan and validates their contents rather than their existence — the distinction that matters, since a record that parses and a record that protects you are different things. It reports no SPF record, no DKIM and no DMARC, alongside the specific ways each can be present but ineffective: a permissive all, a policy of none, duplicate records, a subdomain policy weaker than the domain policy.

It reads public DNS only — the same answers any receiving mail server gets — and never sends mail or touches your provider account. Scan your domain free to see where it stands, or read the Email pillar for every record-level check.

Frequently asked questions

Do I need all three?
You need DMARC to be protected, and DMARC needs at least one of SPF or DKIM to align. In practice publish all three: DKIM survives forwarding where SPF does not, and having both gives DMARC two chances to find an aligned pass.
Does DMARC stop phishing?
It stops one specific and effective kind: mail that puts your exact domain in the visible From address. It does nothing about lookalike domains, a forged display name over an unrelated address, or a compromised account sending genuinely authenticated mail.
Why does my mail pass SPF but fail DMARC?
Almost always alignment. Your sending provider set the envelope sender to its own bounce domain, so SPF passes for that domain rather than yours. Configure a custom Return-Path or bounce subdomain with your provider, or rely on aligned DKIM instead.
Do I need a DMARC record if I do not send email at all?
Yes, and it is the easiest case. A domain that never sends can publish a strict policy immediately, since there is no legitimate mail to break. It stops your domain being used to forge mail to other people.

Sources

Related reading

Is your site ready to ship?

ShipReady scans up to ten pages for security, AI exposure, email deliverability, SEO and launch readiness — with a paste-ready fix for each finding. Free, no signup.