Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Burner Email Providers Laravel Package

wesbos/burner-email-providers

A maintained list of disposable and burner email domains for blocking throwaway signups. Drop it into validation rules or your own checks to reject temporary addresses, with a simple dataset you can filter, cache, or extend.

View on GitHub
Deep Wiki
Context7

Getting Started

There is no Composer package here — composer require wesbos/burner-email-providers will not resolve. This repo is a data source (a plain list of disposable-email domains, one per line, plus an npm wrapper). Your first job is deciding how that data gets into your app.

First steps:

  1. Read the repo root before anything else — emails.txt is the canonical list, and the npm entrypoint just re-exports it. Check the commit history: the value of this package is entirely "how recently was it updated," not code quality.
  2. Vendor a snapshot rather than fetching at runtime:
curl -o database/data/burner-emails.txt \
  https://raw.githubusercontent.com/wesbos/burner-email-providers/master/emails.txt
  1. If you live in a JS build pipeline anyway, npm i burner-email-providers and copy the JSON export into resources/data/ during a build step. For a pure PHP/Laravel app, the raw file is simpler and has no node dependency.

  2. Normalize it into a lookup structure once at boot (a singleton or a cached config array) — do not read the file per request.

First use case: block disposable addresses at registration. Wrap the list in a custom validation rule and attach it to your RegisterRequest:

// app/Rules/NotBurnerEmail.php
class NotBurnerEmail implements ValidationRule
{
    public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        [$local, $domain] = array_pad(explode('@', strtolower(trim($value)), 2), 2, null);
        if ($domain && BurnerList::contains($domain)) {
            $fail('Please use a permanent email address — disposable inboxes are not accepted.');
        }
    }
}

Then 'email' => ['required', 'email', new NotBurnerEmail].

Implementation Patterns

Singleton set, flipped for O(1) lookup. Loading ~10k strings and calling in_array() per validation is wasteful and case-buggy. Flip once:

final class BurnerList
{
    private static ?array $domains = null;

    public static function contains(string $domain): bool
    {
        self::$domains ??= Cache::rememberForever('burner-domains', fn () =>
            array_flip(array_filter(array_map(
                fn ($d) => strtolower(trim($d)),
                file(base_path('database/data/burner-emails.txt'), FILE_IGNORE_NEW_LINES)
            )))
        );

        // also check the parent domain: [email protected] -> mailinator.com
        do {
            if (isset(self::$domains[$domain])) return true;
        } while ($domain = Str::afterLast($domain, '.'));

        return false;
    }
}

Refresh as a scheduled command, not a runtime dependency. The list changes weekly. Ship a burner:update artisan command that pulls the raw file, validates it (non-empty, sane line count, all lines look like domains), and atomically replaces your snapshot. Schedule it monthly in routes/console.php, and commit the refreshed file so deploys are deterministic.

Schedule::command('burner:update')->monthly()->onOneServer();
// after writing the file:
Cache::forget('burner-domains');

Use it as a soft signal, not a hard gate, for existing accounts. A Registered event listener that tags the user (users.risk_flags or a DisposableEmail attribute) lets you throttle trials, skip welcome credits, or require manual review — without blocking signup flows you might regret blocking. Reserve hard rejection for free-tier signups and newsletter forms.

Layer the check. A domain list only catches lazy abuse. Pair it with a DNS/MX existence check and, for trial abuse specifically, a normalized-address comparison (strip +tags, compare the @ domain). Disposable providers rotate domains faster than any static list.

Test the plumbing, not the list. Don't assert on specific domains — the file changes. Assert that your rule rejects a domain you inject via a fixture and accepts gmail.com. For the update command, Http::fake() the raw GitHub response and assert the file and cache are refreshed.

Consider the mature alternative first. Propaganistas\LaravelDisposableEmail is a Composer-installable rule that wraps a comparable (larger, more actively synced) blocklist and gives you disposable_email validation out of the box. If all you need is "reject disposable at registration," use that and skip this package entirely. Reach for wesbos/burner-email-providers only when you want the raw data under your own control — e.g., you need it in a queued job, a scraper guard, or an internal admin filter, not just a validator.

Gotchas and Tips

  • No PHP integration, zero. No service provider, no facade, no config, no composer.json. Everything above is code you write. Budget for that; it's not a five-minute composer require.
  • Never use str_contains($email, $domain). Substring matching against a domain list is a classic false-positive generator. Split on @ and compare the domain label exactly.
  • Subdomains are the leak. The list contains mailinator.com; attackers send from anything.mailinator.com. Walk the domain labels upward as shown above.
  • Watch config:cache and Octane. If you put the list in a config file it gets baked into the cached config — a burner:update won't take effect until config:cache reruns. Keep the data in a file + cache store instead, and forget the cache key on refresh. Under Octane, the static $domains array persists per worker; make sure the refresh path clears it.
  • False positives happen. Real businesses occasionally land on these lists because someone's shared hosting looks like a burner provider. Never retroactively deactivate existing users, and always show a human-readable message with a support path.
  • Don't fetch from GitHub at runtime. Raw URLs are rate-limited, can 404 on branch renames, and turn a third-party outage into a signup outage. Snapshot + scheduled refresh.
  • The list is community-maintained and not audited. Treat freshness as a maintenance chore you own: if nobody refreshes the file for a year, you've shipped a year-old blocklist. That's the main cost of choosing this package over a Composer-native alternative.
  • MIT licensed — attribution is a courtesy, not an obligation, but drop a line in your README crediting the repo and noting the snapshot date.
  • Extension point: if you want to allowlist certain domains (e.g., a partner's shared inbox provider that's on the list), keep a separate config/burner-allowlist.php and check it before the blocklist rather than forking the vendored file.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route