Python powers modern backend APIs, ETL data pipelines, CRM sync workers, and AI agent workflows. Integrating real-time email verification into your Python stack prevents disposable burner signups, protects transactional sender reputation on AWS SES, Postmark, and Resend, and cuts verification costs by up to 90% compared to legacy providers (starting at $0.0002/check or $59 per 100,000 credits).
Prerequisites & Environment Setup
Before integrating verification workflows, ensure your Python environment includes the following dependencies:
- Python 3.10+ for modern union type annotations (
str | None) andasynciotask groups httpxfor async/sync HTTP clients andpydanticfor strict response validation- A MailVeri API key from your dashboard (includes 1,000 free trial credits that never expire)
pip install httpx fastapi pydantic uvicorn1. Synchronous Verification with Python requests
For CLI scripts, cron jobs, or Celery tasks, you can call POST https://api.mailveri.com/v1/verify-mail/ with either JSON or form-encoded payloads:
import os
import requests
MAILVERI_API_KEY = os.environ["MAILVERI_API_KEY"]
def verify_single_email(email: str) -> dict:
response = requests.post(
"https://api.mailveri.com/v1/verify-mail/",
headers={
"X-Api-Key": MAILVERI_API_KEY,
"Content-Type": "application/json",
},
json={"email": email.strip().lower()},
timeout=5.0,
)
response.raise_for_status()
return response.json()The API returns a structured JSON response indicating the exact mailbox verdict and whether a credit was billed:
{
"email": "[email protected]",
"status": "VALID",
"is_disposable": false,
"is_role_account": false,
"is_catch_all": false,
"mx_found": true,
"credits_used": 1
}2. Status Decision Matrix for Python Backends
Map each MailVeri status code to deterministic application logic across user registration and CRM ingestion pipelines:
| Status Verdict | Credit Billed? | Signup Form Action | Cold Outbound / CRM Action |
|---|---|---|---|
| VALID | Yes (1 credit) | Allow registration & grant trial credits | Push to primary campaign sequence |
| ROLE_ACCOUNT | Yes (1 credit) | Allow with warning (shared inbox like info@) | Route to manual SDR review |
| CATCH_ALL | Yes (1 credit) | Allow registration + require email link confirmation | Route to throttled secondary canary domain |
| DISPOSABLE | Yes (1 credit) | Block immediately (HTTP 422) | Delete / suppress permanently |
| INVALID / FULL_INBOX | Yes (1 credit) | Block & prompt user to fix typo | Suppress permanently to keep bounces <2% |
| UNKNOWN | See Billing FAQ | Fail-open & require email verification link | Hold & retry in 24 hours |
3. FastAPI Dependency & Pydantic Schema Guard
In FastAPI applications, encapsulate MailVeri inside a reusable dependency with strict Pydantic validation and fail-open timeout handling so your signup endpoint stays resilient even during upstream network blips:
import os
import httpx
from fastapi import FastAPI, HTTPException, status
from pydantic import BaseModel, EmailStr
app = FastAPI()
MAILVERI_API_KEY = os.environ["MAILVERI_API_KEY"]
class SignupRequest(BaseModel):
email: EmailStr
company_name: str
class MailVeriResult(BaseModel):
email: str
status: str
is_disposable: bool = False
is_role_account: bool = False
is_catch_all: bool = False
@app.post("/api/v1/signup")
async def register_user(payload: SignupRequest):
async with httpx.AsyncClient(timeout=3.5) as client:
try:
resp = await client.post(
"https://api.mailveri.com/v1/verify-mail/",
headers={"X-Api-Key": MAILVERI_API_KEY},
json={"email": payload.email},
)
resp.raise_for_status()
verdict = MailVeriResult.model_validate(resp.json())
except httpx.HTTPError:
# Fail-open on network timeout; require email confirmation link
return {"created": True, "require_email_confirm": True}
if verdict.status in {"INVALID", "DISPOSABLE", "FULL_INBOX"} or verdict.is_disposable:
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail="Please register with a valid, non-disposable work email address.",
)
return {"created": True, "verification_status": verdict.status}4. High-Throughput Async Concurrency with httpx & Semaphores
When enriching hundreds of leads in memory (or before pushing to HubSpot), use asyncio.Semaphore with a shared httpx.AsyncClient and exponential backoff retry logic:
import asyncio
import httpx
async def verify_batch_concurrently(
emails: list[str],
api_key: str,
concurrency: int = 15,
) -> list[dict]:
semaphore = asyncio.Semaphore(concurrency)
headers = {"X-Api-Key": api_key}
async with httpx.AsyncClient(timeout=10.0, headers=headers) as client:
async def check_one(email: str) -> dict:
async with semaphore:
for attempt in range(3):
resp = await client.post(
"https://api.mailveri.com/v1/verify-mail/",
json={"email": email},
)
if resp.status_code == 429:
await asyncio.sleep(2 ** attempt)
continue
resp.raise_for_status()
return resp.json()
return {"email": email, "status": "UNKNOWN"}
return await asyncio.gather(*(check_one(e) for e in emails))5. AI Agent Integration with Model Context Protocol (MCP)
Building autonomous Python agents with LangChain, CrewAI, or Claude Code? MailVeri ships an official MCP server so your agents can verify emails and scrub CSV files directly via tool calls. Read our guide on Unifying Verification Modes for the AI Era, explore the MailVeri MCP Documentation, and test live addresses in the MailVeri Email Checker.
