FastAPI · Python

Block disposable email in FastAPI

Piisend's own stack. Add a reusable dependency or service call before your signup endpoint creates a user.

The code

# services/disposable.py
import os
import httpx

PIISEND_URL = "https://api.piisend.com/api/v1/intelligence/email"

async def is_disposable_email(email: str) -> bool:
    try:
        async with httpx.AsyncClient(timeout=5.0) as client:
            r = await client.post(
                PIISEND_URL,
                headers={
                    "Authorization": f"Bearer {os.environ['PIISEND_API_KEY']}",
                    "Content-Type": "application/json",
                },
                json={"email": email},
            )
        if not r.is_success:
            return False
        return r.json().get("signals", {}).get("disposable") is True
    except httpx.HTTPError:
        return False

# routes/auth.py
from fastapi import APIRouter, HTTPException
from .services.disposable import is_disposable_email

router = APIRouter()

@router.post("/signup")
async def signup(email: str, password: str):
    if await is_disposable_email(email):
        raise HTTPException(400, "Please use a permanent email address.")
    # ...create user

API key

Load `PIISEND_API_KEY` from settings, not hard-coded strings.

Fail-open vs fail-closed

httpx errors return False — log if you need observability.

Pair with verification

Piisend itself uses a vendored blocklist locally; this pattern is for your separate app calling Piisend intelligence.

Send verification email with Piisend

After blocking disposable addresses, send OTP and verification mail through the same Piisend account. One API key for intelligence checks and transactional sends.