{"_id":"@bitclaw/disposable-email","_rev":"4-732abcddb38e7f79ae00c2a4d607da60","name":"@bitclaw/disposable-email","dist-tags":{"latest":"1.2.2"},"versions":{"1.1.0":{"name":"@bitclaw/disposable-email","version":"1.1.0","keywords":["disposable-email","email-validation","spam-prevention","mx-validation","bun"],"author":{"name":"bitclaw"},"license":"MIT","_id":"@bitclaw/disposable-email@1.1.0","maintainers":[{"name":"bitclaw","email":"bitclaw@gmail.com"}],"dist":{"shasum":"97b21c4973dd14b8bf7d93604afe729695733bda","tarball":"https://registry.npmjs.org/@bitclaw/disposable-email/-/disposable-email-1.1.0.tgz","fileCount":18,"integrity":"sha512-SVnZEj9tdDA2ollNqs6DIB5Ek+oBs5anZLD09UF0cKLlrO++E3yjj8rMsPdFGRLlphULFsV8IvpJWeGfW+OeiQ==","signatures":[{"sig":"MEYCIQDW0OOk5jxwsE904yGZbptX+D0gTq0ED1VvJmuPFYJQYwIhAIDTyIqhuMPMFkOYZL9mUHyJLqrQJo3S8+V2FkEBuyEI","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":26178},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"702f27d532d91a5751821c513570589929be3ff6","scripts":{"knip":"knip","lint":"biome check","test":"bun test","build":"tsc -p tsconfig.build.json","format":"biome format --write","lint:fix":"biome check --write","typecheck":"tsc --noEmit","test:watch":"bun test --watch","publish:dev":"npm run build && npm publish --tag dev --access public","publish:major":"npm whoami && npm version major && git push --follow-tags && npm publish --access public","publish:minor":"npm whoami && npm version minor && git push --follow-tags && npm publish --access public","publish:patch":"npm whoami && npm version patch && git push --follow-tags && npm publish --access public","prepublishOnly":"npm run build && npm run test"},"_npmUser":{"name":"bitclaw","email":"bitclaw@gmail.com"},"_npmVersion":"11.6.2","description":"Fast disposable and free email provider detection with optional MX record validation","directories":{},"_nodeVersion":"24.11.1","_hasShrinkwrap":false,"devDependencies":{"knip":"^6.12.1","@types/bun":"^1.3.9","typescript":"^5.8.3","@types/node":"^22.0.0","@biomejs/biome":"^2.4.15"},"_npmOperationalInternal":{"tmp":"tmp/disposable-email_1.1.0_1779641594799_0.40198634247680953","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@bitclaw/disposable-email","version":"1.2.0","keywords":["disposable-email","email-validation","spam-prevention","mx-validation","bun"],"author":{"name":"bitclaw"},"license":"MIT","_id":"@bitclaw/disposable-email@1.2.0","maintainers":[{"name":"bitclaw","email":"bitclaw@gmail.com"}],"dist":{"shasum":"d5b561400bb6cfab3032778c37ba507dd5b81671","tarball":"https://registry.npmjs.org/@bitclaw/disposable-email/-/disposable-email-1.2.0.tgz","fileCount":21,"integrity":"sha512-lNyG54kZMeGPhEhEU+akqzzulohVdR2nT/f7jMknaUZAouCFVPmU/BogoysF/2Mx2z5ErfLcJsZI7pocshYpyg==","signatures":[{"sig":"MEQCID75A6XJoeFXhvnrSQzqcb3CNQAiyssInRVmfSozq/0AAiA55+uMwFrTJoy87JjYABJiv15CiaEvHwPWtJef1gbmnA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":188379},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"9f1e5c7da9dfbf95f333729f709e8ff435568fa4","scripts":{"knip":"knip","lint":"biome check","test":"bun test","build":"tsc -p tsconfig.build.json","format":"biome format --write","lint:fix":"biome check --write","typecheck":"tsc --noEmit","test:watch":"bun test --watch","publish:dev":"npm run build && npm publish --tag dev --access public","publish:major":"npm whoami && npm version major && git push --follow-tags && npm publish --access public","publish:minor":"npm whoami && npm version minor && git push --follow-tags && npm publish --access public","publish:patch":"npm whoami && npm version patch && git push --follow-tags && npm publish --access public","prepublishOnly":"npm run build && npm run test"},"_npmUser":{"name":"bitclaw","email":"bitclaw@gmail.com"},"_npmVersion":"11.6.2","description":"Fast disposable and free email provider detection with optional MX record validation","directories":{},"_nodeVersion":"24.11.1","_hasShrinkwrap":false,"devDependencies":{"knip":"6.14.1","@types/bun":"1.3.14","typescript":"5.9.3","@types/node":"22.19.19","@biomejs/biome":"2.4.15"},"_npmOperationalInternal":{"tmp":"tmp/disposable-email_1.2.0_1785280874040_0.6204713777215161","host":"s3://npm-registry-packages-npm-production"}},"1.2.1":{"name":"@bitclaw/disposable-email","version":"1.2.1","keywords":["disposable-email","email-validation","spam-prevention","mx-validation","bun"],"author":{"name":"bitclaw"},"license":"MIT","_id":"@bitclaw/disposable-email@1.2.1","maintainers":[{"name":"bitclaw","email":"bitclaw@gmail.com"}],"dist":{"shasum":"7c5e6584553b7b8d4e8f34b51582e8144bc53c10","tarball":"https://registry.npmjs.org/@bitclaw/disposable-email/-/disposable-email-1.2.1.tgz","fileCount":21,"integrity":"sha512-3TCc99eRdDRH5IzRpeOQ0ip34cZiHrH+olr6Mrv8d/HGzI8dZkMeUD6K0Auu3MhSSMB1kXxKthDIfq13zqlJMA==","signatures":[{"sig":"MEUCIFDdhFk757h41IbMb7gu0VncSfOuM3IDgK3ldiWLnkJfAiEA7HJZ4m281wzTk9gEaiV3pTh1Plr+X4EbjyrttSYnYt4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":191678},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"123d34b2e1bcbdeb6859d5679a0c3f9072eaa45b","scripts":{"knip":"knip","lint":"biome check","test":"bun test","build":"tsc -p tsconfig.build.json","format":"biome format --write","lint:fix":"biome check --write","typecheck":"tsc --noEmit","test:watch":"bun test --watch","publish:dev":"npm run build && npm publish --tag dev --access public","sync-domains":"bun scripts/sync-domains.ts","publish:major":"npm whoami && npm version major && git push --follow-tags && npm publish --access public","publish:minor":"npm whoami && npm version minor && git push --follow-tags && npm publish --access public","publish:patch":"npm whoami && npm version patch && git push --follow-tags && npm publish --access public","prepublishOnly":"npm run build && npm run test"},"_npmUser":{"name":"bitclaw","email":"bitclaw@gmail.com"},"_npmVersion":"11.6.2","description":"Fast disposable and free email provider detection with optional MX record validation","directories":{},"_nodeVersion":"24.11.1","_hasShrinkwrap":false,"devDependencies":{"knip":"6.14.1","@types/bun":"1.3.14","typescript":"5.9.3","@types/node":"22.19.19","@biomejs/biome":"2.4.15"},"_npmOperationalInternal":{"tmp":"tmp/disposable-email_1.2.1_1785282033399_0.5874616861437976","host":"s3://npm-registry-packages-npm-production"}},"1.2.2":{"name":"@bitclaw/disposable-email","version":"1.2.2","description":"Fast disposable and free email provider detection with optional MX record validation","type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"scripts":{"build":"tsc -p tsconfig.build.json","test":"bun test","test:watch":"bun test --watch","typecheck":"tsc --noEmit","lint":"biome check","lint:fix":"biome check --write","format":"biome format --write","knip":"knip","sync-domains":"bun scripts/sync-domains.ts","prepublishOnly":"npm run build && npm run test","publish:dev":"npm run build && npm publish --tag dev --access public","publish:patch":"npm whoami && npm version patch && git push --follow-tags && npm publish --access public","publish:minor":"npm whoami && npm version minor && git push --follow-tags && npm publish --access public","publish:major":"npm whoami && npm version major && git push --follow-tags && npm publish --access public"},"keywords":["disposable-email","email-validation","spam-prevention","mx-validation","bun"],"author":{"name":"bitclaw"},"license":"MIT","devDependencies":{"@biomejs/biome":"2.4.15","knip":"6.14.1","@types/bun":"1.3.14","@types/node":"22.19.19","typescript":"5.9.3"},"gitHead":"acc84ff2e747169700e89476633d0485cc65a1a1","_id":"@bitclaw/disposable-email@1.2.2","_nodeVersion":"24.11.1","_npmVersion":"11.6.2","dist":{"integrity":"sha512-62+I9UySOop7fAU9YZaAb0ZGD+5YMJdy4LWStVFOmyrY2ZfcY9E/dqcB3g/VKlJ+zFZgQJR8ljxwFc0EcjI6fQ==","shasum":"4eaed600af59e0d4e535f76df8e5e72d0051b678","tarball":"https://registry.npmjs.org/@bitclaw/disposable-email/-/disposable-email-1.2.2.tgz","fileCount":21,"unpackedSize":192040,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIBZ+qfKMlp3SqDO+B6l5qDaucFaRYTaY1FffC7HMQk0PAiBPEFqz1A2OChqjzSKRbc6rPk80tY/5Q8t5BWTuXTkwNA=="}]},"_npmUser":{"name":"bitclaw","email":"bitclaw@gmail.com"},"directories":{},"maintainers":[{"name":"bitclaw","email":"bitclaw@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/disposable-email_1.2.2_1785774484589_0.484075367391823"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-24T16:53:14.594Z","modified":"2026-08-03T16:28:04.878Z","1.1.0":"2026-05-24T16:53:14.949Z","1.2.0":"2026-07-28T23:21:14.217Z","1.2.1":"2026-07-28T23:40:33.523Z","1.2.2":"2026-08-03T16:28:04.729Z"},"author":{"name":"bitclaw"},"license":"MIT","keywords":["disposable-email","email-validation","spam-prevention","mx-validation","bun"],"description":"Fast disposable and free email provider detection with optional MX record validation","maintainers":[{"name":"bitclaw","email":"bitclaw@gmail.com"}],"readme":"# @bitclaw/disposable-email\n\nEmail validation against disposable/temporary email providers with optional DNS MX record checking.\n\n## Features\n\n- **Disposable domain blocklist** - ~8,200 known disposable email providers, generated from a\n  maintained community source (zero network calls to check)\n- **MX host detection** - Optional check that catches rotating-alias domains (services like\n  10minutemail.com that assign a fresh random domain per inbox) by matching the backend mail\n  server instead of the domain name\n- **MX record validation** - Optional DNS lookup to verify the domain can receive mail\n- **Fail-open DNS** - Transient DNS errors allow the request through (only blocks definitive failures)\n- **Zero dependencies** - Uses Node.js built-in `dns/promises`\n\n### Why two blocklists: domain names vs. MX hosts\n\nA domain blocklist only catches services a scraper has already discovered. It can never catch a\n*rotating-alias* service, where every signup gets a new, previously-unseen domain (e.g.\n`10minutemail.com` handed out `vtmpj.net` for one inbox). Those domains aren't predictable, so no\nstatic list, however well maintained, can enumerate them in advance.\n\nWhat *is* stable is the backend infrastructure: rotating-alias services still route all that mail\nthrough the same small set of MX servers, because standing up new mail infrastructure is\nexpensive while registering a new domain is nearly free. `DISPOSABLE_MX_HOSTS` in `src/mx-hosts.ts`\nmatches on that instead. It's checked only when `checkMx: true` is passed to `validateEmailDomain`,\nsince it requires a live DNS lookup.\n\n**Every entry in `DISPOSABLE_MX_HOSTS` was verified with a live `dig MX <domain>` lookup before\nbeing added, and hosts shared with real mail providers are deliberately excluded.** Some\ntemp-mail-flavored domains actually route through general-purpose providers (e.g. `mx.yandex.net`,\n`protonmail.ch`) - blocking those would false-positive real users of that provider, not just the\ndisposable service. Don't add a speculative or unverified hostname to this list; verify it's\ndedicated infrastructure for the disposable service first.\n\n## Installation\n\n```bash\nbun add @bitclaw/disposable-email\n```\n\n## Quick Start\n\n```typescript\nimport { isDisposableEmail, validateEmailDomain } from '@bitclaw/disposable-email'\n\n// Fast synchronous check against blocklist\nisDisposableEmail('user@tempmail.com')  // true\nisDisposableEmail('user@gmail.com')     // false\n\n// Full validation with optional MX check\nconst result = await validateEmailDomain('user@example.com', { checkMx: true })\nif (!result.valid) {\n  console.log(result.reason, result.message)\n}\n```\n\n## API\n\n### `isDisposableEmail(email: string): boolean`\n\nSynchronous check against the built-in blocklist. Returns `true` if the domain is a known disposable email provider.\n\n```typescript\nisDisposableEmail('user@guerrillamail.com')  // true\nisDisposableEmail('user@company.com')        // false\n```\n\n### `validateEmailDomain(email, options?): Promise<EmailValidationResult>`\n\nFull domain validation pipeline:\n\n1. Extracts and validates the domain from the email\n2. Checks against the disposable domain blocklist\n3. Optionally verifies DNS MX records\n\n```typescript\nconst result = await validateEmailDomain('user@fake-domain.xyz', {\n  checkMx: true,     // Enable MX record lookup (default: false)\n  dnsTimeout: 5000   // DNS timeout in ms (default: 5000)\n})\n\nif (!result.valid) {\n  // result.reason: 'disposable' | 'no-mx-records' | 'invalid-domain' | 'dns-error'\n  // result.message: Human-readable explanation\n}\n```\n\n### Types\n\n```typescript\ntype EmailValidationResult = {\n  valid: boolean\n  reason?: 'disposable' | 'no-mx-records' | 'invalid-domain' | 'dns-error'\n  message?: string\n}\n\ntype MxValidationOptions = {\n  checkMx?: boolean     // Default: false\n  dnsTimeout?: number   // Default: 5000\n}\n```\n\n### `DISPOSABLE_DOMAINS: Set<string>`\n\nThe raw domain blocklist, exported for direct access if needed:\n\n```typescript\nimport { DISPOSABLE_DOMAINS } from '@bitclaw/disposable-email'\n\nDISPOSABLE_DOMAINS.has('mailinator.com')  // true\nDISPOSABLE_DOMAINS.size                   // ~8,200\n```\n\nRegenerated from the [disposable-email-domains](https://github.com/disposable-email-domains/disposable-email-domains)\ncommunity CC0 blocklist via `bun run sync-domains`. It overwrites `src/domains.ts`.\n\nA weekly GitHub Actions workflow (`.github/workflows/sync-domains.yml`) runs this automatically\nand opens a PR if the list changed, so it doesn't drift the way the old hand-maintained list did.\n\n### `DISPOSABLE_MX_HOSTS: ReadonlySet<string>`\n\nCurated set of MX hostnames belonging to rotating-alias disposable-mail services, exported for\ndirect access:\n\n```typescript\nimport { DISPOSABLE_MX_HOSTS } from '@bitclaw/disposable-email'\n\nDISPOSABLE_MX_HOSTS.has('prd-smtp.10minutemail.com')  // true\n```\n\nThis list is hand-curated, not scraped, precisely because each entry needs to be verified as\ndedicated infrastructure (see \"Why two blocklists\" above) before it's safe to block on.\n\n## DNS Error Handling\n\n| DNS Result | Behavior |\n|-----------|----------|\n| MX records found, host not in `DISPOSABLE_MX_HOSTS` | `{ valid: true }` |\n| MX records found, host in `DISPOSABLE_MX_HOSTS` | `{ valid: false, reason: 'disposable' }` |\n| ENOTFOUND / ENODATA | `{ valid: false, reason: 'no-mx-records' }` |\n| Timeout | `{ valid: false, reason: 'dns-error' }` |\n| Other DNS error | `{ valid: true }` (fail-open) |\n\n## Design note: why `isDisposableEmail` never does a DNS lookup\n\n`isDisposableEmail` is synchronous and network-free by design, so callers can use it as an\nunconditional gate (e.g. on every OTP send) without adding an external DNS round-trip to the\ncritical path of login/signup. The MX-host check needs a live DNS lookup, so it only lives in\n`validateEmailDomain`'s opt-in `checkMx` path. If you need rotating-alias detection on every\nrequest, call `validateEmailDomain(email, { checkMx: true })` there deliberately, understanding\nyou're accepting DNS latency and the fail-open behavior above.\n\n## Testing\n\n```bash\nbun test\n```\n\n15 tests across 2 files.\n","readmeFilename":"README.md"}