How a phishing email gets past SPF, DKIM and DMARC
One fictional phishing email, checked by SPF, DKIM and DMARC: what each verifies, why p=none and look-alike domains let it through, and what to do if you click.
Beginner8 min read
│ │ header From: corp.example J ┌──────────┐ ┊ ┊ ┊ │ INBOX │ ┊ ┊ ┊ │ │ ┌───┐ ┊ ┊ ┊ │ │ │\ /│ ─────────════════════───────────────────────│ ──────── │ └───┘ ┊ ┊ ┊ │ ──────── │ ┊ ┊ ┊ │ │ ┊ ┊ ┊ │ ──────── │ SPF DKIM DMARC │ ──────── │ └──────────┘
On this page
- What Dao sees
- What the headers say
- Checkpoint 1: SPF asks "may this server send for that domain?"
- Checkpoint 2: DKIM asks "did this domain sign this message, unchanged?"
- Checkpoint 3: DMARC asks "do those passes belong to the From domain?"
- Act two: the attacker changes one letter
- The human layer
- The same trick, through many doors
- Dao clicked. Now what?
- The anatomy, in one breath
This is the story of one email. Everything in it is made up: the company, the person, the domains. The domain names end in .example, a top-level domain reserved for documentation by RFC 2606, so none of them can belong to anyone. What is real is the machinery the email passes through on its way to an inbox, and the places where that machinery can be fooled.
Our fictional company is Example Corp, and its mail domain is corp.example. Our fictional reader is Dao, who works there. It is Monday morning, and a new message is waiting.
What Dao sees
Dao's mail app shows three things:
- From: IT Service Desk
- Subject: Action needed today
- Body: "Your password expires in 24 hours. Please confirm here: [Your account]"
That is the whole picture for most of us. A friendly name, a deadline and a button. Notice that the app shows the display name ("IT Service Desk") and hides the actual address unless Dao taps on it. That detail matters later.
What the headers say
Behind the friendly view, every message carries headers. One of them is added by the receiving mail server to record what its checks found. It is called Authentication-Results, and it is defined in RFC 8601. For our fictional email it might look like this:
From: "IT Service Desk" <it-desk@corp.example>
Authentication-Results: mx.corp.example;
spf=pass smtp.mailfrom=bounce.mailer.example;
dkim=pass header.d=mailer.example;
dmarc=fail header.from=corp.example
Two passes and a fail. To understand why, we need to look at each checkpoint in turn.
Checkpoint 1: SPF asks "may this server send for that domain?"
Sender Policy Framework is defined in RFC 7208. A domain owner publishes a DNS TXT record that starts with v=spf1 and lists the servers allowed to send mail for the domain. The receiving server looks at the IP address that connected to it and checks that list.
The key detail is which domain SPF checks. It looks at the HELO name and the envelope sender (MAIL FROM), the address used for bounces, not the From: line Dao sees. The RFC says plainly that these checks do not provide assurance about other identities "such as the From: header field".
So the attacker in our story simply used an envelope address on a domain they control, bounce.mailer.example, and published an SPF record for it. SPF said pass, and it was right: that server is allowed to send for bounce.mailer.example. It just has nothing to do with corp.example.
A few other SPF facts worth knowing:
- Results include
pass,fail,softfail,neutral,none,temperrorandpermerror(section 2.6). - Evaluation may trigger at most 10 DNS-querying terms (
include,a,mxand so on); going over givespermerror(section 4.6.4). - Forwarding breaks SPF easily, because the forwarder's IP is checked instead of the original sender's (section 10.3).
Checkpoint 2: DKIM asks "did this domain sign this message, unchanged?"
DomainKeys Identified Mail is RFC 6376, an Internet Standard. The sending system adds a DKIM-Signature header containing a hash of the body (bh=), the list of signed headers (h=), the signature itself (b=), the signing domain (d=) and a selector (s=). The receiver fetches the public key from DNS at <selector>._domainkey.<domain> and verifies.
A passing signature proves two things: the domain in d= takes some responsibility for the message, and the signed parts have not changed since signing. It does not say the domain is trustworthy, and the standard does not require the signing identity to match the visible sender.
Our attacker signed the message with their own key for mailer.example. DKIM said pass, and again it was right.
Checkpoint 3: DMARC asks "do those passes belong to the From domain?"
This is the checkpoint that connects the technical checks to what Dao actually sees. DMARC was first published as RFC 7489 in March 2015, an Informational document rather than a standard. In May 2026 it was made obsolete by RFC 9989, a Proposed Standard, which comes with two companion RFCs for reporting, 9990 and 9991. The core idea is the same in both: alignment.
A message passes DMARC only if SPF or DKIM passes and the passing domain aligns with the domain in the From: header. In relaxed mode the two must share an organizational domain; in strict mode they must match exactly (section 3.1).
In our story, From: says corp.example. SPF passed for bounce.mailer.example. DKIM passed for mailer.example. Neither aligns, so DMARC says fail.
│ │ header From: corp.example J ┌──────────┐ ┊ ┊ ┊ │ INBOX │ ┊ ┊ ┊ │ │ ┌───┐ ┊ ┊ ┊ │ │ │\ /│ ─────────════════════───────────────────────│ ──────── │ └───┘ ┊ ┊ ┊ │ ──────── │ ┊ ┊ ┊ │ │ ┊ ┊ ┊ │ ──────── │ SPF DKIM DMARC │ ──────── │ └──────────┘
Why p=none protects nobody
Here is the twist. A failed DMARC check does not stop anything by itself. The receiver looks up the domain owner's policy in a TXT record at _dmarc.corp.example, and the p= tag says what to do:
| Policy | What the domain owner asks for |
|---|---|
p=none |
No specific action regarding delivery (RFC 7489 §6.3) |
p=quarantine |
Treat failing mail as suspicious, for example the spam folder |
p=reject |
Reject failing mail, ideally during the SMTP conversation |
Example Corp, in our story, published p=none and never moved on. The newer RFC 9989 says a discovered p=none policy must not modify existing mail handling processes. So the email that failed DMARC landed in Dao's inbox anyway.
p=none is a useful starting point: the reports (rua=) show who sends mail in your name before you enforce anything. Google, for example, requires bulk senders to Gmail to publish DMARC since 1 February 2024, but accepts a policy of none. Joint guidance from CISA, NSA, FBI and MS-ISAC goes further and recommends that organizations set DMARC to "reject" for the mail they send. Monitoring is a phase, not a destination.
Act two: the attacker changes one letter
Suppose Example Corp fixes its policy and moves to p=reject. Spoofing corp.example directly now fails. So the attacker registers a look-alike domain, c0rp-login.example (a zero instead of an "o"), and sets up SPF, DKIM and DMARC for it properly. Every check now passes, because the mail really does come from c0rp-login.example.
This is not a flaw in DMARC; it is outside its job. RFC 7489 lists "visually similar domain names ("cousin domains")" and abuse of the display name as things it does not address. The display name is free text: anyone can write "IT Service Desk".
That leaves the last layer.
The human layer
CISA's guidance on recognizing phishing lists signs that still hold up well:
- Urgent or emotional language: especially messages that claim dire consequences if you don't respond immediately. "24 hours" is doing that job in our email.
- Requests to send personal or financial information.
- Incorrect email addresses or links: look-alike spellings, such as one wrong letter in a brand name.
- Untrusted shortened links, which hide the destination.
CISA also notes that poor grammar used to be a common sign, but in the era of AI some phishing emails have perfect grammar and spelling, so the other signs matter more.
The most practical habit is to check where a link really goes. The words on a button and its destination are two separate things. CISA's advice on avoiding phishing suggests hovering over a link before clicking: if the address shown does not match the text, the link may be spoofed.
┌──────────────────────────────────────────────────────────────┐ │ ● ● ● mail │ │──────────────────────────────────────────────────────────────│ │ • From: IT Service Desk │ │ Subject: Action needed today │ │ Your password expires in 24 hours. │ │ Please confirm here: [Your account] │ │ │ │ │ │ ↖ │ │──────────────────────────────────────────────────────────────│ │ │ └──────────────────────────────────────────────────────────────┘
If a message might be genuine, CISA's advice is not to use any link or phone number in it, and to reach the company through contact details from its verified website, or the person through another way you already have, such as their phone number.
The same trick, through many doors
Email is the classic route, but not the only one. MITRE ATT&CK files phishing as technique T1566 under the Initial Access tactic, with four sub-techniques:
| ID | Name | The lure |
|---|---|---|
| T1566.001 | Spearphishing Attachment | A malicious file attached to the message |
| T1566.002 | Spearphishing Link | A link to a malicious page or download |
| T1566.003 | Spearphishing via Service | Delivered through a third-party service such as social media |
| T1566.004 | Spearphishing Voice | A message that gets the victim to call a phone number |
ATT&CK notes that phishing can be targeted at a person or company, or sent as a mass campaign. Among its listed mitigations are user training and software configuration, which includes SPF, DKIM and DMARC. In other words, neither layer is expected to work alone.
Dao clicked. Now what?
In our story, Dao clicks, sees a login page that looks right, types a password, and then gets a bad feeling. What happens next matters more than the click.
The UK's National Cyber Security Centre is blunt about this in its phishing guidance for organizations: "Some phishing attacks will always get through", and people should feel able to report "even when they have 'clicked'". It warns against a blame culture, because employees who fear for their jobs will not report mistakes.
What helps, drawing on CISA's advice:
- Tell your IT or security team right away. They can be alert for suspicious or unusual activity.
- Change the password you typed straight away, and change it on every other account where you used the same one.
- Report the message, for example with your mail app's report button. The joint CISA guidance calls reporting one of the most efficient methods for protecting organizations, because it helps email providers spot new or trending phishing attacks.
- Watch your accounts for charges or activity you can't explain.
The same joint guidance also recommends FIDO or PKI-based MFA, which it describes as phishing resistant. It warns that weaker forms of MFA can still be defeated through phishing.
The anatomy, in one breath
SPF checks the sending server against the envelope domain. DKIM checks a signature from whichever domain signed. DMARC checks that those results belong to the From: domain, and its policy decides what happens when they don't. None of them checks whether c0rp is corp. That last check belongs to a person, and the kindest thing an organization can do is make it easy and safe for that person to say "I think I clicked something."
Sources
- RFC 2606: Reserved Top Level DNS Names
- RFC 8601: Message Header Field for Indicating Message Authentication Status
- RFC 7208: Sender Policy Framework (SPF) for Authorizing Use of Domains in Email, Version 1
- RFC 6376: DomainKeys Identified Mail (DKIM) Signatures
- RFC 7489: Domain-based Message Authentication, Reporting, and Conformance (DMARC)
- RFC 9989: Domain-Based Message Authentication, Reporting, and Conformance (DMARC), IETF Datatracker
- Google Workspace Admin Help: Email sender guidelines
- CISA, NSA, FBI, MS-ISAC: Phishing Guidance: Stopping the Attack Cycle at Phase One
- CISA: Recognize and Report Phishing
- CISA: Avoiding Social Engineering and Phishing Attacks
- MITRE ATT&CK: Phishing, Technique T1566
- NCSC: Phishing attacks: defending your organisation
Keep reading
Related posts
Network security
How to read MITRE ATT&CK without treating it as a checklist
What MITRE ATT&CK is, how tactics, techniques and procedures fit, how to read a technique page, and how to use Navigator layers without chasing 100%.
Beginner9 min read
- MITRE ATT&CK
- D3FEND
- Detection engineering
- Threat intelligence
- SOC
Network security
Find a port scan and a password spray in firewall and auth logs
Practise on synthetic logs: read syslog and PAN-OS traffic fields, find a port scan and a password spray (event 4625), then link them by time and source.
Intermediate12 min read
- Logging
- Firewall Logs
- Windows Event 4625
- Port Scan
- Password Spraying
- MITRE ATT&CK
- NIST SP 800-92
Network security
Five network segmentation myths, checked against CISA and NIST
VLANs alone are not segmentation. Five common myths checked against CISA, NIST and MITRE guidance, plus a default-deny rollout and ways to test it.
Beginner10 min read
- network segmentation
- microsegmentation
- zero trust
- lateral movement
- MITRE ATT&CK
- CISA
- NIST
- firewalls