Skip to main content

Disposable Email Score

A robust, explainable risk-scoring engine for email signups. Detects disposable emails, typosquatting attacks, and suspicious domains.

Python 3.8+ License: MIT Twitter

Features

  • Disposable Domain Detection — Checks against 113,000+ known disposable email domains
  • Typosquatting Detection — Catches fake domains like gmaiil.com, yahooo.com
  • MX Record Analysis — Flags domains with missing or suspicious mail servers
  • Role Account Detection — Flags shared inboxes like admin@, info@, sales@
  • Subdomain Detection — Blocks mail.tempmail.com if tempmail.com is blocked
  • Plus Alias Detection — Detects user+tag@gmail.com patterns
  • Allowlist Support — Trusted domains bypass all checks
  • Explainable Output — Returns score, decision, signals, and human-readable reasons

🚀 Hosted API (Coming Soon)

Don't want to self-host? We're building a hosted API with:

  • Simple REST API — works with any language
  • No setup required — get an API key and start
  • Always updated blocklist

👉 Join the waitlist to get early access + lifetime discount.

Installation

pip install disposable-email-score

Quick Start

from disposable_email_score import evaluate_email

result = evaluate_email("user@tempmail.xyz")
print(result.model_dump_json(indent=2))

Output

{
  "decision": "block",
  "score": 0.7,
  "thresholds": {
    "allow": 0.3,
    "block": 0.7
  },
  "signals": {
    "domain_in_blocklist": 0.7
  },
  "reasons": [
    "known_disposable_domain"
  ]
}

Using RiskLevel

from disposable_email_score import evaluate_email, RiskLevel

result = evaluate_email("test@example.com")

if result.decision == RiskLevel.BLOCK:
    print("❌ Blocked!")
elif result.decision == RiskLevel.REVIEW:
    print("🟡 Needs review")
else:
    print("✅ Allowed")

How It Works

Architecture

Risk Levels

Score Decision Action
< 0.3 allow Low risk — let them through
0.3 - 0.69 review Medium risk — require CAPTCHA or verification
≥ 0.7 block High risk — reject signup

Signals & Weights

Signal Weight Description
domain_in_blocklist 0.7 Known disposable domain
typosquatting 0.6 Looks like a typo of gmail.com, yahoo.com, etc.
mx_risky_or_missing 0.5 No MX records or suspicious mail infrastructure
plus_alias 0.05 Uses +tag in local part

Framework Integration

FastAPI

from fastapi import FastAPI
from disposable_email_score import evaluate_email, RiskResult

app = FastAPI()

@app.get("/check-email", response_model=RiskResult)
def check_email(email: str):
    return evaluate_email(email)

Django

from django.http import JsonResponse
from disposable_email_score import evaluate_email

def validate_signup(request):
    email = request.GET.get('email')
    result = evaluate_email(email)
    
    if result.decision == "block":
        return JsonResponse({'error': 'Email not allowed'}, status=400)
    
    return JsonResponse(result.model_dump())

Configuration

All weights and thresholds are in config.py:

THRESHOLD_BLOCK = 0.7
THRESHOLD_REVIEW = 0.3

SCORES = {
    "disposable_domain": 0.7,
    "typosquatting": 0.6,
    "no_mx_records": 0.5,
    ...
}

Auto-Updates

Domain lists are automatically updated weekly via GitHub Actions from disposable-email-domains.

Development

# Install with dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Format code
ruff format src/ tests/

# Lint
ruff check src/ tests/

License

MIT

Metadata

Release files for disposable-email-score 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for disposable-email-score 0.1.1
File Size Uploaded
disposable_email_score-0.1.1.tar.gz 653.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for disposable-email-score 0.1.1
File Interpreter ABI Platform
disposable_email_score-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 1.3 MB

Release files / disposable_email_score-0.1.1.tar.gz

Download URL disposable_email_score-0.1.1.tar.gz
Size 653.3 kB
Tags Source
SHA-256 checksum
How to use checksums
9df4c2bc13dd6afd22922c5e71b6e556430634eff0748b3ecc4df13d69c96c10
BLAKE2b-256 checksum
How to use checksums
839584a3d91e9e862a8587b58045963c9cf634ce1db92377648a3b296e927778
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.14

Release files / disposable_email_score-0.1.1-py3-none-any.whl

Download URL disposable_email_score-0.1.1-py3-none-any.whl
Size 654.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d433db838cbe5cd45b999ee7cef45fbadd4f71a0cf0fc5feb7e30ae4d63b9cdc
BLAKE2b-256 checksum
How to use checksums
f0229b9a2b1c4621ff7a33e7ee794b8dc6a28d8c7c95b352b14153a33c6b6807
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.14

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page