Every security awareness program eventually has the same conversation:
"We sent the campaign yesterday. The dashboard says it went out. But
nobody clicked, and three people on Slack are asking why they didn't get
the test email."
Then somebody opens their spam folder and finds the simulated phish
sitting next to a Nigerian prince. The campaign isn't broken. The
deliverability is.
I've spent enough time debugging this for HailBytes SAT customers that I
can write the post-mortem from memory. Here it is.
The core problem
A phishing simulation is, by construction, an email designed to look
suspicious. Modern mail providers (Microsoft 365, Google Workspace,
Mimecast, Proofpoint) are trained on suspicious email and will quarantine
it aggressively unless you give them strong signals to trust the sender.
There are exactly four signals that matter at scale:
- SPF — does the sending IP have permission to send for this domain
- DKIM — is the message body cryptographically signed by the domain
- DMARC — what should receivers do if SPF/DKIM disagree
- Sender reputation — has this IP / domain pair sent good mail before
Get all four right and your campaigns hit the inbox. Miss any one and
you're fighting probabilities.
Step 1: do not send from your real corporate domain
This is the most common mistake. Teams deploy a phishing platform, point
it at noreply@theirrealcompany.com, and immediately damage their own
domain reputation when receivers flag the test as suspicious.
Use a separate purpose-built domain for simulated phishing.
security-training.example-corp.com or a fresh look-alike domain owned
by you. Publish DMARC on the real domain in p=reject. Run the sim
domain in p=none (or p=quarantine once warm) so receivers can
classify it as deliverable-but-suspicious — exactly the behaviour you
want for training.
Step 2: SPF that actually authorizes the sender
If you're running HailBytes SAT (or any platform) on your own EC2
instance and sending direct to MX, the SPF record on your sim domain
needs to authorize that IP:
v=spf1 ip4:203.0.113.42 -all
If you're relaying through SES, SendGrid, or Postmark:
v=spf1 include:amazonses.com -all
The two -all (hardfail) records will get you the strongest signal.
~all (softfail) is acceptable while warming up.
Step 3: DKIM, properly
DKIM is the part that breaks silently. Generate a 2048-bit key
(openssl genrsa -out dkim.key 2048) and publish the public half as a
TXT record at selector._domainkey.sim-domain.example.com. In SAT we
default to selector s1 — change it if you rotate keys.
The signature must cover at least From, Subject, Date, and
To. If your SMTP relay is rewriting headers, your signature will
break and DKIM will fail without an obvious error in the dashboard.
Verify with:
dig +short TXT s1._domainkey.sim-domain.example.com
Then send yourself a test message and check Authentication-Results in
the raw headers. You want dkim=pass.
Step 4: DMARC alignment
DMARC requires that either SPF or DKIM passes and the authenticated
domain matches the From: domain. This trips up almost everyone who uses
a relay service.
If your From: is security@sim.example.com but DKIM is signed by
amazonses.com, DMARC alignment fails even though DKIM itself passes.
Fix: either sign with your own domain (best) or set the relay to use a
custom MAIL FROM that aligns with your domain (acceptable).
Publish DMARC at _dmarc.sim-domain.example.com:
v=DMARC1; p=none; rua=mailto:dmarc-reports@example.com; pct=100
The p=none is intentional during warming. Move to p=quarantine once
your reports show consistent SPF and DKIM passes.
Step 5: warm the IP
A brand-new IP sending 5,000 phishing simulations on day one will go
straight to spam, no matter how clean your DMARC is. Reputation is
volume-and-pattern based.
Realistic warming schedule for a new sim IP:
| Day | Volume | Notes |
|---|---|---|
| 1-3 | 50 | Internal-only test accounts |
| 4-7 | 200 | Volunteer pilot group, mark "not spam" actively |
| 8-14 | 500 | First small department |
| 15+ | 2k+ | Full org, monitor postmaster tools |
Microsoft and Google both expose postmaster dashboards. Use them. If
you see reputation dropping to "low" or "bad" you're sending faster
than the receiver trusts.
Step 6: per-recipient header rules
Even with all of the above, individual mailboxes can have transport
rules that quarantine specific patterns. The single most useful thing
you can do as a security team is publish an internal allowlist
document that mail admins can apply to bypass quarantine for the
sim domain only. Most receivers support per-domain or per-IP overrides.
A reasonable Microsoft 365 example: add the sim IP to the IP Allow
List in the connection filter, and create a transport rule that sets
SCL to -1 for messages from *@sim-domain.example.com. This bypasses
spam filtering but, importantly, not the user's perception — the
email still arrives looking suspicious, which is the whole point.
The result
When customers walk through this checklist with HailBytes SAT, inbox
placement on Microsoft 365 typically goes from 30-40% (campaign
launched cold) to 90%+ (campaign launched after a 2-week warm). The
single biggest jump comes from getting DKIM alignment right, not from
any IP-warming voodoo.
If you want to skip the homework, the platform handles SPF / DKIM /
DMARC scaffolding and IP warming as part of deployment — full guide at
hailbytes.com/sat. But honestly, the
above checklist is product-agnostic. Whatever sim platform you're
running, work through these six steps before you blame the tool.
Top comments (0)