Python Email Validation
Complete guide to email validation in Python
What You'll Learn
- Install and configure VerifyForge in Python
- Validate emails in Python scripts
- Build validation functions
- Handle errors gracefully
- Process bulk validations
- Best practices for production
Prerequisites
- Python 3.8+ installed
- Basic knowledge of Python
- VerifyForge API key (get free key)
Installation
pip install verifyforge
Quick Start
from verifyforge import VerifyForge
client = VerifyForge(api_key="your_api_key")
result = client.validate("user@example.com")
if result.data.is_valid:
print(f"✓ Email is valid!")
print(f"Reachability: {result.data.reachability}")
Tutorial 1: Basic Validation Script
# validate_email.py
import sys
from verifyforge import VerifyForge, VerifyForgeError
def validate_email(email: str) -> dict:
"""Validate a single email address"""
client = VerifyForge(api_key="your_api_key")
try:
result = client.validate(email)
return {
"email": result.data.email,
"is_valid": result.data.is_valid,
"reachability": result.data.reachability,
"disposable": result.data.disposable,
"role_account": result.data.role_account,
"free_provider": result.data.free_provider,
"suggestion": result.data.suggestion,
}
except VerifyForgeError as e:
print(f"Validation error: {e}")
return None
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: python validate_email.py <email>")
sys.exit(1)
email = sys.argv[1]
result = validate_email(email)
if result:
print(f"\nValidation Results:")
print(f"Email: {result['email']}")
print(f"Valid: {'✓' if result['is_valid'] else '✗'}")
print(f"Reachability: {result['reachability']}")
print(f"Disposable: {result['disposable']}")
if result['suggestion']:
print(f"Suggestion: {result['suggestion']}")
Run:
python validate_email.py user@example.com
Tutorial 2: Validation with Caching
# email_validator.py
import os
from functools import lru_cache
from verifyforge import VerifyForge
client = VerifyForge(api_key=os.environ.get("VERIFYFORGE_API_KEY"))
@lru_cache(maxsize=1000)
def validate_email_cached(email: str) -> dict:
"""Validate email with caching"""
result = client.validate(email)
return {
"is_valid": result.data.is_valid,
"reachability": result.data.reachability,
"disposable": result.data.disposable,
}
def is_valid_email(email: str) -> bool:
"""Simple boolean check"""
try:
result = validate_email_cached(email)
return result["is_valid"]
except Exception:
return False
Tutorial 3: Bulk Validation for CSV
# bulk_validate_csv.py
import csv
from verifyforge import VerifyForge
def validate_csv(input_file: str, output_file: str, batch_size: int = 100):
"""Validate emails from CSV file"""
client = VerifyForge(api_key="your_api_key")
# Read emails from CSV
emails = []
with open(input_file, 'r') as f:
reader = csv.DictReader(f)
for row in reader:
emails.append(row['email'])
print(f"Found {len(emails)} emails to validate")
# Validate in batches
all_results = []
for i in range(0, len(emails), batch_size):
batch = emails[i:i + batch_size]
print(f"Validating batch {i//batch_size + 1}...")
try:
result = client.validate_bulk(batch)
for validation in result.results:
all_results.append({
'email': validation.email,
'is_valid': validation.is_valid,
'reachable': validation.reachable,
})
except Exception as e:
print(f"Batch failed: {e}")
# Write results to CSV
with open(output_file, 'w', newline='') as f:
fieldnames = ['email', 'is_valid', 'reachable']
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(all_results)
print(f"Results written to {output_file}")
if __name__ == "__main__":
validate_csv('emails.csv', 'validated_emails.csv')
Tutorial 4: API with FastAPI
# main.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, EmailStr
from verifyforge import (
VerifyForge,
AuthenticationError,
InsufficientCreditsError,
ValidationError
)
import os
app = FastAPI()
client = VerifyForge(api_key=os.environ.get("VERIFYFORGE_API_KEY"))
class EmailRequest(BaseModel):
email: EmailStr
class BulkEmailRequest(BaseModel):
emails: list[EmailStr]
@app.post("/api/validate")
async def validate_email(request: EmailRequest):
try:
result = client.validate(request.email)
return {
"success": True,
"data": {
"email": result.data.email,
"is_valid": result.data.is_valid,
"reachability": result.data.reachability,
"disposable": result.data.disposable,
"role_account": result.data.role_account,
"suggestion": result.data.suggestion,
}
}
except AuthenticationError:
raise HTTPException(status_code=401, detail="Invalid API key")
except InsufficientCreditsError:
raise HTTPException(status_code=402, detail="Insufficient credits")
except ValidationError as e:
raise HTTPException(status_code=400, detail=str(e))
except Exception as e:
raise HTTPException(status_code=500, detail="Validation failed")
@app.post("/api/validate-bulk")
async def validate_bulk(request: BulkEmailRequest):
if len(request.emails) > 100:
raise HTTPException(
status_code=400,
detail="Maximum 100 emails per request"
)
try:
result = client.validate_bulk(request.emails)
return {
"success": True,
"data": {
"results": [
{
"email": r.email,
"is_valid": r.is_valid,
"reachable": r.reachable
}
for r in result.results
],
"summary": {
"total": result.summary.total,
"valid": result.summary.valid,
"invalid": result.summary.invalid,
}
}
}
except Exception as e:
raise HTTPException(status_code=500, detail="Bulk validation failed")
Run:
uvicorn main:app --reload
Tutorial 5: Pandas DataFrame Validation
# validate_dataframe.py
import pandas as pd
from verifyforge import VerifyForge
def validate_dataframe(df: pd.DataFrame, email_column: str = 'email') -> pd.DataFrame:
"""Add validation columns to DataFrame"""
client = VerifyForge(api_key="your_api_key")
emails = df[email_column].tolist()
# Validate in batches
batch_size = 100
validations = []
for i in range(0, len(emails), batch_size):
batch = emails[i:i + batch_size]
result = client.validate_bulk(batch)
validations.extend(result.results)
# Add validation columns
df['is_valid'] = [v.is_valid for v in validations]
df['reachability'] = [v.reachable for v in validations]
return df
# Usage
if __name__ == "__main__":
# Read CSV
df = pd.read_csv('subscribers.csv')
# Validate
df = validate_dataframe(df)
# Filter valid emails
valid_df = df[df['is_valid'] == True]
# Save
valid_df.to_csv('valid_subscribers.csv', index=False)
print(f"Valid emails: {len(valid_df)}/{len(df)}")
Best Practices
1. Environment Variables
import os
from dotenv import load_dotenv
load_dotenv()
client = VerifyForge(api_key=os.environ.get("VERIFYFORGE_API_KEY"))
# .env
VERIFYFORGE_API_KEY=your_api_key_here
2. Context Manager
from verifyforge import VerifyForge
with VerifyForge(api_key="your_api_key") as client:
result = client.validate("test@example.com")
print(result.data.is_valid)
3. Error Handling
from verifyforge import (
VerifyForge,
AuthenticationError,
InsufficientCreditsError,
ValidationError
)
client = VerifyForge(api_key="your_api_key")
try:
result = client.validate("test@example.com")
except AuthenticationError:
print("Invalid API key")
except InsufficientCreditsError:
print("Out of credits")
except ValidationError as e:
print(f"Validation error: {e.message}")
except Exception as e:
print(f"Unexpected error: {e}")
4. Async Validation
import asyncio
from concurrent.futures import ThreadPoolExecutor
from verifyforge import VerifyForge
client = VerifyForge(api_key="your_api_key")
async def validate_async(emails: list[str]) -> list:
"""Validate emails asynchronously"""
loop = asyncio.get_event_loop()
with ThreadPoolExecutor() as executor:
futures = [
loop.run_in_executor(executor, client.validate, email)
for email in emails
]
results = await asyncio.gather(*futures)
return results
# Usage
emails = ["test1@example.com", "test2@example.com"]
results = asyncio.run(validate_async(emails))
5. Retry Logic
import time
from verifyforge import VerifyForge, VerifyForgeError
def validate_with_retry(email: str, max_retries: int = 3) -> dict:
"""Validate with exponential backoff"""
client = VerifyForge(api_key="your_api_key")
for attempt in range(max_retries):
try:
result = client.validate(email)
return result.data
except VerifyForgeError as e:
if attempt == max_retries - 1:
raise
wait_time = 2 ** attempt # Exponential backoff
print(f"Retry {attempt + 1} in {wait_time}s...")
time.sleep(wait_time)
Complete Example: Email List Cleaner
# email_cleaner.py
import csv
import sys
from typing import List, Dict
from verifyforge import VerifyForge
class EmailCleaner:
def __init__(self, api_key: str):
self.client = VerifyForge(api_key=api_key)
def clean_email_list(
self,
emails: List[str],
allow_disposable: bool = False,
allow_risky: bool = False
) -> Dict[str, List[str]]:
"""Clean email list and categorize results"""
valid_emails = []
invalid_emails = []
risky_emails = []
disposable_emails = []
# Validate in batches
batch_size = 100
for i in range(0, len(emails), batch_size):
batch = emails[i:i + batch_size]
try:
result = self.client.validate_bulk(batch)
for validation in result.results:
if not validation.is_valid:
invalid_emails.append(validation.email)
elif validation.is_valid and validation.disposable:
if allow_disposable:
valid_emails.append(validation.email)
else:
disposable_emails.append(validation.email)
elif validation.reachable == 'risky':
if allow_risky:
valid_emails.append(validation.email)
else:
risky_emails.append(validation.email)
else:
valid_emails.append(validation.email)
except Exception as e:
print(f"Batch {i//batch_size + 1} failed: {e}")
return {
"valid": valid_emails,
"invalid": invalid_emails,
"risky": risky_emails,
"disposable": disposable_emails,
}
def clean_csv(self, input_file: str, output_prefix: str = "cleaned"):
"""Clean CSV file and output categorized results"""
# Read emails
with open(input_file, 'r') as f:
reader = csv.DictReader(f)
emails = [row['email'] for row in reader]
print(f"Cleaning {len(emails)} emails...")
# Clean
results = self.clean_email_list(emails)
# Write results
for category, email_list in results.items():
if email_list:
filename = f"{output_prefix}_{category}.csv"
with open(filename, 'w', newline='') as f:
writer = csv.writer(f)
writer.writerow(['email'])
for email in email_list:
writer.writerow([email])
print(f"Wrote {len(email_list)} {category} emails to {filename}")
if __name__ == "__main__":
cleaner = EmailCleaner(api_key="your_api_key")
cleaner.clean_csv("email_list.csv")
Troubleshooting
Problem: Module not found
Solution: Install SDK: pip install verifyforge
Problem: API key error
Solution: Set environment variable: export VERIFYFORGE_API_KEY=your_key
Problem: Timeout errors
Solution: Increase timeout:
client = VerifyForge(api_key="your_key", timeout=60)
