mxverify
Fast email verification with no API key. Check syntax, disposable domains, role addresses, and live MX records — then get each email tagged valid / risky / invalid, with a reason. Zero dependencies, works offline except for the DNS lookups it needs.
No Hunter, no NeverBounce, no ZeroBounce account. No per-email billing. Just a tiny library + CLI you run yourself.
npx mxverify jane@stripe.com hello@apify.com test@mailinator.com
VALID mx-ok jane@stripe.com
RISKY role-based hello@apify.com [role]
INVALID disposable test@mailinator.com [disposable]
3 checked — 1 valid, 1 risky, 1 invalid
Why
Most "is this email real?" tools want an API key and bill you per check. For a lot of jobs — cleaning a lead list, gating a signup form, deduping a CSV — you don't need a paid service. You need four cheap checks done locally:
- Syntax — is it a well-formed address? (RFC-ish, rejects what real mail servers reject)
- Disposable — is the domain a throwaway? (built-in blocklist of ~6,900 domains)
- Role-based — is it
info@ / sales@ / noreply@? (deliverable, but not a person — you decide)
- MX records — can the domain actually receive mail? (live DNS lookup, with an A-record fallback per RFC 5321)
mxverify does exactly that and nothing else. It never contacts the mailbox (no SMTP probe by default), so it's safe to run against a prospect list without touching anyone.
Install
npm install mxverify
npm install -g mxverify
Library
import { verifyEmail, verifyEmails } from 'mxverify';
const one = await verifyEmail('jane@stripe.com');
const results = await verifyEmails(['a@x.com', 'b@x.com', 'info@y.com']);
const sendReady = results.filter((r) => r.status === 'valid');
Status & reason
valid | well-formed, not disposable, domain has MX | mx-ok |
risky | deliverable but lower confidence | role-based, implicit-mx, mx-unknown |
invalid | don't send | invalid-syntax, disposable, no-mx |
risky covers role addresses (info@), domains that receive mail via an A record instead of MX (RFC 5321), and lookups that couldn't complete (timeout / SERVFAIL) — those are flagged, not silently dropped.
Options
verifyEmail(email, {
checkMx: true,
mxTimeoutMs: 5000,
mxCache: new Map(),
});
CLI
mxverify someone@example.com
mxverify --file emails.txt
cat emails.txt | mxverify --stdin
mxverify --file emails.txt --json
mxverify --file emails.txt --fast
Exit code is non-zero when every input email is invalid — handy in CI/scripts.
How the MX check stays accurate
A naive MX lookup marks live domains (like google.com, whose MX answer some resolvers truncate) as dead. mxverify falls back to an A/AAAA lookup when there's no MX record — per RFC 5321 the A record is the implicit mail exchanger — and only returns no-mx when the domain resolves to nothing at all. It also sets public DNS resolvers as a fallback so it works on locked-down hosts where Node's default resolver fails.
Need emails to verify?
mxverify cleans a list you already have. If you need to build one, the verification logic here also ships inside an Apify actor that scrapes business emails from Google Maps and websites and verifies them in the same run: Google Maps Email Scraper and Website Contact & Email Finder.
License
MIT © Renzo Madueno