npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

temp-cloak

v0.1.0

Published

Detect disposable/temporary email addresses, free webmail providers, and role accounts. Zero dependencies, works in Node and the browser, with an optional Express middleware and a memory-optimized Bloom-filter variant.

Readme

disposable-email-guard

Detect disposable / temporary email addresses, free webmail providers, and role accounts (info@, support@, ...). Works in Node and the browser, ships dual ESM + CJS + .d.ts, and includes an optional Express middleware plus a memory-optimized Bloom-filter variant.

npm install disposable-email-guard

Quick start

import { isDisposable, check, isFreeProvider, isRoleAccount } from "disposable-email-guard";

isDisposable("[email protected]"); // true
isDisposable("[email protected]");      // false

isFreeProvider("[email protected]");    // true
isRoleAccount("[email protected]");      // true

check("[email protected]");
// {
//   email: "[email protected]",
//   domain: "mailinator.com",
//   disposable: true,
//   category: "disposable",
//   reason: 'domain "mailinator.com" is a known disposable provider',
//   normalized: "[email protected]"
// }

isDisposable (and the other helpers) accept either a full email or a bare domain:

isDisposable("mailinator.com"); // true

API

isDisposable(emailOrDomain, options?) => boolean

Options:

  • matchSubdomains (default true) — walk parent domains, so foo.mailinator.com matches mailinator.com.
  • allowlist — iterable of domains to always treat as not disposable.
isDisposable("[email protected]");                          // true
isDisposable("[email protected]", { matchSubdomains: false }); // false
isDisposable("[email protected]", { allowlist: ["mailinator.com"] }); // false

check(emailOrDomain, options?) => CheckResult

Returns the full classification. Never throws — invalid input yields a clean result:

check("not-an-email");
// { email: "not-an-email", domain: null, disposable: false,
//   category: "clean", reason: "invalid format", normalized: null }
interface CheckResult {
  email: string | null;
  domain: string | null;
  disposable: boolean;
  category: "disposable" | "free" | "role" | "clean";
  reason: string;
  normalized: string | null;
}

isFreeProvider(emailOrDomain) => boolean

True for gmail/yahoo/outlook/hotmail/icloud/proton, etc.

isRoleAccount(email) => boolean

True when the normalized local-part is a role account (admin, info, support, noreply, sales, contact, help, ...).

Mutating the shared list

import { addDomains, removeDomains, allowDomains } from "disposable-email-guard";

addDomains(["my-temp-mail.example"]);
removeDomains(["yopmail.com"]);
allowDomains(["partner-temp.example"]); // never flagged as disposable

createGuard(opts?) => Guard

An isolated instance with its own domain sets — mutations don't leak into the global guard.

import { createGuard } from "disposable-email-guard";

const guard = createGuard();
guard.addDomains(["local-only.example"]);
guard.isDisposable("[email protected]"); // true
// the global isDisposable() is unaffected

You can also seed an isolated guard with a blocklist / allowlist:

const guard = createGuard({ blocklist: ["x.com"], allowlist: ["y.com"] });
guard.isDisposable("[email protected]"); // true
guard.isDisposable("[email protected]"); // false

datasetVersion

import { datasetVersion } from "disposable-email-guard";
datasetVersion; // { version: "0.1.0", domains: <actual count> }

The domains value is the actual number of entries in the bundled list, computed at runtime.

Express middleware

express is an optional peer dependency. This package never imports express at runtime and types the request/response loosely, so it stays framework-agnostic.

import express from "express";
import { emailGuard } from "disposable-email-guard";

const app = express();
app.use(express.json());

app.post(
  "/signup",
  emailGuard({
    field: "email",            // string field, or (req) => string | undefined
    block: ["disposable"],     // categories that cause a 403
    allowlist: ["partner.example"],
    blocklist: ["bad.example"],
    matchSubdomains: true,
    attach: true,            // attach result to req.emailCheck (default true)
    onBlock: (req, res, next, result) => {
      res.status(422).json({ message: "No throwaway emails", reason: result.reason });
    },
  }),
  (req, res) => {
    // req.emailCheck holds the full CheckResult
    res.json({ ok: true, check: req.emailCheck });
  },
);

The middleware attaches the full result to req.emailCheck. When omitted, the default onBlock responds with 403 JSON. Requests without an email field pass through untouched.

Memory-optimized Bloom variant

For large deployments where memory matters, import the same API from disposable-email-guard/bloom. It's backed by a Bloom filter: never produces false negatives (every known disposable domain is still flagged) at the cost of a tiny, tunable false-positive probability.

import { isDisposable } from "disposable-email-guard/bloom";

isDisposable("[email protected]"); // true

CLI

npx disposable-email-guard update

The updater is a stub for now — fetching a remote feed is planned for a future release. Use addDomains() / createGuard() to extend the list today.

About the data

The bundled lists are a curated STARTER SET, not exhaustive. Disposable providers appear, disappear, and rotate domains constantly. Treat this as a baseline signal and combine it with your own heuristics or an external feed via addDomains(). The disposable-domain count is reported honestly through datasetVersion.domains.

License

MIT © udayps