Every email is two things at once: a human-readable message and a machine-readable protocol artifact. The protocol artifact — the headers — contains the forensic evidence you need to determine whether the email is legitimate. The human-readable message is what the attacker crafted to deceive the recipient.
Your job is to read both layers.
The Email Structure
┌─────────────────────────────────────────────┐
│ SMTP Envelope (invisible to user) │
│ MAIL FROM: <attacker@evil.com> │
│ RCPT TO: <victim@corp.com> │
├─────────────────────────────────────────────┤
│ RFC 5322 Headers (partially visible) │
│ Received: (multiple, tracing path) │
│ From: CEO Name <ceo@corp.com> │ ← What user sees
│ To: victim@corp.com │
│ Reply-To: attacker@evil.com │ ← Where replies go
│ Subject: Urgent Wire Transfer Request │
│ Date: Wed, 14 Aug 2024 09:21:03 +0000 │
│ Authentication-Results: ... │
│ DKIM-Signature: v=1; a=rsa-sha256... │
├─────────────────────────────────────────────┤
│ Body │
│ [HTML or plain text content] │
│ [Embedded links, attachments] │
└─────────────────────────────────────────────┘
The Received Chain
The Received chain is the forensic record of every server that handled the email. Read it bottom-to-top — the bottom is where the email started.
Example chain:
Received: from mx.corp.com (mx.corp.com [10.1.0.5])
by mail.corp.com with ESMTP; Wed, 14 Aug 2024 09:21:08 UTC
← Your mail server added this (top = most recent)
Received: from mail.attacker.com (mail.attacker.com [45.33.32.156])
by mx.corp.com with ESMTPS (TLS1.3); Wed, 14 Aug 2024 09:21:05 UTC
← Your mail gateway received from attacker's server
Received: from [192.168.1.5] (attacker-laptop [192.168.1.5])
by mail.attacker.com with ESMTPA; Wed, 14 Aug 2024 09:21:00 UTC
← Attacker's server received from attacker's local machine (bottom = origin)
Reading this chain:
- Email originated from
192.168.1.5(attacker’s private network — suspicious, usually would be NAT’d to public IP) - Passed through
mail.attacker.comat IP45.33.32.156 - Entered your org at
mx.corp.com - Delivered to
mail.corp.com
The outermost IP (where your mail gateway first received from the internet) is 45.33.32.156. This is the IP you submit to threat intel feeds.
SPF, DKIM, DMARC — The Authentication Trifecta
SPF (Sender Policy Framework)
SPF publishes a list of IP addresses authorized to send email for a domain, in DNS.
corp.com TXT "v=spf1 include:_spf.google.com ip4:192.0.2.1 ~all"
include:_spf.google.com— Google Workspace is authorized to send for corp.comip4:192.0.2.1— this specific IP is authorized~all— anything else is a softfail (should be -all for strict orgs)
SPF validates the SMTP envelope sender (Return-Path), NOT the visible From: header.
| SPF Result | Meaning |
|---|---|
| pass | Sending IP is authorized |
| fail | Sending IP is not authorized (hard fail) |
| softfail | Sending IP is not authorized (soft fail — ~all policy) |
| neutral | Domain hasn’t stated a policy |
| none | No SPF record exists |
| permerror | SPF evaluation error (often: >10 DNS lookups) |
DKIM (DomainKeys Identified Mail)
DKIM adds a cryptographic signature to the email. The sending domain publishes a public key in DNS. Your mail server verifies the signature on receipt.
DKIM-Signature: v=1; a=rsa-sha256; d=corp.com; s=selector1;
bh=<body_hash>; h=from:to:subject:date; b=<signature>
DKIM validates that the email content was signed by the domain owner. It proves the email wasn’t modified in transit and originated from someone with the domain’s private key.
DKIM does NOT validate the From: address — an attacker can DKIM-sign mail from their own domain attacker.com and still spoof the display name.
DMARC (Domain-based Message Authentication, Reporting & Conformance)
DMARC adds the alignment requirement. It says: “The From: header domain must match the domain that passed SPF or DKIM.”
corp.com TXT "v=DMARC1; p=reject; rua=mailto:dmarc@corp.com"
p=reject— reject mail that fails DMARC alignmentp=quarantine— send to spam folderp=none— no action, but generate reports
DMARC alignment:
- SPF alignment: envelope sender domain = From: header domain
- DKIM alignment: DKIM
d=domain = From: header domain
The Authentication-Results Header: Field Map
Authentication-Results: mx.corp.com;
spf=pass smtp.mailfrom=sender@attacker.com;
dkim=pass header.d=attacker.com header.s=selector1;
dmarc=fail (p=reject) header.from=corp.com reason="SPF not aligned"
| Field | Meaning |
|---|---|
spf= | SPF result |
smtp.mailfrom= | The envelope sender (MAIL FROM) that SPF evaluated |
dkim= | DKIM result |
header.d= | The domain the DKIM signature claims (d= tag) |
header.s= | The DKIM selector (used to look up the public key in DNS) |
dmarc= | DMARC result |
(p=reject) | The DMARC policy for the From: header domain |
header.from= | The domain in the visible From: header |
M3AAWG Email Authentication Recommended Best Practices— M3AAWG ATT&CK T1566 — Phishing— MITRE ATT&CK