SPF vs DKIM vs DMARC explained (what each one actually does)
Five identities travel inside one email and only one is visible. Which identifier each protocol binds, when it can be evaluated, and why DMARC had to exist.
Three protocols, five identities. A single email carries a HELO domain, an envelope-sender domain, a DKIM signing domain, an optional DKIM agent identifier, and the From address in the header — and only the last one is ever shown to a human. SPF authenticates one of the first two. DKIM authenticates the third. Neither is required to have anything to do with the fifth, which is exactly the gap DMARC was written to close. Understand which identifier each protocol binds and the whole subject stops being an acronym problem.
Five identities travel in one message, and only one is visible
Before comparing the protocols, it is worth writing out what they are comparing. These are the identifiers present in an ordinary SMTP delivery.
- The HELO or EHLO domain. The name the connecting server announces for itself at the start of the conversation. RFC 7208 section 2.3 says "It is RECOMMENDED that SPF verifiers not only check the 'MAIL FROM' identity but also separately check the 'HELO' identity", and notes that a HELO check is cheaper because an SPF record published for a HELO identity refers to a single host.
- The envelope sender, or MAIL FROM. The address given in the
MAIL FROMcommand and written into theReturn-Pathheader. This is where bounces go. RFC 7208 section 2.4 makes checking it mandatory when a HELO check has not produced a definitive result, and covers the awkward case: RFC 5321 permits a null reverse-path on notification messages, and "when the reverse-path is null, this document defines the 'MAIL FROM' identity to be the mailbox composed of the local-part 'postmaster' and the 'HELO' identity". - The DKIM Signing Domain Identifier, the
d=tag. RFC 6376 section 2.5 defines it as "a single domain name that is the mandatory payload output of DKIM and that refers to the identity claiming some responsibility for the message by signing it". - The DKIM Agent or User Identifier, the
i=tag. Section 2.6: "a single identifier that refers to the agent or user on behalf of whom the Signing Domain Identifier (SDID) has taken responsibility". Optional, and rarely load-bearing. - The From header domain, formally RFC5322.From. The only one a mail client renders next to a display name. RFC 9989 is blunt about why it matters and why it is dangerous, describing DMARC's focus as being on "an identifier, namely the RFC5322.From address, which is part of a body of data that has been trivially forged throughout the history of email".
Nothing in SMTP requires these five to agree. A message with EHLO out-17.relay.example, MAIL FROM: [email protected], a signature with d=relay.example, and From: [email protected] is entirely legal and completely ordinary.
SPF binds an envelope identity to an IP address, and nothing more
SPF is one TXT record on the domain that appears in the envelope. The receiver takes the connecting IP address, the envelope-sender domain and the HELO name, and evaluates the record's mechanisms in order until one matches.
Two properties are worth holding onto.
It produces seven possible results, and only one of them is a pass. RFC 7208 section 2.6 defines none, neutral, pass, fail, softfail, temperror and permerror. Most tooling collapses that into a green tick or a red cross, which throws away the distinction that matters most in practice: permerror means the record could not be evaluated at all, and receivers commonly treat it the way they treat a failure. A syntactically broken record and an unauthorised sender look identical on a dashboard and are entirely different bugs.
Its budget is ten DNS lookups, and it is spent by nesting you cannot see. Section 4.6.4: the include, a, mx, ptr and exists mechanisms and the redirect modifier "cause DNS queries", and "SPF implementations MUST limit the total number of those terms to 10 during SPF evaluation… If this limit is exceeded, the implementation MUST return 'permerror'." The all, ip4 and ip6 mechanisms cost nothing. The trap is that a vendor's include: expands into their own includes, so your record can cross the limit on a day you changed nothing, because they added a mechanism to theirs. There is a separate recommendation to limit void lookups to two.
The structural limitation is the one people trip over. SPF's answer is about the envelope, and a relay writes the envelope. Forwarding breaks it by definition: the forwarding host was never in your record, so the check fails for a message that is entirely legitimate. That failure mode is not a bug in SPF; it is the boundary of what a path-based check can assert.
DKIM binds a domain to a hash of the headers it chose to sign
DKIM works from the other direction. Your signing platform holds a private key, publishes the matching public key in DNS at selector._domainkey.yourdomain.com, and adds a header:
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=acme.com; s=selector1; h=from:to:subject:date:message-id; bh=47DEQpj8HB...; b=dzdVyOfAKC...
The d= tag is the SDID and the one DMARC will later compare. The s= tag names the selector to fetch. The h= tag lists which headers the signature covers, and bh= is a hash of the body. Anything named in h= that is rewritten in transit invalidates the signature — a mailing list that prepends a tag to the subject and appends a footer to the body breaks both halves at once.
DKIM's verdict vocabulary is narrower than SPF's. RFC 6376 section 3.9 defines exactly three outcomes: SUCCESS, PERMFAIL for "a permanent, non-recoverable error such as a signature verification failure", and TEMPFAIL for "a temporary, recoverable error such as a DNS query timeout". There is no softfail, no neutral, and no notion of a partial pass.
There is also no way for DKIM to report its own absence. An unsigned message and a message whose signature was stripped in transit are indistinguishable to a verifier, because in both cases there is simply no DKIM-Signature header to evaluate. That is not a flaw either — it is a direct consequence of the design — but it is why a signature alone can never be a policy.
Where the public key lives is provider-specific, and it is the piece most likely to be half-done. Google Workspace publishes a TXT record at google._domainkey. Microsoft 365 uses two CNAMEs, selector1._domainkey and selector2._domainkey, and publishing them without enabling signing in the admin portal is a common resting state. Amazon SES Easy DKIM issues three CNAMEs with randomly generated per-identity tokens, all of them required, which is also why no generic selector-guessing tool can ever find an SES domain's keys.
DMARC is not authentication — it is the assessor policy DKIM left open
Here is the sentence that explains why a third protocol was needed at all. RFC 6376, in the informative discussion at section 3.11, says of DKIM: "This document does not require the value of the SDID or AUID to match an identifier in any other message header field. This requirement is, instead, an Assessor policy issue."
DKIM deliberately declined to specify the link between the signing domain and the visible From address, and handed that question to whoever assesses the message. DMARC is that assessor policy, written down and published in DNS by the domain owner rather than invented by each receiver.
RFC 9989, published in May 2026 as a Standards Track document obsoleting RFC 7489 and RFC 9091, describes the mechanism as Identifier Alignment: DMARC "describes the concept of alignment between the Author Domain and an Authenticated Identifier and requires such Identifier Alignment between the two for a message to achieve a DMARC pass". The two Authenticated Identifiers are defined narrowly. For DKIM, "if the cryptographic signature validates, then the DKIM Signing Domain is the DKIM-Authenticated Identifier". For SPF, "if the use of the domain in the MAIL FROM identity is validated by SPF, then that domain is the SPF-Authenticated Identifier".
Three consequences follow directly, and each one surprises somebody.
- DMARC passes if either mechanism passes and aligns. One is enough. A message with a broken SPF record and a valid, aligned DKIM signature is a DMARC pass.
- A pass on a mechanism that does not align contributes nothing. SPF passing for
relay-provider.netis not an SPF-Authenticated Identifier foracme.com. - Both alignment modes default to relaxed.
adkimandaspfare optional tags whose default value isr. Strict alignment is something you choose, not something you inherit. - The HELO identity is discarded. SPF may validate both the HELO and the MAIL FROM identity, but RFC 9989 section 4.4.2 is explicit that "DMARC relies solely on SPF validation of the MAIL FROM identity". A perfectly aligned HELO name contributes nothing to a DMARC result, which is one identity fewer than most diagrams show.
The rest of DMARC — the tags, the aggregate report format, and the DNS tree walk that replaced the Public Suffix List in the 2026 revision — is a subject of its own, and what changed in DMARC in May 2026 and how to read a report field by field is where that belongs.
The comparison, parameter by parameter
Lined up against the same questions, the three stop looking like layers of one thing.
What it binds. SPF binds an envelope-level domain to a connecting IP address. DKIM binds a domain to a cryptographic hash of selected headers and the body. DMARC binds a passing result from either of those to the domain in the visible From header.
Where the evidence comes from. SPF: a TXT record plus the TCP connection itself. DKIM: a public key in DNS plus the message bytes. DMARC: the outputs of the other two plus a TXT record at _dmarc.
When it can be evaluated. SPF needs only the IP address and the envelope, both of which the receiver holds before the message body is transferred — which is why an SPF rejection can happen before you have spent bandwidth on the message. DKIM needs the complete body to recompute bh=, so it cannot conclude until the transfer is finished. DMARC needs both plus the From header, so it is always last.
The verdict vocabulary. SPF: seven results. DKIM: three. DMARC: pass or fail, with a policy attached.
Survives ordinary forwarding. SPF: no, by design. DKIM: yes, if headers and body are untouched. DMARC: yes, if DKIM survived.
Survives a mailing list that rewrites the subject and appends a footer. SPF: no. DKIM: no. DMARC: no — which is the entire reason the Authenticated Received Chain exists, published as RFC 8617 and still Experimental.
What it says about the message. SPF and DKIM say something about provenance. Neither says anything about honesty, and RFC 6376 section 1.5 is careful about even the integrity claim: verifying the signature "asserts that the hashed content has not changed since it was signed and asserts nothing else about 'protecting' the end-to-end integrity of the message".
The failure that catches almost every cold-email setup
You send From: [email protected] through a platform that stamps Return-Path: [email protected] and signs with d=relay-provider.net. SPF passes. DKIM passes. DMARC fails.
Both passes belong to the relay. Neither is an Authenticated Identifier for acme.com, so neither aligns, and a header full of green ticks sits above a red verdict. The fix is either to have the platform sign with your own domain — which every serious sending platform supports — or to configure a custom Return-Path on a subdomain you control so the SPF-Authenticated Identifier becomes yours.
Diagnosing it takes one message and one header rather than a theory. The publish-and-verify order for a cold email domain covers the sequence, and what each of your three records returns from a terminal covers the lookups. If you would rather generate provider-accurate records than hand-write them, the SPF, DKIM and DMARC record generator assembles them with alignment already set.
Reading the verdict, and knowing whose word you are taking
The receiver writes its conclusion into an Authentication-Results header, specified in RFC 8601. A typical line:
Authentication-Results: mx.google.com; spf=pass smtp.mailfrom=mail.acme.com; dkim=pass [email protected] header.s=selector1; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=acme.com
Read the domains rather than the words. smtp.mailfrom is what SPF evaluated. header.i shows what DKIM signed. header.from is what DMARC compared against. Three green passes attached to three different domains is an alignment failure wearing a success costume.
One caution that is easy to miss: this header is written by whichever host processed the message, and any hop can add one. It is trustworthy on the boundary you control — your own mailbox, reading a message you sent yourself — and unverifiable on a header added by a machine you do not operate. Treat it as evidence about a specific hop, not as a global verdict.
Autocloz's free plan covers 5 users and 10 mailboxes with SPF, DKIM and DMARC monitoring on every sending domain — start free if you want the alignment question answered on a schedule rather than the day something breaks.
What each one cannot do, and what Autocloz does not do here
Being precise about the boundaries is more useful than another paragraph of reassurance.
SPF cannot see the address your recipient reads. It has no access to the From header at all. Any claim that SPF "verifies the sender" is using the word sender in a sense the specification does not.
DKIM cannot tell a receiver that a signature is missing. No header means no evaluation, so a stripped signature and unsigned mail are the same event. Only a published policy turns absence into a decision.
DMARC cannot say a message is honest. A DMARC pass means the domain in the From line authorised the message. A phishing message sent from a domain the attacker registered and authenticated correctly passes DMARC on the way to defrauding somebody.
None of the three decides placement. Passing removes a reason to filter you; it does not create a reason to deliver you. Complaint rate, volume and domain reputation continue to run that decision, and the levers that actually decide which folder a message lands in sit downstream of everything described here.
Autocloz does not publish DNS records for you, and cannot. Only whoever controls the zone can do that. What it does is check: a per-domain monitor attached to the email sending channel stores the SPF, DKIM and DMARC verdict from each round and rolls it into pass, warn or fail, with the raw records kept so the UI does not re-query DNS on every page load.
Its DKIM check guesses selectors unless you record yours. Selectors cannot be enumerated from DNS — only the signing platform knows them — so the probe tries a short list of common names and, on a miss, reports unknown rather than fail. Recording your real selectors is what makes a miss meaningful. Before that, an absent answer is genuinely an absence of information.
Report ingestion is push, and it counts rather than names. Autocloz accepts a DMARC aggregate report XML body on an authenticated endpoint and stores the policy domain, the reporting organisation, the date range, the total message count and the per-record SPF, DKIM and DMARC pass counts, then raises an alert when the DMARC pass rate falls below 80% across at least 50 messages. It does not fetch reports on your behalf, and it does not break out the individual source IP addresses — so it will tell you that alignment slipped, and you will still open the raw XML to find out which sender caused it.
Frequently asked
What is the difference between SPF, DKIM and DMARC in one sentence each?
SPF asks whether the connecting IP address is authorised to use the envelope-sender domain, and returns one of seven verdicts. DKIM asks whether a cryptographic signature over a chosen list of headers and the body still validates against a public key published by the signing domain. DMARC asks a different kind of question entirely - whether either of those two results belongs to the domain shown in the From line the recipient reads - and then applies a policy and sends reports. Two of the three are authentication; the third is a binding rule.
Does SPF authenticate the From address my recipient sees?
No, and this is the single most common misunderstanding about it. RFC 7208 defines two identities SPF may check - the HELO identity at section 2.3 and the MAIL FROM identity at section 2.4 - and neither is the From header a mail client displays. The MAIL FROM address is the envelope sender, written into the Return-Path, and a relay routinely sets it to a bounce address on its own domain. SPF can pass perfectly for that relay's domain while saying nothing about yours.
Why does DKIM exist if SPF already checks the sender?
SPF binds a domain to an IP address, so it breaks the moment a message is relayed by a host that was never on your list - which is what ordinary forwarding does. DKIM binds a domain to a hash of the message, so the signature survives the extra hop as long as nothing rewrote a signed header or the body. The two protocols fail under different conditions, which is why DMARC passes when either one passes and aligns, rather than requiring both.
Is DMARC an authentication protocol?
Not in the sense SPF and DKIM are. DMARC performs no cryptography and makes no DNS authorisation check of its own. RFC 9989 describes it as requiring Identifier Alignment between the Author Domain and an Authenticated Identifier produced by SPF or DKIM, then publishing a policy for what a receiver should do when no alignment is found, plus a reporting channel. It is the assessor policy that RFC 6376 explicitly declined to specify for DKIM.
What does relaxed versus strict alignment actually change?
Relaxed alignment requires only that the two domains share an organisational domain, so mail.acme.com aligns with acme.com. Strict alignment requires an exact match, so mail.acme.com does not align with acme.com. Both adkim and aspf default to relaxed when the tag is omitted from the DMARC record, per RFC 9989. Choose strict only when your entire sending flow uses one exact hostname; choose relaxed when billing, marketing and outbound each send from their own subdomain.
How many DNS lookups is an SPF record allowed?
RFC 7208 section 4.6.4 requires implementations to limit terms that cause DNS queries - include, a, mx, ptr and exists mechanisms plus the redirect modifier - to ten during evaluation, and to return permerror if the limit is exceeded. Nested includes count against the same budget, so three chained vendor includes can cross it without your record visibly growing. The specification separately says implementations should limit void lookups to two.