Block disposable email signups in Flask
Add a decorator that runs before your signup view. Works with Flask-Login, Flask-Security, or vanilla Flask.
The code
# app/auth.py
import os, functools, requests
from flask import request, jsonify, abort
CDE_KEY = os.environ["CDE_KEY"]
def is_disposable(email: str) -> bool:
try:
r = requests.get(
"https://api.checkdisposable.email/v1/check",
params={"email": email},
headers={"Authorization": f"Bearer {CDE_KEY}"},
timeout=3,
)
return r.ok and r.json().get("is_disposable") is True
except requests.RequestException:
return False # fail open
def block_disposable(view):
@functools.wraps(view)
def wrapped(*args, **kwargs):
email = (request.get_json(silent=True) or {}).get("email") or request.form.get("email")
if email and is_disposable(email):
return jsonify(error="Please use a real email address."), 400
return view(*args, **kwargs)
return wrapped
# routes.py
from flask import Blueprint
auth_bp = Blueprint("auth", __name__)
@auth_bp.post("/signup")
@block_disposable
def signup():
# ...create user
return jsonify(ok=True)Notes
- Decorator order
- Apply `@block_disposable` ABOVE any login decorators so anonymous signups still get the check.
- JSON or form
- The decorator reads from both `request.json` and `request.form`, so it works for SPA POSTs and traditional HTML form submissions.
- Async option
- On Flask 2+ with the `async` extra, swap `requests` for `httpx.AsyncClient` to avoid blocking the event loop on `gunicorn --worker-class uvicorn.workers.UvicornWorker`.
Get a free API key
500 checks/month, no credit card. No credit card. 30 seconds.
Sign up free →