Skip to main content

Zero-dependency disposable/burner email detector

Project description

burner-bouncer

CI npm version JSR PyPI version License: MIT

Detect disposable / burner email addresses instantly. Zero runtime dependencies. Ships as both an npm package (TypeScript, ESM + CJS), a JSR package (Deno/Bun), and a Python package, backed by a single shared blocklist of 500+ real disposable-email domains.


Why Burner Bouncer?

  • No external requests — the blocklist is bundled at install time; nothing is phoned home at runtime.
  • Dual ecosystem — identical API surface in JavaScript/TypeScript and Python so you can use the same library across your stack.
  • Always typed — full TypeScript types and a typed Python dataclass result, no any guessing.
  • Tiny — the entire JS bundle is under 10 kB gzipped.
  • 500+ domains — covers Mailinator, Guerrilla Mail, YOPmail, 10MinuteMail, Temp-Mail, Maildrop, and hundreds more.
  • CLI included — run npx burner-bouncer check <email> with no install.
  • Weekly auto-sync — a GitHub Actions workflow opens PRs to keep the blocklist fresh from upstream sources.

JavaScript / TypeScript

Installation

npm install burner-bouncer
# or
pnpm add burner-bouncer
# or
yarn add burner-bouncer

Deno / JSR

deno add @grocerysushi/burner-bouncer

CLI (no install required)

npx burner-bouncer check user@mailinator.com
npx burner-bouncer check a@mailinator.com b@gmail.com
npx burner-bouncer check user@company.com --dns   # also verify MX record
npx burner-bouncer blocklist                       # print all blocked domains

Usage

import {
  isDisposable, check, checkMany, getDomain, getBlocklist,
  isFreeProvider, isRoleAddress, suggest, getFreeProviders, checkWithDns,
} from 'burner-bouncer';

// Quick boolean check
isDisposable('user@mailinator.com');   // true
isDisposable('user@gmail.com');        // false
isDisposable('notanemail');            // false

// Free provider detection (Gmail, Yahoo, Hotmail, etc.)
isFreeProvider('user@gmail.com');      // true
isFreeProvider('user@company.com');    // false

// Role address detection (admin, noreply, support, etc.)
isRoleAddress('admin@example.com');    // true
isRoleAddress('john@example.com');     // false

// Typo suggestion
suggest('user@gmial.com');             // 'user@gmail.com'
suggest('user@gmail.com');             // null (already correct)

// Full result object
check('test@mailinator.com');
// {
//   email: 'test@mailinator.com',
//   domain: 'mailinator.com',
//   isDisposable: true,
//   isFreeProvider: false,
//   isRoleAddress: false,
//   reason: 'blocklist'
// }

check('admin@gmail.com');
// { ..., isDisposable: false, isFreeProvider: true, isRoleAddress: true, reason: null }

check('notanemail');
// { email: 'notanemail', domain: null, isDisposable: false, ..., reason: 'invalid_email' }

// Batch check
checkMany(['a@mailinator.com', 'b@gmail.com', 'bad']);

// MX record validation (async, requires network)
const result = await checkWithDns('user@gmail.com');
result.hasMx; // true

// Retrieve lists
getBlocklist();      // ['10minutemail.com', ...]
getFreeProviders();  // ['aol.com', 'gmail.com', ...]

JS API Reference

Function Signature Description
isDisposable (email: string) => boolean Returns true if the email's domain is on the blocklist.
isFreeProvider (email: string) => boolean Returns true if the domain is a known free email provider (Gmail, Yahoo, etc.).
isRoleAddress (email: string) => boolean Returns true if the local part is a role prefix (admin, noreply, support, etc.).
suggest (email: string) => string | null Returns a corrected email if the domain looks like a typo, otherwise null.
check (email: string) => CheckResult Returns a full result object.
checkMany (emails: string[]) => CheckResult[] Runs check on each email.
checkWithDns (email: string) => Promise<DnsCheckResult> Like check but also verifies MX records via DNS.
getDomain (email: string) => string | null Extracts and lowercases the domain. Returns null for invalid emails.
getBlocklist () => string[] Returns a sorted copy of all blocked domains.
getFreeProviders () => string[] Returns a sorted copy of all known free provider domains.

CheckResult interface

interface CheckResult {
  email: string;
  domain: string | null;
  isDisposable: boolean;
  isFreeProvider: boolean;
  isRoleAddress: boolean;
  reason: 'blocklist' | 'invalid_email' | null;
}

interface DnsCheckResult extends CheckResult {
  hasMx: boolean | null;  // null when email is invalid
}

Python

Installation

pip install burner-bouncer

Usage

from burner_bouncer import (
    is_disposable, check, check_many, get_domain, get_blocklist,
    is_free_provider, is_role_address, suggest, get_free_providers,
    check_with_dns,
)

# Quick boolean checks
is_disposable("user@mailinator.com")   # True
is_free_provider("user@gmail.com")     # True
is_role_address("admin@example.com")   # True
suggest("user@gmial.com")              # 'user@gmail.com'

# Full result dataclass
result = check("test@mailinator.com")
result.is_disposable    # True
result.is_free_provider # False
result.is_role_address  # False
result.reason           # 'blocklist'
result.to_dict()

# MX validation
result = check_with_dns("user@gmail.com")
result.has_mx  # True

# Batch check
results = check_many(["a@mailinator.com", "b@gmail.com", "bad"])

# Retrieve lists
get_blocklist()       # ['10minutemail.com', ...]
get_free_providers()  # ['aol.com', 'gmail.com', ...]

Python API Reference

Function Signature Description
is_disposable (email: str) -> bool Returns True if the email's domain is on the blocklist.
is_free_provider (email: str) -> bool Returns True if the domain is a known free email provider.
is_role_address (email: str) -> bool Returns True if the local part is a role prefix.
suggest (email: str) -> Optional[str] Returns a corrected email for likely typos, otherwise None.
check (email: str) -> CheckResult Returns a CheckResult dataclass instance.
check_many (emails: List[str]) -> List[CheckResult] Runs check on each email.
check_with_dns (email: str) -> DnsCheckResult Like check but also verifies MX records.
get_domain (email: str) -> Optional[str] Extracts and lowercases the domain.
get_blocklist () -> List[str] Returns a sorted list of all blocked domains.
get_free_providers () -> List[str] Returns a sorted list of all free provider domains.

CheckResult dataclass

@dataclass
class CheckResult:
    email: str
    domain: Optional[str]
    is_disposable: bool
    is_free_provider: bool
    is_role_address: bool
    reason: Optional[str]  # 'blocklist' | 'invalid_email' | None

    def to_dict(self) -> dict: ...

@dataclass
class DnsCheckResult:
    # all CheckResult fields +
    has_mx: Optional[bool]  # None when email is invalid

Repository Structure

burner-bouncer/
├── data/
│   └── disposable_domains.json   # Shared blocklist (500+ domains)
├── js/
│   ├── src/
│   │   ├── index.ts              # JS/TS library source
│   │   └── cli.ts                # CLI entrypoint (npx burner-bouncer)
│   ├── tests/
│   │   └── index.test.ts         # Jest test suite
│   ├── jest.config.js
│   ├── package.json
│   └── tsconfig.json
├── python/
│   ├── burner_bouncer/
│   │   └── __init__.py           # Python library source
│   ├── tests/
│   │   └── test_burner_bouncer.py
│   └── pyproject.toml
├── scripts/
│   └── sync-blocklist.js         # Auto-sync blocklist from upstream sources
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   └── submit-domain.yml     # "Submit a domain" form
│   └── workflows/
│       ├── ci.yml                # CI: test JS + Python on every push/PR
│       ├── publish.yml           # Publish to npm + JSR + PyPI on version tag
│       └── sync-blocklist.yml    # Weekly blocklist sync
├── jsr.json                      # JSR (Deno registry) config
├── CONTRIBUTING.md
├── .gitignore
├── LICENSE
└── README.md

Contributing

See CONTRIBUTING.md for full details. The short version:

  1. Add domains to data/disposable_domains.json (sorted, deduplicated, lowercase)
  2. Run cd js && npm test and cd python && pytest
  3. Open a pull request — use the Submit a domain issue template for new domains

License

MIT © 2025 burner-bouncer contributors

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

burner_bouncer-1.1.0.tar.gz (6.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

burner_bouncer-1.1.0-py3-none-any.whl (6.3 kB view details)

Uploaded Python 3

File details

Details for the file burner_bouncer-1.1.0.tar.gz.

File metadata

  • Download URL: burner_bouncer-1.1.0.tar.gz
  • Upload date:
  • Size: 6.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for burner_bouncer-1.1.0.tar.gz
Algorithm Hash digest
SHA256 8c50c1a8e4605ad46f97273b05fa616fc8c2962ae6ad864311f974d5aa4ae477
MD5 b0fdc25eb52457e642c8c35c31e8a71d
BLAKE2b-256 18ce69eeb6cfcea93f29b7f6436c6feaab383fd39ee2634811e2308b148873ef

See more details on using hashes here.

Provenance

The following attestation bundles were made for burner_bouncer-1.1.0.tar.gz:

Publisher: publish.yml on grocerysushi/burner-bouncer

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file burner_bouncer-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: burner_bouncer-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 6.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for burner_bouncer-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 782e3504b72346347e71c20225e3aa340a06daf91e9c2275572fb4d4c142d39f
MD5 48b7ac166cf50a39efc5438d6d5d97ee
BLAKE2b-256 40c0c393b60ae45e64223de3433b803d53dcf882917900401ba5eeaf241823f7

See more details on using hashes here.

Provenance

The following attestation bundles were made for burner_bouncer-1.1.0-py3-none-any.whl:

Publisher: publish.yml on grocerysushi/burner-bouncer

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page