8.2 SPF, DKIM, DMARC, and Email Authentication Results
Key Takeaways
- SPF can prove the connecting IP was listed for the envelope domain; it does not bind header From until DMARC alignment and does not prove a lookalike is the real brand.
- DKIM pass means the d= domain signed the covered fields and body hash; a mailing list footer can break DKIM without proving spoofing.
- DMARC pass requires SPF-pass-plus-alignment or DKIM-pass-plus-alignment with the header From domain; policies are none, quarantine, and reject.
- SPF pass, DKIM pass, and DMARC pass on a cousin domain the attacker owns is expected phishing infrastructure, not a clean bill of health.
- Authentication-Results is a receiver-added RFC 8601 header: read spf= against smtp.mailfrom, dkim= against header.d, and dmarc= against header.from.
8.2 SPF, DKIM, DMARC, and Email Authentication Results
SPF, DKIM, and DMARC are DNS-published policies plus receiver checks. They reduce direct spoofing of domains that deploy them well. They do not stop phishing. Lookalike domains, display-name tricks, compromised mailboxes on authorized senders, and malicious mail from a hijacked marketing platform can all authenticate. SAL1 training content names these protocols because analysts must read Authentication-Results without treating pass as benign.
What each protocol proves — and does not prove
SPF
Sender Policy Framework (SPF) (RFC 7208) lets a domain publish which IP addresses, and which other domains, may send mail using that domain in the SMTP envelope (MAIL FROM, later visible as Return-Path). The receiving server takes the connecting IP of the SMTP session and asks DNS: does this domain's TXT policy include that IP, directly or via include: / redirect=?
SPF can prove: the host that delivered this SMTP transaction was listed as a sender for envelope domain X.
SPF does not prove:
- That header From matches the envelope (until DMARC alignment is applied).
- That a human at company X intended the message.
- That the sending account was not compromised. A stolen mailbox at a legitimate software-as-a-service (SaaS) mailer still SPF-passes.
- That domain X is the brand the user thinks they see. The attacker can SPF-pass a lookalike they own.
SPF also fails closed or open depending on the terminal mechanism: -all (fail), ~all (softfail), ?all (neutral), +all (pass everyone — effectively no policy). A missing record yields none. DNS failures yield temperror; broken records yield permerror.
DKIM
DomainKeys Identified Mail (DKIM) (RFC 6376) attaches a digital signature over selected header fields and a hash of the body. The signer publishes a public key in DNS at a selector (selector._domainkey.example.com). A pass means those signed fields and the body hash match, and the signer controls the d= domain in the DKIM-Signature header.
DKIM can prove: this content is unaltered relative to what the d= domain signed, for the signed header set.
DKIM does not prove:
- That
d=equals header From, unless DMARC alignment holds. - That mailing-list footers did not break the body hash (a common legitimate
dkim=fail). - Intent. A criminal platform can sign as itself.
DMARC
Domain-based Message Authentication, Reporting, and Conformance (DMARC) (RFC 9989, which obsoletes RFC 7489) ties SPF and DKIM back to the domain in header From. A DMARC pass requires (SPF pass and SPF identifier alignment) or (DKIM pass and DKIM identifier alignment). Alignment may be relaxed (organizational domain match, so mail.brand.example can align with brand.example) or strict (exact domain match).
DMARC can prove: the domain in From authorized this path via SPF and/or DKIM, according to that domain's published policy.
DMARC does not prove the visual brand is genuine if the From domain is a registered lookalike. It also does not prove the message is wanted: authorized bulk mail and compromised senders pass.
DMARC policy (p=) tells receivers what to do on fail:
| Policy | Meaning | Analyst implication |
|---|---|---|
| none | Monitor; do not treat fail as a delivery block. | Spoofed mail may still reach the inbox. Operational teams may collect aggregate reports (rua); do not assume the domain is protected. |
| quarantine | Place failing mail in spam or a quarantine store. | Users may still release it. Look for quarantine logs, not only mailbox copies. |
| reject | Refuse at SMTP. | Direct spoofing of that From domain should not land. Lookalikes with their own p=reject still land and still pass. |
Current RFC 9989 removed the historic pct= tag in favor of the t= testing flag, retains subdomain policy (sp=), and defines reporting through companion specifications. SAL1-level analysis starts with pass/fail plus the published p= value.
How Authentication-Results is written
Receivers add Authentication-Results (RFC 8601) when they finish checks. A realistic invented example:
Authentication-Results: mx.northwind.example;
spf=softfail (sender IP 203.0.113.40 is not permitted) smtp.mailfrom=contoso.com;
dkim=fail reason="signature verification failed" header.d=contoso.com;
dmarc=fail (p=reject dis=none) header.from=contoso.com
Read it as three independent sentences plus a DMARC combination:
spf=applies tosmtp.mailfrom(envelope), not automatically to From.dkim=namesheader.d(the signing domain).dmarc=namesheader.fromand may echo the domain's policy.
SPF result vocabulary you will see: pass, fail, softfail, neutral, none, temperror, permerror. DKIM: pass, fail, none, policy, neutral, temperror, permerror. DMARC: pass, fail, none (no policy published).
softfail usually means the domain published ~all. Historically that asked receivers to accept but mark. Many filters still deliver softfail mail. Do not equate softfail with pass, and do not equate it with a hard fail.
none means no policy or no signature was found. A domain with dmarc=none is not authenticated; the check did not apply.
The lookalike trap
Suppose header From is it@cont0so.example (digit zero instead of the letter o), the attacker published SPF -all, DKIM, and p=reject, and Authentication-Results shows:
spf=pass smtp.mailfrom=cont0so.example;
dkim=pass header.d=cont0so.example;
dmarc=pass (p=reject) header.from=cont0so.example
Every protocol did its job — for cont0so.example. Users still read "Contoso IT." This is why section 8.1 walked From versus lookalike ownership before celebrating pass. SPF pass on a domain the attacker owns is the expected outcome of competent phishing infrastructure, not evidence of legitimacy. A real-brand p=reject policy does not block mail whose From domain is a different registered name.
A second trap is the opposite: a legitimate forwarder or mailing list breaks SPF (new connecting IP) and DKIM (body rewritten). DMARC then fails for a real newsletter. Analysts confirm by checking List-Unsubscribe, historical mail from the same d=, and whether the organisation allowlists that forwarder.
Verdict combinations
| SPF | DKIM | Alignment with From | DMARC | Typical story |
|---|---|---|---|---|
| pass | pass | yes | pass | Authorized path for that From domain. Still inspect content; mailbox compromise and lookalikes remain. |
| pass | fail | SPF aligned | pass | Common when a list modified the body but envelope still matches. |
| fail | pass | DKIM aligned | pass | Third-party sender that signs as the brand (marketing platform) but is not in SPF. |
| fail | fail | no | fail | Spoof, misconfigured forwarder, or domain without working auth. Read p= to see why it still arrived. |
| pass | pass | From is brand; auth is lookalike | fail for brand; pass for lookalike | Always compare the exact From domain string to the brand's organizational domain. |
| none | none | n/a | none | No published policy. Identity is unauthenticated. |
Worked pairing with the 8.1 invoice: the raw From, envelope, and DKIM domain all use paymnts-contoso.example, so SPF or DKIM can align and DMARC can pass for that attacker-owned lookalike. The display name still says Contoso Accounts Payable, which is the human deception. By contrast, if the raw From were ap@contoso.example while SPF and DKIM authenticated only paymnts-contoso.example, DMARC would fail for the From domain because neither identifier aligns. That is why you quote the raw From in the ticket, not the preview pane.
Another worked pairing: spf=softfail for contoso.com, dkim=none, dmarc=fail with p=quarantine. The envelope IP was not in Contoso's SPF (or only matched ~all), nothing was signed, and the receiver was asked to junk rather than reject. The message may still be in a quarantine portal. That is not a DKIM pass, and it is not proof of a lookalike — it is failed authentication of the claimed brand, which you still correlate with URLs and intent.
Operational limits — these checks do not stop all phishing
Do not write "DMARC protected us, so this cannot be phishing" in a case report. The protocols do not stop:
- Lookalike and cousin domains with their own correct DNS, including
p=rejecton the fake name. - Display-name-only impersonation from a random mailbox that authenticates as itself.
- QR-code lures that leave email authentication intact because the mail itself is a PDF.
- Compromised users sending from real accounts on authorized infrastructure.
- Homograph domains that still DMARC-pass as themselves.
Use Authentication-Results as one column in a table with domain-age, URL decode, attachment type, and business context. Pass answers "did this domain authorize the path?" It never answers "should a human trust this?"
When you escalate, paste the Authentication-Results block, the exact From and Return-Path, the published DMARC p= you observed (or none), and a one-line statement of alignment: aligned pass for lookalike X, or fail for brand Y. That language matches how gateways actually decide, and it keeps the next analyst from re-litigating a green pass badge in the mail client.
What does an SPF pass actually prove?
An attacker registers cont0so.example, publishes SPF, DKIM, and DMARC p=reject, and sends mail that fully passes. The real brand contoso.com also publishes p=reject. Why can the phishing message still authenticate?
A domain publishes DMARC p=none. Mail claiming that From domain fails both aligned SPF and aligned DKIM. What should an analyst expect?