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.

Terminalbash
pip install isdisposable
check.pypython
from isdisposable import is_disposable

is_disposable("test@mailinator.com")  # True
is_disposable("user@gmail.com")       # False

Django — a custom form validator

Wrap the check in a validator so it applies to any form or model field that holds an email.

validators.pypython
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

app.pypython
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.

main.pypython
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.

audit.pypython
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:

api.pypython
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.

Block disposable emails today

isDisposable is free and open source — add it to your signup flow in one line.

Keep reading