Bulk Email Spoofing Checker (SPF, DMARC, DKIM, MX) avatar

Bulk Email Spoofing Checker (SPF, DMARC, DKIM, MX)

Pricing

$5.00 / 1,000 domain checkeds

Go to Apify Store
Bulk Email Spoofing Checker (SPF, DMARC, DKIM, MX)

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

Joshua Pole

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

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 areYou use it to
MSP / IT service providerAudit every client domain in one run and turn the fix_first list into a monthly report or upsell.
Security consultant / pentesterAdd email-spoofing findings to an assessment in minutes — with the exact remediation per domain.
Agency / web builderCheck all domains you manage before a client's phishing incident does it for you.
Sales / lead generationFind companies whose domain can be spoofed — a concrete, verifiable reason to start a security conversation.
IT admin with many domainsFind the forgotten parked domains with no SPF/DMARC that attackers love to abuse.

🔍 What it checks

CheckDetails
DMARCRecord present and valid · policy p= · subdomain policy sp= · pct= · reporting address rua= · inheritance from the parent domain
SPFRecord present · single record · -all / ~all / ?all / +all · recursive DNS-lookup count (RFC 7208 limit of 10 → silent PermError)
DKIMProbes ~35 common selectors: Google Workspace, Microsoft 365, Mailchimp, SendGrid, Mailgun, Zoho, Amazon SES, Proton, Fastmail … plus your own
MXMail 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
DomainNon-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

spoofableMeaningTypical cause
🔴 yesForged mail "from" this domain gets delivered.No DMARC · invalid DMARC · p=none
🟠 riskDMARC is enforced, but with a hole.pct<100 · sp=none (subdomains spoofable) · missing or broken SPF
🟢 noProtected against direct spoofing.DMARC quarantine/reject at 100% + valid SPF
⚪ errorCould 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

Situationmain_fix you get
Parked domain, no mail at allLock it: TXT "v=spf1 -all" + _dmarc TXT "v=DMARC1; p=reject"
Sends mail, no SPF and no DMARCPublish SPF with -all first, then DMARC with rua= reporting
DMARC p=noneMove to p=quarantine, then p=reject
Subdomain inherits a weak sp=nonePublish an own DMARC record on the subdomain
DMARC pct=25Set pct=100 so all spoofed mail is blocked
SPF over 10 DNS lookupsReduce 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:

domainspoofableSPFDMARCDKIMmain_fix
acme-shop.com🔴 yes-allnone✓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~allquarantine✓Remove sp=none so subdomains inherit p=quarantine.
fabrikam.net🟢 no-allquarantine✓Optional hardening: move DMARC to p=reject.
litware.com🟢 no~allreject✓None — domain is protected against direct spoofing.
adatum.eu🟢 no~allreject✓None — domain is protected against direct spoofing.
wingtip.co🟢 no-allreject–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

FieldTypeDefaultDescription
domainsstring[]—Required. Domains, URLs or email addresses. Max 10,000 per run.
dkimSelectorsstring[][]Extra DKIM selectors to probe on top of the ~35 built-in ones.
nameserversstring[]1.1.1.1, 8.8.8.8Public DNS resolvers to use.
concurrencyinteger10Domains checked in parallel (1–50).
extendedChecksbooleantrueAdd MTA-STS, TLS-RPT, BIMI, DNSSEC and CAA checks + hardening score.

📤 Output fields

FieldDescription
domainNormalised domain name.
spoofableyes · risk · no · error
main_fixThe single most important fix, as a concrete DNS record.
issuesEvery problem found, in plain English.
mx / null_mxMail servers / whether the domain declares it receives no mail.
spf_record · spf_all · spf_lookupsRaw SPF record · its all qualifier · recursive DNS-lookup count.
dmarc_record · dmarc_policy · dmarc_subdomain_policy · dmarc_pct · dmarc_ruaRaw DMARC record and its parsed tags.
dmarc_inherited_fromParent domain whose DMARC applies, if the domain has none of its own.
dkim_selectors_foundDKIM selectors with a published key.
hardening_score0–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_stepMissing protections, biggest first, and the record to add for the top one.
mta_sts_record · tls_rpt_record · bimi_record · caa_records · dnssec_signedRaw hardening data.
errorWhy a domain could not be checked.
checked_atUTC 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 ApifyClient
client = 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-sts record is verified; the policy file on mta-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.com is 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.