Recipes
Working solutions: clean a CRM export, gate a signup form, block disposable addresses, verify a mailing list in CI, keep a suppression list in sync.
View as Markdown →Complete, working solutions to the things people actually build. Every snippet runs as-is once you substitute your key.
Clean a CRM export before a campaign
You have a CSV of leads and want only the addresses that will land.
emailverify login
emailverify bulk --file leads.csv --out verified.json --timeout 300
--file accepts one address per line, a JSON array, or a CSV — for a CSV it picks the column containing an @. Then keep only the sendable ones:
jq -r '.results[] | select(.status == "valid" or .status == "accept_all") | .email' \
verified.json > safe-to-send.txt
Or in Python, using the deliverability score rather than the raw status:
import csv, json
from emailverify import Client
client = Client.from_env()
with open("leads.csv") as fh:
emails = [row["email"] for row in csv.DictReader(fh) if row.get("email")]
safe, risky = [], []
for i in range(0, len(emails), 100): # bulk caps at 100 per call
for r in client.bulk(emails[i:i + 100])["results"]:
score = r.get("deliverability_score") or {}
target = safe if score.get("can_send") else risky
target.append(r["email"])
print(f"{len(safe)} safe, {len(risky)} risky")
open("safe-to-send.txt", "w").write("\n".join(safe))
Gate a signup form
Validate syntax instantly on the client, then verify properly on the server before you create the account.
// server side — never trust the browser for this
const res = await fetch(
`https://emailverifypro.com/validate?email=${encodeURIComponent(email)}`,
{ headers: { "X-API-Key": process.env.EMAILVERIFY_API_KEY } }
);
const data = await res.json();
if (data.is_disposable) {
return reject("Please use a permanent email address.");
}
if (data.did_you_mean) {
return suggest(`Did you mean ${data.did_you_mean}?`);
}
if (!data.deliverability_score?.can_send) {
return reject("We couldn't verify that address.");
}
Keep the full check off the request path where you can — it can take seconds. Either run it asynchronously after signup, or use GET /validate/quick for a fast DNS-only answer and follow up properly in a background job.
Catch typos at the point of entry
curl "https://emailverifypro.com/verify/typo?email=someone@gmial.com"
{"email": "someone@gmial.com", "did_you_mean": "someone@gmail.com", "confidence": 0.97}
Block disposable addresses
r = client.verify("test@mailinator.com")
if r["is_disposable"]:
raise ValueError("Disposable addresses are not accepted")
Find someone's address
r = client.call("find-email", domain="example.com",
first_name="Jane", last_name="Doe")
print(r["email"], r["confidence"])
It learns the domain's convention from addresses it has already seen, builds the likely candidates, and verifies them.
Keep a suppression list in step with your ESP
Point your ESP's webhook at the matching receiver and bounces feed back automatically:
| ESP | Webhook URL |
|---|---|
| SendGrid | https://emailverifypro.com/webhooks/sendgrid |
| Amazon SES | https://emailverifypro.com/webhooks/ses |
| Postmark | https://emailverifypro.com/webhooks/postmark |
| Mailchimp | https://emailverifypro.com/webhooks/mailchimp |
Or record outcomes yourself:
client.call("bounce", email="hard-bounced@example.com", bounce_type="hard")
client.call("delivered", email="landed@example.com")
Every report improves the model for your future verifications.
Verify in CI before a send
# .github/workflows/verify-list.yml
name: Verify mailing list
on:
pull_request:
paths: ["lists/**.csv"]
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: pipx install emailverify
- name: Verify and fail on undeliverable addresses
env:
EMAILVERIFY_API_KEY: ${{ secrets.EMAILVERIFY_API_KEY }}
run: |
emailverify bulk --file lists/campaign.csv --out out.json --json
bad=$(jq '[.results[] | select(.status == "invalid")] | length' out.json)
echo "$bad undeliverable addresses"
test "$bad" -eq 0
Re-verify a warm list on a schedule
Addresses decay — people leave companies and domains lapse. Re-check anything older than 90 days:
emailverify raw POST /admin/reverify --body '{"older_than_days": 90}'
Deduplicate before you spend credits
Gmail dots, plus-addressing and case differences all hide duplicates:
emailverify dedup --file leads.txt
{"original_count": 5000, "unique_count": 4380, "duplicates_removed": 620}
Ask an AI assistant to do it
With the MCP server connected, these all work as plain requests:
- “Verify every address in this CSV and tell me which will bounce.”
- “Is acme.com a catch-all domain?”
- “Find the email format for stripe.com, then work out Jane Doe's address.”
- “How much of my monthly quota is left?”
- “Add these five addresses to my suppression list.”