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.1.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.1-py3-none-any.whl (6.3 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: burner_bouncer-1.1.1.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.1.tar.gz
Algorithm Hash digest
SHA256 d2eaa9a63d602f76c9c36a49754c5ea5f747c8b7a69cc023a4c7f72cca9b95ee
MD5 e6d35963af0977da9f4d9a1ae8d1e0ee
BLAKE2b-256 4a8855f790232ddfbb09b6f9101713887bb20f4c7424e593fd41e27dc578c6cb

See more details on using hashes here.

Provenance

The following attestation bundles were made for burner_bouncer-1.1.1.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.1-py3-none-any.whl.

File metadata

  • Download URL: burner_bouncer-1.1.1-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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 eb2f568d14c783975646f09184861db11e869c9b3df277e2200d3f6aac9fd622
MD5 4b0afa80aa9ef18e269254a3025479be
BLAKE2b-256 569efd8fb8641cf3d1d59a513b3b2616ae6663a5fdb9ff0ca157a9bef5f223c8

See more details on using hashes here.

Provenance

The following attestation bundles were made for burner_bouncer-1.1.1-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