Bulk Email Spoofing Checker (SPF, DMARC, DKIM, MX)
Pricing
$5.00 / 1,000 domain checkeds
Bulk Email Spoofing Checker (SPF, DMARC, DKIM, MX)
Check a list of domains for email spoofing risk. Passive DNS lookups of SPF, DMARC, DKIM and MX; returns a yes / risk / no verdict and the single most important fix per domain.
Pricing
$5.00 / 1,000 domain checkeds
Rating
0.0
(0)
Developer
Joshua Pole
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Bulk Email Spoofing Checker — SPF, DMARC, DKIM & MX
Can someone send email pretending to be your domain? Paste a list of domains and get one clear answer per domain — yes, risk or no — plus the one DNS fix that closes the gap, ready to copy-paste.
✅ Spoofable domains in seconds · ✅ One prioritised fix per domain · ✅ MTA-STS, BIMI, DNSSEC & CAA hardening score · ✅ 10,000 domains per run · ✅ 100% passive — DNS lookups only · ✅ No API keys
⚡ See it in 5 seconds
// input{ "domains": ["acme-shop.com"] }
// output{"domain": "acme-shop.com","spoofable": "yes","main_fix": "Move DMARC from p=none to p=quarantine, then p=reject (_dmarc.acme-shop.com).","issues": ["DMARC p=none (monitoring only, no enforcement)"]}
No scores to interpret, no 40-field reports to read. A verdict and the fix.
🎯 Who uses this
| You are | You use it to |
|---|---|
| MSP / IT service provider | Audit every client domain in one run and turn the fix_first list into a monthly report or upsell. |
| Security consultant / pentester | Add email-spoofing findings to an assessment in minutes — with the exact remediation per domain. |
| Agency / web builder | Check all domains you manage before a client's phishing incident does it for you. |
| Sales / lead generation | Find companies whose domain can be spoofed — a concrete, verifiable reason to start a security conversation. |
| IT admin with many domains | Find the forgotten parked domains with no SPF/DMARC that attackers love to abuse. |
🔍 What it checks
| Check | Details |
|---|---|
| DMARC | Record present and valid · policy p= · subdomain policy sp= · pct= · reporting address rua= · inheritance from the parent domain |
| SPF | Record present · single record · -all / ~all / ?all / +all · recursive DNS-lookup count (RFC 7208 limit of 10 → silent PermError) |
| DKIM | Probes ~35 common selectors: Google Workspace, Microsoft 365, Mailchimp, SendGrid, Mailgun, Zoho, Amazon SES, Proton, Fastmail … plus your own |
| MX | Mail servers · RFC 7505 null MX (domain that explicitly receives no mail) |
| Hardening (optional, on by default) | MTA-STS (forced encrypted delivery) · TLS-RPT (delivery failure reports) · BIMI (logo in the inbox) · DNSSEC (signed DNS) · CAA (which CA may issue certificates) → 0–100 hardening_score + next step |
| Domain | Non-existent (NXDOMAIN) and invalid domains are flagged — and not billed |
Input is forgiving: https://www.acme-shop.com/contact, info@acme-shop.com and ACME-SHOP.COM all become acme-shop.com. Duplicates are removed.
🚦 The verdict
spoofable | Meaning | Typical cause |
|---|---|---|
🔴 yes | Forged mail "from" this domain gets delivered. | No DMARC · invalid DMARC · p=none |
🟠 risk | DMARC is enforced, but with a hole. | pct<100 · sp=none (subdomains spoofable) · missing or broken SPF |
🟢 no | Protected against direct spoofing. | DMARC quarantine/reject at 100% + valid SPF |
⚪ error | Could not be checked — not billed. | Domain doesn't exist · invalid name · DNS timeout |
The hardening checks never change this verdict — they answer a different question: how well-defended is this domain beyond spoofing?
Every row also gets main_fix: the single most important change, written as an actual DNS record. Even no domains can get optional hardening (e.g. quarantine → reject, add rua= reporting).
Smart fixes, not generic advice
| Situation | main_fix you get |
|---|---|
| Parked domain, no mail at all | Lock it: TXT "v=spf1 -all" + _dmarc TXT "v=DMARC1; p=reject" |
| Sends mail, no SPF and no DMARC | Publish SPF with -all first, then DMARC with rua= reporting |
DMARC p=none | Move to p=quarantine, then p=reject |
Subdomain inherits a weak sp=none | Publish an own DMARC record on the subdomain |
DMARC pct=25 | Set pct=100 so all spoofed mail is blocked |
| SPF over 10 DNS lookups | Reduce SPF below 10 lookups — it now fails silently with PermError |
📊 Example: a portfolio run
Input — 10 domains, mixed formats:
{"domains": ["acme-shop.com", "https://www.northwind.io/", "info@contoso-bakery.nl","fabrikam.net", "parked-brand.com", "mail.tailspin.org","litware.com", "adatum.eu", "wingtip.co", "doesnotexist-zz9.nl"]}
Dataset → Overview view:
| domain | spoofable | SPF | DMARC | DKIM | main_fix |
|---|---|---|---|---|---|
| acme-shop.com | 🔴 yes | -all | none | ✓ | Move DMARC from p=none to p=quarantine, then p=reject. |
| contoso-bakery.nl | 🔴 yes | – | – | – | Publish SPF … -all. Then: add DMARC … p=reject; rua=mailto:… |
| parked-brand.com | 🔴 yes | – | – | – | Domain does not send mail? Lock it: v=spf1 -all + v=DMARC1; p=reject. |
| mail.tailspin.org | 🔴 yes | – | none (inherited) | – | Add an own DMARC record with p=reject — it now inherits sp=none from tailspin.org. |
| northwind.io | 🟠 risk | ~all | quarantine | ✓ | Remove sp=none so subdomains inherit p=quarantine. |
| fabrikam.net | 🟢 no | -all | quarantine | ✓ | Optional hardening: move DMARC to p=reject. |
| litware.com | 🟢 no | ~all | reject | ✓ | None — domain is protected against direct spoofing. |
| adatum.eu | 🟢 no | ~all | reject | ✓ | None — domain is protected against direct spoofing. |
| wingtip.co | 🟢 no | -all | reject | – | Optional: add rua= to DMARC to receive abuse reports. |
| doesnotexist-zz9.nl | ⚪ error | – | – | – | domain does not exist (NXDOMAIN) — not billed |
Key-value store → SUMMARY — your work queue, worst first:
{"domains": 10,"spoofable": 4,"at_risk": 1,"protected": 4,"errors": 1,"fix_first": [{ "domain": "acme-shop.com", "spoofable": "yes", "main_fix": "Move DMARC from p=none to p=quarantine, then p=reject (_dmarc.acme-shop.com)." },{ "domain": "contoso-bakery.nl", "spoofable": "yes", "main_fix": "Publish SPF: … Then: Add DMARC: …" },{ "domain": "northwind.io", "spoofable": "risk", "main_fix": "Remove sp=none from _dmarc.northwind.io so subdomains inherit p=quarantine." }]}
(Example domains are fictional; the verdicts and fixes are real outputs of this Actor on real DNS configurations.)
📥 Input
| Field | Type | Default | Description |
|---|---|---|---|
domains | string[] | — | Required. Domains, URLs or email addresses. Max 10,000 per run. |
dkimSelectors | string[] | [] | Extra DKIM selectors to probe on top of the ~35 built-in ones. |
nameservers | string[] | 1.1.1.1, 8.8.8.8 | Public DNS resolvers to use. |
concurrency | integer | 10 | Domains checked in parallel (1–50). |
extendedChecks | boolean | true | Add MTA-STS, TLS-RPT, BIMI, DNSSEC and CAA checks + hardening score. |
📤 Output fields
| Field | Description |
|---|---|
domain | Normalised domain name. |
spoofable | yes · risk · no · error |
main_fix | The single most important fix, as a concrete DNS record. |
issues | Every problem found, in plain English. |
mx / null_mx | Mail servers / whether the domain declares it receives no mail. |
spf_record · spf_all · spf_lookups | Raw SPF record · its all qualifier · recursive DNS-lookup count. |
dmarc_record · dmarc_policy · dmarc_subdomain_policy · dmarc_pct · dmarc_rua | Raw DMARC record and its parsed tags. |
dmarc_inherited_from | Parent domain whose DMARC applies, if the domain has none of its own. |
dkim_selectors_found | DKIM selectors with a published key. |
hardening_score | 0–100: MTA-STS 25 · DNSSEC 25 · CAA 20 · TLS-RPT 15 · BIMI 15 (mail-only checks are skipped for domains without mail). |
hardening_missing / hardening_next_step | Missing protections, biggest first, and the record to add for the top one. |
mta_sts_record · tls_rpt_record · bimi_record · caa_records · dnssec_signed | Raw hardening data. |
error | Why a domain could not be checked. |
checked_at | UTC timestamp of the check. |
Export as CSV, Excel, JSON, XML or HTML from the dataset tab, or connect it to Google Sheets, Zapier, Make or n8n.
🔌 Use it via API
Python
from apify_client import ApifyClientclient = ApifyClient("YOUR_API_TOKEN")run = client.actor("securityzenkai/email-spoof-checker").call(run_input={"domains": ["acme-shop.com", "northwind.io"]})for row in client.dataset(run["defaultDatasetId"]).iterate_items():print(f'{row["domain"]}: {row["spoofable"]} — {row["main_fix"]}')
JavaScript
import { ApifyClient } from "apify-client";const client = new ApifyClient({ token: "YOUR_API_TOKEN" });const run = await client.actor("securityzenkai/email-spoof-checker").call({domains: ["acme-shop.com", "northwind.io"],});const { items } = await client.dataset(run.defaultDatasetId).listItems();items.filter((r) => r.spoofable === "yes").forEach((r) => console.log(r.domain, "→", r.main_fix));
Schedule it (e.g. monthly) in Apify to catch the day someone weakens a DMARC record.
💰 Pricing
$5 per 1,000 domains checked ($0.005 per domain). You only pay for domains that were actually analysed — non-existent, invalid and timed-out domains are free. No subscription, no seats.
🛡️ Passive & safe by design
This Actor only performs public DNS lookups — the same queries every mail server makes when it receives an email. It never connects to, scans, logs into or sends email to the domains you check. That makes it safe to run on any list of domains, including prospects and third parties.
⚠️ What it does not do
- DKIM selectors can't be enumerated. "No DKIM found" means none of the common selectors — the domain may use a custom one. Add known selectors via
dkimSelectors. - MTA-STS is checked in DNS only. The
_mta-stsrecord is verified; the policy file onmta-sts.<domain>is not downloaded, to keep the Actor DNS-only. - DNSSEC = DS record published. It confirms the zone is signed at the registrar, not a full chain validation.
- No live SMTP tests. It doesn't connect to mail servers, so it doesn't verify STARTTLS or actual message signing.
- No look-alike domains.
acme-sh0p.comis a different problem (typosquatting); this Actor audits the domains you give it. - Parent-domain lookup is simplified. For DMARC inheritance it strips one label (
mail.acme.com→acme.com). - Point-in-time. DNS changes; results reflect the moment of the check (
checked_at).
❓ FAQ
What does "spoofable" actually mean?
An attacker can send email with your domain in the visible From: address and receiving mail servers will deliver it. Only an enforced DMARC policy (quarantine or reject) stops that — SPF alone does not, because SPF checks the hidden envelope sender, not the From: header people see.
Why is p=none rated yes?
p=none is monitoring mode: receivers report spoofed mail but still deliver it. It's the right first step, not the end state.
Why does a domain that never sends email need SPF and DMARC? Parked and unused domains are favourite spoofing targets precisely because nobody watches them. Two TXT records lock them down completely.
~all or -all?
With DMARC enforced, both are fine — DMARC does the blocking. Without DMARC, neither protects the From: header.
Is checking someone else's domain legal?
Yes — the Actor reads the same public DNS records any mail server or dig command reads. Nothing is scanned or probed.
Do I need API keys or accounts? No.
🔗 Related Actors
- Website Security & SSL Expiry Checker — grade the same domains A–F on security headers, TLS certificate expiry and HTTPS redirects.