Spam Filter Whitelist
PhishSpot phishing simulations look like real attacks — that’s the point. Corporate spam filters (Microsoft 365, Google Workspace, Mimecast, Proofpoint, on-prem Postfix/SpamAssassin) will routinely block them unless they’re explicitly whitelisted. This chapter explains how to give your mail-server admin a single URL they can plug into their filter, and have it stay current automatically.
22.1 Why a whitelist?
Section titled “22.1 Why a whitelist?”SPF, DKIM and DMARC tell receiving servers “this email is genuinely from the domain it claims to be from.” For real phishing they often pass — that’s exactly why phishing is hard. But the same checks pass for our simulations too, and modern spam filters use much more than SPF/DKIM: they look at content patterns, link reputation, sender behaviour history, and dozens of other signals. Several of those signals will (correctly!) classify a phishing simulation as suspicious.
The right fix is for the receiving filter to bypass spam scanning for traffic that comes from PhishSpot. That requires the admin to tell their filter:
- which IP addresses we send from,
- which sending domains we use, and
- (optionally) which exact sender addresses appear on the From: header.
PhishSpot generates that list per account and exposes it at a stable URL. Configure your filter to pull it on a schedule (or react to our webhook when it changes) and you’re done.
22.2 Your whitelist URL
Section titled “22.2 Your whitelist URL”Open Account settings → Integrations → Spam Filter Whitelist. You’ll see a panel with:
- Your unique URL containing a 64-character secret token,
- A format picker (txt / json / csv / md / Microsoft 365 / Google Workspace / Mimecast / Proofpoint / Postfix / SpamAssassin),
- A status badge showing when the URL was last fetched and from which IP,
- A rotate button to invalidate the current URL,
- A disable toggle that returns 410 Gone until re-enabled,
- A live preview of what’s currently allowed,
- A download history of the last 50 fetches.
The URL is a single line you copy-paste into your spam filter or a small refresher script. There’s no API token, no Authorization header — the secret is in the path, and HTTPS encrypts it in transit. We rate-limit each token to 60 requests per minute, log every fetch (IP + UA) in the download history, and run on HTTPS only.
22.3 Picking the right format
Section titled “22.3 Picking the right format”| Format | When to use |
|---|---|
txt | Plain text. Default. Easy to grep and pipe into scripts. |
json | Structured payload. Best for custom integrations. |
csv | Generic CSV — good as a fallback. |
md | Human-readable Markdown — for documentation and review. |
microsoft365 | PowerShell snippet + Tenant Allow/Block List commands for Exchange Online. |
google-workspace | CSV laid out for the Google Admin email allowlist import. |
mimecast | CSV in Mimecast’s Permitted Senders policy shape. |
proofpoint | CSV in Proofpoint PPS Safelist shape. |
postfix | access table snippet for on-prem Postfix. |
spamassassin | whitelist_from lines for local.cf. |
URL pattern: https://platform.phishspot.com/api/v1/integrations/spam/<TOKEN>/<format> — leave the format off and you get plain text.
22.4 Setup guides per provider
Section titled “22.4 Setup guides per provider”22.4.1 Microsoft 365 / Exchange Online
Section titled “22.4.1 Microsoft 365 / Exchange Online”- In the PhishSpot panel, pick Microsoft 365 (PowerShell) and copy the URL.
- Save it to
phishspot-whitelist.ps1on a workstation that has Exchange Online PowerShell installed. - Run
Connect-ExchangeOnline(you’ll need Exchange Administrator rights). - Execute the script. It does two things:
- Adds each sending domain and address to the Tenant Allow/Block List with
New-TenantAllowBlockListItems, - Merges the gateway IPs into the Hosted Connection Filter Policy via
Set-HostedConnectionFilterPolicy.
- Adds each sending domain and address to the Tenant Allow/Block List with
- Optionally create a Mail Flow rule with “skip spam filtering” for senders matching
@<your-phishspot-domain>. Re-pull the URL weekly to keep the list current.
22.4.2 Google Workspace
Section titled “22.4.2 Google Workspace”- Pick the Google Workspace (CSV) format and download the file.
- In Google Admin Console, go to Apps → Google Workspace → Gmail → Spam, phishing and malware.
- Open the Email allowlist for your top-level OU and paste the IP entries from the CSV (one per line).
- Open Inbound gateway (also in Spam settings) and add the same IPs. This is what makes Gmail bypass spam scoring for those connections.
- To allow by domain instead of IP, add the domain entries from the CSV to the Approved senders list (same section).
22.4.3 Mimecast
Section titled “22.4.3 Mimecast”- Pick Mimecast (CSV) in the panel.
- In Mimecast Administration, go to Gateway → Policies → Permitted Senders.
- Click Import and upload the CSV. Mimecast picks up sender IPs from the
Sender IPcolumn and senders/domains from theSendercolumn. - Either schedule a
curljob (curl -fSL '<URL>' > whitelist.csvthen re-import) or use the Mimecast API for automation.
22.4.4 Proofpoint Protection Server (PPS)
Section titled “22.4.4 Proofpoint Protection Server (PPS)”- Pick Proofpoint PPS (CSV).
- Either upload via System → User Management → Safelists → Import in the PPS UI, or push via the PPS REST API (
/api/v1/safelist/import). - PPS treats sender, domain and IP entries differently — the CSV’s
typecolumn tells PPS which list to put each row in.
22.4.5 Postfix (on-prem)
Section titled “22.4.5 Postfix (on-prem)”- Pick Postfix access table.
- Save to
/etc/postfix/phishspot_whitelist, then runpostmap /etc/postfix/phishspot_whitelistto compile the lookup table. - Reference it from
main.cf:smtpd_sender_restrictions =check_sender_access hash:/etc/postfix/phishspot_whitelist,... - Run
postfix reload. - For IP-based bypass, copy the IPs into a separate CIDR file and add
check_client_access cidr:/etc/postfix/phishspot_ipstosmtpd_client_restrictions.
22.4.6 SpamAssassin
Section titled “22.4.6 SpamAssassin”- Pick SpamAssassin local.cf.
- Append the snippet to
/etc/spamassassin/local.cf. - Validate with
spamassassin -D --lint. - Restart
spamd. - The snippet uses
whitelist_from *@<domain>andtrusted_networks <ips>— the latter raises the trust score for relayed mail.
22.5 Auto-refresh via webhook
Section titled “22.5 Auto-refresh via webhook”The whitelist changes when you (or PhishSpot) add a sending domain, when a campaign uses a new From: address, or when our infrastructure team rotates gateway IPs. To keep the customer side current automatically:
- In Account settings → Webhooks → Endpoints, add a new endpoint pointing at a URL on your side.
- Subscribe to the event type
spam_whitelist.updated. - When the list changes we POST to that URL with a signed payload (HMAC-SHA256 in
X-Webhook-Signatureusing the endpoint’s signing secret). The payload includes the new snapshot digest and the full set of whitelist URLs across formats. - Your handler verifies the signature, then triggers your platform-specific import (the PowerShell job above, the Google Admin API call, Mimecast / Proofpoint API, etc.).
We retry failed deliveries 5 times with exponential backoff. After 5 consecutive failures we email account admins so the integration doesn’t silently rot.
22.6 Stale-fetch alerts
Section titled “22.6 Stale-fetch alerts”We track when each URL was last fetched. If 24 hours pass without a successful fetch — meaning your spam filter has stopped pulling the list — we email every admin on the account. The most common causes:
- The cron / scheduled task that pulls the URL stopped.
- Your firewall is now blocking outbound HTTPS to
platform.phishspot.com. - The URL was rotated and the old one expired before anyone updated the filter.
- The integration was removed from the spam filter accidentally.
To silence the warning, re-trigger the fetch from your side (one curl is enough — we reset the counter on every successful request).
22.7 Best practices
Section titled “22.7 Best practices”- Schedule the pull at least daily, ideally hourly. The endpoint is cheap to hit.
- Verify the snapshot digest (
X-PhishSpot-Snapshot-Digestheader) — if it matches what you have, skip the re-import to avoid noise in your downstream system. - Rotate quarterly. Even with no leak, regular rotation limits blast radius if a script ever logs the URL.
- Monitor your side too. Alert if the cron job hasn’t run successfully in N hours. Don’t rely only on our stale-warning email.
- Use the webhook in addition to the cron, not instead of it. The cron is the safety net; the webhook is the fast path.
- Test your bypass with PhishSpot’s “Send test email” feature in a campaign before going live. If the test doesn’t land in the recipient inbox, your bypass isn’t working.
22.8 FAQ & troubleshooting
Section titled “22.8 FAQ & troubleshooting”“Our phishing simulations still go to spam.” Confirm the spam filter is actually pulling the URL: check the download history in the PhishSpot panel — does the IP and timestamp match your filter’s egress IP and pull schedule? If yes, check the bypass rule is on the correct policy (often filters have separate inbound vs. transport policies). If no, the URL isn’t reaching the filter.
“The CSV format my filter expects is different.”
Use the plain csv format as a template and transform it server-side. The json format is the most flexible source — easy to map to any target schema with jq or a 20-line script.
“Our webhook isn’t receiving deliveries.”
Check the endpoint URL in Webhooks → Endpoints — make sure it’s HTTPS, publicly reachable, and not behind an authentication wall. Open the endpoint detail page in PhishSpot to see the delivery log with response codes and response bodies. Verify the HMAC signature handling on your side matches OpenSSL::HMAC.hexdigest("SHA256", signing_secret, raw_body).
“What if you change your gateway IPs?”
You’ll get a spam_whitelist.updated event the moment we make the change, and the URL response includes the new IPs immediately. If your filter has a fresh pull within the change window, you’ll never notice.
“Can I have multiple URLs for different filters?” Not in the MVP — there’s one active URL per account. If you need separate URLs (e.g., for a phased rollout), use the rotation flow: rotate, wait 24h, rotate again. Each rotation gives you a fresh URL with a 24-hour grace period.