How to detect disposable emails in Python
May 16, 2026 · 6 min read
Disposable email addresses — temporary inboxes from services like mailinator.com — let users sign up without giving you a real address. In Python, you can reject them with a single function call. This guide covers Django, Flask, and FastAPI.
Install the package
The isdisposable package bundles 160,000+ disposable domains and runs offline — no API key, no network call, zero dependencies.
pip install isdisposablefrom isdisposable import is_disposable
is_disposable("test@mailinator.com") # True
is_disposable("user@gmail.com") # FalseDjango — a custom form validator
Wrap the check in a validator so it applies to any form or model field that holds an email.
from django.core.exceptions import ValidationError
from isdisposable import is_disposable
def validate_not_disposable(value):
if is_disposable(value):
raise ValidationError(
"Disposable email addresses are not allowed.",
code="disposable",
)
# In a form:
class SignupForm(forms.Form):
email = forms.EmailField(validators=[validate_not_disposable])Flask
from flask import Flask, request, jsonify
from isdisposable import is_disposable
app = Flask(__name__)
@app.post("/signup")
def signup():
email = request.json["email"]
if is_disposable(email):
return jsonify(error="Disposable email addresses are not allowed."), 422
# ...create the user
return jsonify(ok=True)FastAPI — a Pydantic validator
FastAPI validates request bodies with Pydantic. Add a field validator and the rejection happens before your route code even runs.
from fastapi import FastAPI
from pydantic import BaseModel, field_validator
from isdisposable import is_disposable
app = FastAPI()
class SignupRequest(BaseModel):
email: str
@field_validator("email")
@classmethod
def reject_disposable(cls, v: str) -> str:
if is_disposable(v):
raise ValueError("Disposable email addresses are not allowed.")
return v
@app.post("/signup")
def signup(body: SignupRequest):
# body.email is guaranteed non-disposable here
return {"ok": True}Cleaning an existing user table
Use is_disposable_bulk to audit a whole list at once and find accounts that slipped through before you added the check.
from isdisposable import is_disposable_bulk
emails = [u.email for u in users]
flags = is_disposable_bulk(emails)
suspicious = [u for u, bad in zip(users, flags) if bad]
print(f"{len(suspicious)} disposable accounts found")Catching brand-new domains
The offline list covers every known disposable domain. To also catch domains registered after your last update — plus MX-record checks and a risk score — use the API client:
from isdisposable import create_client
client = create_client(api_key="isd_live_xxxxx")
result = client.check("test@mailinator.com")
print(result.disposable, result.score)See the API reference for the full response shape. Start with the free offline package and add the API only where you need live checks.