verify-email
Skill2 starsChanged 7 months agoMITView on GitHub
Verify whether email addresses are reachable without sending an email. Checks syntax, DNS/MX records, disposable domains, and SMTP mailbox existence.
- Sends data out
In this repository11 other files it gives its agents.
- add-ai-access-scrapersSkill
- answer-questionsSkill
- enrich-storiesSkill
- find-photo-evidenceSkill
- generate-story-leadsSkill
- geographic-source-discoverySkill
- identify-new-questions-from-articleSkill
- new-skillSkill
- trusted-human-source-discoverySkill
- trusted-source-discoverySkill
- web-fetch-cloudflare-circumventSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
30 rules. About 0 are common, 17 are distinctive, and 13 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈17
Distinctive · estimate
This author's own choices. Worth a look.
13
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 10
Verify the email matches a valid format: one @, valid local part (no leading/trailing dots, no consecutive dots), and a valid domain (valid …
- Distinctive: line 13
If the syntax is invalid, mark the email as Invalid (bad syntax) and skip remaining steps.
- Very specific: line 17
Run dig +short <domain> MX via Bash.
- Very specific: line 19
If no MX records are returned, try dig +short <domain> A as a fallback (some domains accept mail on their A record).
- Distinctive: line 20
If neither returns results, mark as Invalid (no mail server) and skip remaining steps.
- Distinctive: line 21
If MX records exist, note the lowest-preference (primary) MX server for Step 4.
- Distinctive: line 25
Check whether the domain is a known disposable/temporary email provider.
- Distinctive: line 29
If disposable, flag it as Warning: disposable email provider but continue to Step 4.
- Distinctive: line 35
Run this Bash script, substituting the email and MX server:
- Very specific: line 79
Connection refused/timeout: check (once per run) whether outbound port 25 works at all: timeout 8 bash -c 'exec …
- Distinctive: line 81
If that fails, mark as Indeterminate (port 25 blocked locally).
- Very specific: line 88
After the RCPT TO check, if the result was 250, test whether the domain is catch-all by checking a clearly fake address: …
- Very specific: line 99
Call browser_navigate to https://account.live.com/password/reset
- Very specific: line 100
Call browser_snapshot to find the email input field.
- Very specific: line 101
Call browser_fill_form to enter the email address into the email input.
- Very specific: line 102
Call browser_click on the "Next" button.
- Very specific: line 103
Wait 3 seconds, then call browser_snapshot and check:
- Distinctive: line 104
If the page contains text like "that Microsoft account doesn't exist" or "No account found with that email" → Unreachable (account not …
- Distinctive: line 105
If the page shows identity verification options ("verify your identity", "send a code", "authenticator app") → Reachable (account exists)
- Distinctive: line 106
If a CAPTCHA appears, note it and mark as Indeterminate (CAPTCHA blocked)
- Very specific: line 111
Call browser_snapshot to find the email/phone input field.
- Very specific: line 112
Call browser_fill_form to enter the email address.
- Very specific: line 113
Call browser_click on "Continue".
- Distinctive: line 115
If the page shows an error message like "Sorry, we don't recognize that email" → Unreachable (account not found)
- Distinctive: line 116
If the page shows verification options (send a code, security key, etc.) → Reachable (account exists)
- Distinctive: line 121
Before using the headless browser, try the faster API check:
- Distinctive: line 141
Use the SMTP RCPT TO check from Step 4.
- Distinctive: line 158
After the table, briefly explain any indeterminate results and suggest next steps (e.g., "send a confirmation email to verify" for …
- Distinctive: line 163
Before presenting results, inform the user of the following:
- Distinctive: line 171
No technique — free or paid — can definitively verify a specific mailbox on a catch-all domain without sending.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
You will be given one or more email addresses (comma-separated). For each email address, run the verification pipeline below. Report results in a summary table at the end.
Step 1: Syntax check
Verify the email matches a valid format: one @, valid local part (no leading/trailing dots, no consecutive dots),
and a valid domain (valid hostname characters, at least one dot).
If the syntax is invalid, mark the email as Invalid (bad syntax) and skip remaining steps.
Step 2: DNS/MX record check
Run dig +short <domain> MX via Bash. Inspect the results:
- If no MX records are returned, try
dig +short <domain> Aas a fallback (some domains accept mail on their A record). - If neither returns results, mark as Invalid (no mail server) and skip remaining steps.
- If MX records exist, note the lowest-preference (primary) MX server for Step 4.
Step 3: Disposable email check
Check whether the domain is a known disposable/temporary email provider. Search the web for
"is <domain> a disposable email" or check against well-known disposable domains (mailinator.com, guerrillamail.com,
tempmail.com, throwaway.email, yopmail.com, sharklasers.com, 10minutemail.com, trashmail.com, etc.).
If disposable, flag it as Warning: disposable email provider but continue to Step 4.
Step 4: SMTP RCPT TO verification
This step connects to the mail server and asks if the mailbox exists without sending an email.
Run this Bash script, substituting the email and MX server:
{
exec 3<>/dev/tcp/<mx_server>/25
timeout=5
# Read greeting
read -t $timeout -u 3 greeting
echo "GREETING: $greeting"
# HELO
echo -e "HELO verify.local\r" >&3
read -t $timeout -u 3 helo_resp
echo "HELO: $helo_resp"
# MAIL FROM
echo -e "MAIL FROM:<verify@verify.local>\r" >&3
read -t $timeout -u 3 mail_resp
echo "MAIL FROM: $mail_resp"
# RCPT TO - the actual verification
echo -e "RCPT TO:<EMAIL_ADDRESS>\r" >&3
read -t $timeout -u 3 rcpt_resp
echo "RCPT TO: $rcpt_resp"
# QUIT
echo -e "QUIT\r" >&3
exec 3<&-
exec 3>&-
} 2>&1Interpret the RCPT TO response — match the response text as well as the code:
- 250: Mailbox exists (or domain is catch-all — see below)
- Text mentions "full", "quota", "blocks limit", or "inode limit" (any code, typically 452/552): the mailbox exists but is over quota — mark as Risky (mailbox full)
- Text mentions "relay", "relaying", "not local", or "authentication required" (any code, e.g.
551 User not local: authentication required for relaying): the server rejected the probe, not the mailbox — this says nothing about whether the address exists — mark as Indeterminate (relay denied) - 550/551/553 (no relay/quota wording): Mailbox does not exist — mark as Invalid (mailbox not found)
- 450/451/452 (no quota wording): Temporary rejection (greylisting) — mark as Indeterminate (greylisted)
- Connection refused/timeout: check (once per run) whether outbound port 25 works at all:
timeout 8 bash -c 'exec 3<>/dev/tcp/gmail-smtp-in.l.google.com/25 && read -t 5 -u 3 greeting && echo "$greeting"'. If that fails, mark as Indeterminate (port 25 blocked locally). If it succeeds and the domain was A-record-only (no MX — the A record usually points to a web server, not a mail server), mark as Invalid (no mail server); otherwise mark as Indeterminate (server unreachable) - Any other error: Note the code and mark as Indeterminate
Catch-all detection
After the RCPT TO check, if the result was 250, test whether the domain is catch-all by checking a clearly fake
address: does-not-exist-xyz-99@<domain>. If that also returns 250, the domain accepts all addresses and the result
is Indeterminate (catch-all domain).
Step 5: Provider-specific headless browser verification
For providers that defeat SMTP verification, use Playwright to check account existence via their password recovery flows. Skip the SMTP check (Step 4) for these providers and use this step instead.
Microsoft (outlook.com, hotmail.com, live.com, msn.com)
- Call
browser_navigatetohttps://account.live.com/password/reset - Call
browser_snapshotto find the email input field. - Call
browser_fill_formto enter the email address into the email input. - Call
browser_clickon the "Next" button. - Wait 3 seconds, then call
browser_snapshotand check:- If the page contains text like "that Microsoft account doesn't exist" or "No account found with that email" → Unreachable (account not found)
- If the page shows identity verification options ("verify your identity", "send a code", "authenticator app") → Reachable (account exists)
- If a CAPTCHA appears, note it and mark as Indeterminate (CAPTCHA blocked)
Yahoo (yahoo.com, ymail.com, aol.com, yahoo.co.uk, yahoo.ca, etc.)
- Call
browser_navigatetohttps://login.yahoo.com/forgot - Call
browser_snapshotto find the email/phone input field. - Call
browser_fill_formto enter the email address. - Call
browser_clickon "Continue". - Wait 3 seconds, then call
browser_snapshotand check:- If the page shows an error message like "Sorry, we don't recognize that email" → Unreachable (account not found)
- If the page shows verification options (send a code, security key, etc.) → Reachable (account exists)
- If a CAPTCHA appears, note it and mark as Indeterminate (CAPTCHA blocked)
Microsoft 365 (business domains with MX pointing to outlook.com or *.mail.protection.outlook.com)
Before using the headless browser, try the faster API check:
Run via Bash:
curl -s -X POST 'https://login.microsoftonline.com/common/GetCredentialType' \
-H 'Content-Type: application/json' \
-d '{"Username": "EMAIL_ADDRESS"}' | python3 -c "import sys,json; r=json.load(sys.stdin); print('EXISTS' if r.get('IfExistsResult')==0 else 'NOT_FOUND' if r.get('IfExistsResult')==1 else f'UNKNOWN({r.get(\"IfExistsResult\")})')"EXISTS→ Reachable (Microsoft 365 account exists)NOT_FOUND→ Unreachable (account not found)UNKNOWN→ Fall back to the Microsoft headless browser check above
iCloud (icloud.com, me.com, mac.com)
Apple does not expose account enumeration in password recovery flows. For iCloud addresses, SMTP verification is unreliable (catch-all behavior) and no headless workaround exists. Mark as Indeterminate (Apple — cannot verify).
All other providers
Use the SMTP RCPT TO check from Step 4.
Output
Present a summary table:
| Syntax | MX Record | Disposable | Verification Method | Result | Verdict |
Verification Method should indicate what was used: SMTP, Headless (Microsoft), Headless (Yahoo), API (M365), or N/A.
Verdicts:
- Reachable: Account confirmed to exist via SMTP 250 (non-catch-all) or headless browser / API check
- Unreachable: Failed syntax, MX, SMTP returned 550, or headless browser confirmed account does not exist
- Risky: Disposable email provider (may still be reachable)
- Indeterminate: Could not confirm (catch-all, greylisted, CAPTCHA blocked, or Apple iCloud)
After the table, briefly explain any indeterminate results and suggest next steps (e.g., "send a confirmation email to verify" for indeterminate addresses).
Limitations — tell the user about these
Before presenting results, inform the user of the following:
- This is not 100% reliable. Even commercial email verification services (ZeroBounce, NeverBounce, etc.) only achieve ~95-99% accuracy, and they use rotating IP pools, ML models trained on billions of bounce logs, and proprietary ESP data partnerships that we don't have.
- iCloud addresses (icloud.com, me.com, mac.com) cannot be verified. Apple blocks all enumeration techniques. The only way to confirm an iCloud address is to send an actual email.
- Catch-all domains are fundamentally unverifiable. ~20-30% of business domains accept mail for any address. No technique — free or paid — can definitively verify a specific mailbox on a catch-all domain without sending.
- SMTP checks may fail from this machine. Port 25 is blocked by many ISPs and cloud providers. If the SMTP step times out or is refused, it may be a network issue rather than an invalid address.
- Headless browser checks depend on provider UI. Microsoft and Yahoo can change their password recovery pages at any time, which would break the headless verification. If the page structure looks unexpected, note this.
- CAPTCHAs may block headless checks. Repeated use from the same IP will trigger CAPTCHAs on Microsoft and Yahoo, degrading results to Indeterminate.
- A "Reachable" result means the account exists, not that someone reads it. The mailbox could be abandoned, full, or filtered. The only true confirmation is a reply from the recipient.
Email addresses to verify: $ARGUMENTS
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

