SPF, DKIM & DMARC: Reading the Verdicts in Headers
Publishing the DNS records is half the job. This is about the other half — reading what a receiving server decided, straight from the header it left behind.
This page assumes SPF, DKIM, and DMARC records already exist somewhere in DNS and focuses on the artifact a receiving server leaves behind after checking them: the Authentication-Results header. If you need the DNS record syntax, qualifiers, and deployment roadmap instead, see SPF, DKIM, and DMARC: Email Authentication Explained on the Domain Intelligence Dashboard — this article picks up exactly where that one leaves off.
What Each Protocol Actually Proves
Three different questions get asked and answered independently, and keeping them separate is the key to reading the results correctly:
- SPF asks: was this connecting IP address authorized to send for the envelope sender's domain? It checks the SMTP envelope (
MAIL FROM, visible in headers asReturn-Path), not the visible From address, and it breaks under plain forwarding because the forwarding server's IP usually isn't in the original domain's SPF record. - DKIM asks: does a valid cryptographic signature prove this message's content wasn't altered after a specific domain signed it? It checks the message itself, not the connection, which is why it survives forwarding — the signature travels with the content.
- DMARC asks: did the domain in the visible From header actually authorize this mail, using SPF or DKIM as evidence? It's a policy layer on top of the other two, not a third independent check.
Where the Verdicts Live: the Authentication-Results Header
A receiving server records what it found in an Authentication-Results: header, formatted per RFC 8601. The value is a semicolon-separated list: an authserv-id identifying the server that ran the checks, followed by one method=verdict segment per protocol, each carrying the specific domain that verdict applies to:
Authentication-Results: mx.example.com; spf=softfail (mail.example.com: domain of transitioning bob@example.net does not designate 192.0.2.44 as permitted sender) smtp.mailfrom=bob@example.net; dkim=pass header.d=example.net; dmarc=fail (p=quarantine) header.from=example.net
Reading it segment by segment:
spf=
The verdict (pass, fail, softfail, neutral, none, temperror, or permerror) is followed by smtp.mailfrom=, the exact envelope-sender domain the check ran against. In the example above, smtp.mailfrom=bob@example.net tells you SPF evaluated example.net — useful context, because that domain can differ from the visible From domain entirely.
dkim=
Followed by header.d=, the domain that owned the signing key used to produce a valid signature. A message can carry multiple DKIM signatures (common when a mailing list re-signs a message); each gets its own dkim= segment, and DMARC alignment cares whether any of them matches the From domain.
dmarc=
Followed by header.from=, the domain the DMARC policy check was run against — always the visible From domain, since that's what DMARC exists to protect. The parenthetical, when present, often echoes the domain's published policy (p=none, p=quarantine, or p=reject) so you can see not just whether it failed but what the domain owner asked receivers to do about it.
Alignment: Why a "Pass" Isn't Always Enough
Here is the detail that trips up nearly every manual read of these headers: SPF and DKIM can both pass while DMARC still fails, because DMARC additionally requires alignment — the domain that passed SPF or DKIM must match (or share a parent domain with, under relaxed alignment) the domain in the visible From header. An email can pass SPF for attacker-domain.example and still spoof a From address at yourcompany.com, because SPF alone never checks what the From header says. DMARC is the layer that closes exactly this gap by cross-checking the two.
Practically: when you're reading a header block and see spf=pass or dkim=pass, always check which domain the smtp.mailfrom= or header.d= property names before concluding the message is legitimate. A pass for the wrong domain is not reassuring — it's exactly what an attacker abusing their own, properly configured domain would produce.
Multiple Authentication-Results Headers — Which One to Trust
A message relayed through several internal hops before reaching your inbox can carry more than one Authentication-Results header — one per server that performed checks, stacked newest-first exactly like Received: headers. As a rule of thumb, the topmost one was added by the border server closest to you, the final recipient, and is generally the most trustworthy: it reflects the last hop's view of the message, after any internal relays have already had their chance to tamper with earlier results. Older, lower headers can be forged by anything upstream of your own infrastructure, so don't take a favorable verdict at face value unless it came from a server your organization actually controls or trusts.
Check Your Own Authentication-Results
Paste a raw header block below to see every Authentication-Results header parsed into individual method/verdict/domain badges, exactly as described above.
Paste the raw headers of an email to reconstruct its delivery path, check SPF/DKIM/DMARC results, and look for signs of a spoofed sender.
Privacy note: parsing runs entirely client-side. Header content is never sent to a server.
For the domain-owner side of this — publishing the SPF, DKIM, and DMARC records these checks evaluate — see the full authentication guide and the Domain Intelligence Dashboard, which reads a domain's live DNS records directly. To read the rest of a message's headers — including the delivery chain these authentication checks sit alongside — start with how to read email headers.
Further Reading
- RFC 7208 — Sender Policy Framework (SPF)
The IETF standard for SPF, including the full set of verdicts referenced in Authentication-Results.
- RFC 6376 — DomainKeys Identified Mail (DKIM)
The IETF standard for DKIM signature verification.
- RFC 7489 — DMARC
Domain-based Message Authentication, Reporting, and Conformance, including the alignment rules.
- RFC 8601 — Authentication-Results header field
The exact syntax this article walks through, including the property-domain tags for each method.