Fast, async email verification CLI. Validate single addresses or entire CSV lists: syntax, MX/DNS records, SMTP catch-all detection, disposable and role-account detection, typo suggestions, and a deliverability score — all locally, no third-party verification API required.
Clean your email lists before a campaign, reduce bounce rates, and protect your sender reputation — straight from the terminal.
- ✅ Syntax validation (RFC 5321 length and dot rules, not just a naive regex)
- 🌐 MX / DNS lookup with per-domain caching (transient DNS errors are never cached)
- 📬 SMTP catch-all detection — flags domains that accept any mailbox
- 🗑️ Disposable email detection (Mailinator, YOPmail, 10minutemail… including subdomains)
- 👔 Role account detection (
info@,sales@,support@…) with company-domain matching - ✏️ Typo suggestions —
juan@gmial.com→ did you meanjuan@gmail.com? - 🎲 Random/suspicious local-part detection (
a8f3k2j9x7q1@…) - 📊 Deliverability scoring (0–100) per address
- ⚡ Async bulk verification of CSV files with configurable concurrency
- 📤 Mailrelay integration — push verified contacts to a group in one command
pip install mailcheck-cli
# or
pipx install mailcheck-cli# Verify a single email address
mailcheck check juan@empresa.com
# Verify a CSV list in bulk (auto-detects the email column)
mailcheck bulk list.csv -o results.csv --workers 20
# DNS-only mode (skip SMTP probing — faster, firewall-friendly)
mailcheck bulk list.csv -o results.csv --no-smtp
# Push verified contacts to Mailrelay
mailcheck push-mailrelay results.csv --api-key $MAILRELAY_API_KEY --group-id 42 --filter valid| Flag | Description |
|---|---|
--no-smtp |
Skip the SMTP catch-all probe (DNS/MX only) |
--strict |
Count risky results as invalid in the summary |
--workers N |
Parallel verifications (default 20) |
--email-column COL |
Explicit email column name for bulk |
--limit N |
Only verify the first N rows |
--filter valid|valid+risky|all |
Which statuses push-mailrelay uploads |
| Status | Reason | Score |
|---|---|---|
| invalid | invalid_format |
0 |
| invalid | missing_mx |
0 |
| invalid | disposable |
5 |
| invalid | placeholder |
10 |
| risky | domain_typo (suggestion included) |
15 |
| risky | role_account_without_domain_match |
40 |
| risky | suspicious_local_part |
50 |
| risky | dns_error |
60 |
| risky | free_email_domain (B2B mode) |
65 |
| valid | ok on a catch-all domain |
80 |
| valid | role_account_on_company_domain |
90 |
| valid | ok |
100 |
Each processed row gets: mc_status, mc_reason, mc_score, mc_catch_all, mc_suggestion.
0— all valid1— some risky results2— some invalid results
Useful for CI pipelines and shell scripting.
docker build -t mailcheck .
docker run --rm -v $(pwd):/app mailcheck check juan@empresa.comimport asyncio
from mailcheck import EmailVerifier
verifier = EmailVerifier(check_smtp=False)
result = asyncio.run(verifier.verify("juan@empresa.com"))
print(result.status, result.score, result.suggestion)pip install -e ".[dev]"
pytestMIT