Validating email addresses before sending is essential for maintaining your sender reputation and reducing bounce rates. In this tutorial, you'll learn how to integrate the MailRook email validation API into your Python application.
You only need the requests library:
pip install requests
The simplest use case — validate one email address:
import requests
API_KEY = "your_api_key_here"
BASE_URL = "https://api.mailrook.com/v1"
def validate_email(email: str) -> dict:
"""Validate a single email address."""
response = requests.get(
f"{BASE_URL}/validate/{email}",
headers={"Authorization": f"Bearer {API_KEY}"}
)
response.raise_for_status()
return response.json()
# Usage
result = validate_email("[email protected]")
print(f"Email: {result['email']}")
print(f"Valid: {result['is_valid']}")
print(f"Reason: {result['reason']}")
The API returns a detailed validation result:
{
"email": "[email protected]",
"is_valid": false,
"reason": "mailbox_not_found",
"checks": {
"syntax": true,
"domain": true,
"mx_records": true,
"smtp": false,
"disposable": false,
"catch_all": false,
"role_based": false
},
"response_time_ms": 342
}
Key fields:
is_valid — Whether the email can receive mailreason — Why it failed (if invalid)checks — Individual check resultsFor validating entire lists, use the batch endpoint:
import requests
import time
def validate_batch(emails: list[str]) -> dict:
"""Submit a batch of emails for validation."""
# Submit the batch
response = requests.post(
f"{BASE_URL}/validate/batch",
headers={"Authorization": f"Bearer {API_KEY}"},
json={"emails": emails}
)
response.raise_for_status()
batch = response.json()
list_uuid = batch["list_uuid"]
# Poll for results
while True:
status = requests.get(
f"{BASE_URL}/validate/list/{list_uuid}",
headers={"Authorization": f"Bearer {API_KEY}"}
).json()
if status["status"] == "completed":
return status
print(f"Progress: {status.get('progress', 0)}%")
time.sleep(2)
# Usage
emails = [
"[email protected]",
"[email protected]",
"[email protected]",
]
results = validate_batch(emails)
for result in results["results"]:
status = "valid" if result["is_valid"] else "invalid"
print(f"{result['email']}: {status}")
Add real-time validation to your Django registration form:
# validators.py
import requests
from django.core.exceptions import ValidationError
def validate_email_mailrook(email: str):
"""Django validator that checks email via MailRook."""
try:
response = requests.get(
f"https://api.mailrook.com/v1/validate/{email}",
headers={"Authorization": f"Bearer {API_KEY}"},
timeout=5
)
result = response.json()
if not result.get("is_valid"):
reason = result.get("reason", "unknown")
raise ValidationError(
f"This email address appears to be invalid: {reason}"
)
except requests.RequestException:
# Don't block signups if the API is unreachable
pass
# models.py
from django.db import models
from .validators import validate_email_mailrook
class User(models.Model):
email = models.EmailField(
validators=[validate_email_mailrook]
)
Process an entire CSV of emails:
import csv
import requests
def validate_csv(input_path: str, output_path: str):
"""Read emails from CSV, validate, and write results."""
with open(input_path) as infile:
emails = [row[0].strip() for row in csv.reader(infile) if row]
# Submit batch
response = requests.post(
f"{BASE_URL}/validate/batch",
headers={"Authorization": f"Bearer {API_KEY}"},
json={"emails": emails}
)
batch = response.json()
# Wait for completion (simplified)
import time
while True:
status = requests.get(
f"{BASE_URL}/validate/list/{batch['list_uuid']}",
headers={"Authorization": f"Bearer {API_KEY}"}
).json()
if status["status"] == "completed":
break
time.sleep(2)
# Write results
with open(output_path, "w", newline="") as outfile:
writer = csv.writer(outfile)
writer.writerow(["email", "valid", "reason"])
for result in status["results"]:
writer.writerow([
result["email"],
result["is_valid"],
result.get("reason", "")
])
valid = sum(1 for r in status["results"] if r["is_valid"])
total = len(status["results"])
print(f"Validated {total} emails: {valid} valid, {total - valid} invalid")
# Usage
validate_csv("contacts.csv", "validated_contacts.csv")
Always handle API errors gracefully:
import requests
from requests.exceptions import RequestException
def safe_validate(email: str) -> dict | None:
"""Validate with proper error handling."""
try:
response = requests.get(
f"{BASE_URL}/validate/{email}",
headers={"Authorization": f"Bearer {API_KEY}"},
timeout=10
)
if response.status_code == 429:
print("Rate limited — wait before retrying")
return None
if response.status_code == 401:
print("Invalid API key")
return None
response.raise_for_status()
return response.json()
except RequestException as e:
print(f"API request failed: {e}")
return None
Start with 100 free email checks per day. No credit card required.
Get Started Free