PHP Classes

How to Use a PHP Email Validation Filter Class to Avoid Accepting Email Addresses That Will Be Invalid After Some Time Using the Package Disposable Email Blocker Core: Detect disposable or temporary email addresses

Recommend this page to a friend!
  Info   Documentation   View files Files   Install with Composer Install with Composer   Download Download   Reputation   Support forum   Blog    
Last Updated Ratings Unique User Downloads Download Rankings
2026-07-10 (1 month ago) RSS 2.0 feedNot yet rated by the usersTotal: Not yet counted Not yet ranked
Version License PHP version Categories
disposable-addresses 1.0MIT/X Consortium ...7Email, Networking, Validation, PHP 7
Description 

Author

This package can detect disposable or temporary email addresses.

It provides a class that can check if the domain of an email address is used to create disposable or temporary email addresses.

The package can also build email address checker objects using a fluent interface to define a list of criteria to check the email addresses.

Currently the checker builder can add criteria.

- Use domain lists from specific files

- Detect domains using patterns

- Exclude domains from being detected as disposable

- Use cache files to reduce the time to detect if email addresses are disposable

Picture of Raul
  Performance   Level  
Name: Raul <contact>
Classes: 8 packages by
Country: Brazil Brazil

Instructions

Please read this document to learn how to configure and use the class to validate disposable email addresses.

Documentation

Disposable Email Blocker - Core

Fast disposable/temporary email detection with full Public Suffix List (PSL) support, pattern matching, caching, and whitelist capabilities.

This repository is also a reference source for disposable/temporary email domains. Even if you don't use the PHP library, you can rely on it as a single, consolidated, always up-to-date list of disposable email domains, plus a fresh copy of the Public Suffix List. Automated workflows keep both files current under src/Resources/:

  • disposable_domains.txt - the consolidated, deduplicated list of disposable/temporary email domains, merged from multiple upstream sources.
  • public_suffix_list.dat - an up-to-date copy of the official Public Suffix List.

Consume these files directly (raw download, git submodule, or your own tooling) in any language or stack - no PHP required.

Table of Contents

Features

  • Fast O(1) lookups using hash-based domain checking
  • Full PSL support - correctly handles subdomains and public suffixes
  • IDN/Punycode support - international domain names are handled correctly
  • Pattern matching - detect suspicious domain patterns via regex
  • Whitelist support - allow specific domains to bypass checks
  • Caching layer - PSR-6/PSR-16 compatible cache adapters
  • Detailed results - `CheckResult` with matched checker info
  • Batch operations - efficiently check multiple emails at once
  • Multiple checkers - file-based, callback-based, or chain multiple checkers
  • Domain parsing - `DomainInfo` for detailed domain analysis (PSL, subdomain, IDN)
  • Extensible sources - built-in sources + custom parsers for any format
  • CLI tools - `bin/update-domains` to fetch and merge domain lists, `bin/update-psl` to update the Public Suffix List
  • Framework agnostic - use with any PHP project

Installation

composer require raul3k/disposable-email-blocker-core

Quick Start

use Raul3k\DisposableBlocker\Core\DisposableEmailChecker;

$checker = DisposableEmailChecker::create();

// Check if email is disposable
$checker->isDisposable('test@mailinator.com'); // true
$checker->isDisposable('test@gmail.com');      // false

// Safe version (returns false for invalid emails instead of throwing)
$checker->isDisposableSafe('invalid-email');   // false

// Check domain directly
$checker->isDomainDisposable('tempmail.com');  // true

Builder

The fluent builder is the recommended way to compose checkers:

use Raul3k\DisposableBlocker\Core\DisposableEmailChecker;

$checker = DisposableEmailChecker::builder()
    ->withBundledDomains()
    ->withPatternDetection()
    ->withWhitelist(['mycompany.com', 'partner.org'])
    ->withFileCache('/tmp/disposable-cache')
    ->build();

$checker->isDisposable('test@mailinator.com'); // true
$checker->isDisposable('test@mycompany.com');  // false (whitelisted)

Available builder methods:

  • `withBundledDomains()` - use the bundled ~159k domain list
  • `withDomainsFile(string $path)` - use a custom domains file
  • `withPatternDetection(?array $patterns = null)` - enable regex pattern matching
  • `withChecker(CheckerInterface $checker)` - add any custom checker
  • `withCallback(callable $callback)` - add a callback-based checker
  • `withWhitelist(array $domains)` - whitelist specific domains
  • `withFileCache(string $directory, ?int $ttl = 3600)` - enable file-based caching
  • `withCache(CacheInterface $cache, ?int $ttl = 3600)` - use a custom cache
  • `withNormalizer(DomainNormalizer $normalizer)` - use a custom normalizer

Detailed Check Results

Get detailed information about the check result:

use Raul3k\DisposableBlocker\Core\DisposableEmailChecker;

$checker = DisposableEmailChecker::create();

// Check an email
$result = $checker->check('test@mailinator.com');

$result->isDisposable();      // true
$result->isSafe();            // false
$result->getDomain();         // 'mailinator.com'
$result->getOriginalInput();  // 'test@mailinator.com'
$result->getMatchedChecker(); // 'Raul3k\DisposableBlocker\Core\Checkers\FileChecker'
$result->isWhitelisted();     // false
$result->toArray();           // array representation
$result->toJson();            // JSON string

// Check a domain directly
$result = $checker->checkDomain('mailinator.com');
$result->isDisposable(); // true

// Safe versions (return safe result for invalid input instead of throwing)
$result = $checker->checkSafe('invalid-email');
$result->isSafe(); // true

Batch Operations

Check multiple emails efficiently:

use Raul3k\DisposableBlocker\Core\DisposableEmailChecker;

$checker = DisposableEmailChecker::create();

$emails = [
    'user1@gmail.com',
    'user2@mailinator.com',
    'user3@yahoo.com',
];

// Get boolean results
$results = $checker->isDisposableBatch($emails);
// ['user1@gmail.com' => false, 'user2@mailinator.com' => true, 'user3@yahoo.com' => false]

// Get detailed results
$results = $checker->checkBatch($emails);
// ['user1@gmail.com' => CheckResult, 'user2@mailinator.com' => CheckResult, ...]

Pattern-Based Detection

Detect suspicious domain patterns using regex:

use Raul3k\DisposableBlocker\Core\DisposableEmailChecker;
use Raul3k\DisposableBlocker\Core\Checkers\{ChainChecker, FileChecker, PatternChecker};

// Combine file-based checking with pattern matching
$checker = DisposableEmailChecker::create(
    new ChainChecker([
        new FileChecker(__DIR__ . '/domains.txt'),
        new PatternChecker(), // Uses default patterns
    ])
);

// Default patterns detect:
// - temp, disposable, throwaway, fake, junk, spam
// - 10minutemail, 5minmail, etc.
// - guerrillamail, yopmail, mailinator
// - Suspicious TLDs: .tk, .ml, .ga, .cf, .gq

// Add custom patterns
$patternChecker = new PatternChecker();
$patternChecker->addPattern('/^suspicious-/i');

Whitelist Support

Allow specific domains to bypass disposable checks:

use Raul3k\DisposableBlocker\Core\DisposableEmailChecker;
use Raul3k\DisposableBlocker\Core\Checkers\{FileChecker, WhitelistChecker};

$innerChecker = new FileChecker(__DIR__ . '/domains.txt');
$whitelistChecker = new WhitelistChecker($innerChecker, [
    'company.com',      // Allow company.com and all subdomains
    'partner.org',
]);

$checker = DisposableEmailChecker::create($whitelistChecker);

// Even if mailinator.com is in the list, whitelist takes precedence
$whitelistChecker->addToWhitelist('special-case.mailinator.com');

// Check whitelist status
$whitelistChecker->isWhitelisted('company.com');     // true
$whitelistChecker->isWhitelisted('sub.company.com'); // true (parent is whitelisted)

Caching

Add caching to improve performance for repeated checks:

use Raul3k\DisposableBlocker\Core\DisposableEmailChecker;
use Raul3k\DisposableBlocker\Core\Checkers\{FileChecker, CachedChecker};
use Raul3k\DisposableBlocker\Core\Cache\{ArrayCache, FileCache};

// In-memory cache (single request)
$cache = new ArrayCache();

// File-based cache (persistent)
$cache = new FileCache('/path/to/cache/dir');

// Wrap any checker with caching
$innerChecker = new FileChecker(__DIR__ . '/domains.txt');
$cachedChecker = new CachedChecker($innerChecker, $cache, ttl: 3600);

$checker = DisposableEmailChecker::create($cachedChecker);

PSR-6/PSR-16 Cache Adapters

Use any PSR-compatible cache:

use Raul3k\DisposableBlocker\Core\Cache\{Psr6Adapter, Psr16Adapter};

// PSR-16 (SimpleCache)
$cache = new Psr16Adapter($yourPsr16Cache);

// PSR-6 (CacheItemPool)
$cache = new Psr6Adapter($yourPsr6Pool);

$cachedChecker = new CachedChecker($innerChecker, $cache);

Custom Checkers

Using a Callback (Redis, Database, API, etc.)

use Raul3k\DisposableBlocker\Core\DisposableEmailChecker;
use Raul3k\DisposableBlocker\Core\Checkers\CallbackChecker;

// Redis
$checker = DisposableEmailChecker::create(
    new CallbackChecker(fn(string $domain) => $redis->sismember('disposable_domains', $domain))
);

// PDO
$stmt = $pdo->prepare('SELECT 1 FROM disposable_domains WHERE domain = ? LIMIT 1');
$checker = DisposableEmailChecker::create(
    new CallbackChecker(function (string $domain) use ($stmt): bool {
        $stmt->execute([$domain]);
        return (bool) $stmt->fetchColumn();
    })
);

// Eloquent (Laravel)
$checker = DisposableEmailChecker::create(
    new CallbackChecker(fn(string $domain) => \App\Models\DisposableDomain::where('domain', $domain)->exists())
);

Implementing CheckerInterface

For reusable or complex checkers, implement the interface directly:

use Raul3k\DisposableBlocker\Core\Checkers\CheckerInterface;

class PdoDatabaseChecker implements CheckerInterface
{
    private \PDOStatement $stmt;

    public function __construct(\PDO $pdo, string $table = 'disposable_domains')
    {
        $this->stmt = $pdo->prepare(
            sprintf('SELECT 1 FROM %s WHERE domain = ? LIMIT 1', $table)
        );
    }

    public function isDomainDisposable(string $normalizedDomain): bool
    {
        $this->stmt->execute([$normalizedDomain]);
        return (bool) $this->stmt->fetchColumn();
    }
}

// Usage
$checker = DisposableEmailChecker::create(new PdoDatabaseChecker($pdo));

use Illuminate\Database\Eloquent\Model;
use Raul3k\DisposableBlocker\Core\Checkers\CheckerInterface;

class EloquentDatabaseChecker implements CheckerInterface
{
    / @var class-string<Model> */
    private string $model;

    / @param class-string<Model> $model */
    public function __construct(string $model = \App\Models\DisposableDomain::class)
    {
        $this->model = $model;
    }

    public function isDomainDisposable(string $normalizedDomain): bool
    {
        return $this->model::where('domain', $normalizedDomain)->exists();
    }
}

// Usage
$checker = DisposableEmailChecker::create(new EloquentDatabaseChecker());

Using a Custom File

use Raul3k\DisposableBlocker\Core\DisposableEmailChecker;
use Raul3k\DisposableBlocker\Core\Checkers\FileChecker;

$checker = DisposableEmailChecker::create(
    new FileChecker('/path/to/your/domains.txt')
);

Chaining Multiple Checkers

use Raul3k\DisposableBlocker\Core\DisposableEmailChecker;
use Raul3k\DisposableBlocker\Core\Checkers\{ChainChecker, FileChecker, PatternChecker, CallbackChecker};

$checker = DisposableEmailChecker::create(
    new ChainChecker([
        new FileChecker('/path/to/domains.txt'),
        new PatternChecker(),
        new CallbackChecker(fn($domain) => $redis->sismember('extra_domains', $domain)),
    ])
);

// After checking, you can see which checker matched
$result = $checker->check('test@tempmail.com');
$result->getMatchedChecker(); // 'Raul3k\DisposableBlocker\Core\Checkers\PatternChecker'

Working with Sources

Sources provide lists of disposable domains. The library includes several pre-configured sources.

Available Built-in Sources

| Source | Format | Size | |--------|--------|------| | disposable-email-domains | Text | ~5k | | burner-email-providers | Text | ~27k | | mailchecker | Text | ~56k | | ivolo-disposable | JSON | ~122k | | fakefilter | Text | ~10k |

Fetching from Sources

use Raul3k\DisposableBlocker\Core\Sources\SourceRegistry;

$registry = new SourceRegistry();

// List available sources
$sources = $registry->list();
// ['disposable-email-domains', 'burner-email-providers', 'mailchecker', ...]

// Fetch domains from a source
$source = $registry->get('disposable-email-domains');
foreach ($source->fetch() as $domain) {
    echo $domain . "\n";
}

Adding Custom Sources

use Raul3k\DisposableBlocker\Core\Sources\{SourceRegistry, UrlSource, FileSource};
use Raul3k\DisposableBlocker\Core\Parsers\{TextLineParser, JsonArrayParser};

$registry = new SourceRegistry();

// Remote text file (one domain per line)
$registry->register(new UrlSource(
    url: 'https://example.com/domains.txt',
    name: 'my-text-source',
    parser: new TextLineParser()
));

// Remote JSON array
$registry->register(new UrlSource(
    url: 'https://example.com/domains.json',
    name: 'my-json-source',
    parser: new JsonArrayParser()
));

// JSON with nested path
$registry->register(new UrlSource(
    url: 'https://api.example.com/data.json',
    name: 'my-nested-json',
    parser: new JsonArrayParser('response.data.domains')
));

// Local file
$registry->register(new FileSource(
    path: '/path/to/local-domains.txt',
    name: 'my-local-source'
));

Updating the Bundled Domain List

Use the CLI tool to fetch domains from all sources and update the bundled list:

# Update from all sources
./bin/update-domains

# Preview without writing
./bin/update-domains --dry-run

# Fetch from specific sources only
./bin/update-domains --source=disposable-email-domains --source=mailchecker

# Custom output path
./bin/update-domains --output=storage/domains.txt

# Show detailed progress
./bin/update-domains --verbose

# See all options
./bin/update-domains --help

You can customize sources via a disposable-blocker.php config file in your project root:

<?php
use Raul3k\DisposableBlocker\Core\Sources\UrlSource;

return [
    'sources' => [
        new UrlSource(
            url: 'https://example.com/my-domains.txt',
            name: 'my-custom-source'
        ),
    ],
    'exclude_sources' => ['fakefilter'],
    'output_path' => __DIR__ . '/storage/disposable_domains.txt',
];

Updating the Public Suffix List

The library bundles a copy of the Public Suffix List for domain normalization. To update it:

# Update to the latest PSL
./bin/update-psl

# Preview without writing
./bin/update-psl --dry-run

# Show detailed progress
./bin/update-psl --verbose

# Custom output path
./bin/update-psl --output=storage/public_suffix_list.dat

The script downloads from the canonical source, validates the content (size, structure, and parse checks), and writes the updated file.

A GitHub Actions workflow runs monthly to keep the bundled PSL current via automated PRs.

Domain Info

Parse and inspect domain details using the Public Suffix List:

use Raul3k\DisposableBlocker\Core\DomainInfo;

$info = DomainInfo::parse('user@mail.example.co.uk');

$info->domain();           // 'example.co.uk'
$info->subdomain();        // 'mail'
$info->publicSuffix();     // 'co.uk'
$info->secondLevelDomain(); // 'example'
$info->host();             // 'mail.example.co.uk'
$info->isIcann();          // true
$info->isPrivate();        // false
$info->isKnownSuffix();    // true
$info->isValid();          // true

// IDN support
$info = DomainInfo::parse('??????.??');
$info->ascii();   // 'xn--e1afmkfd.xn--p1ai'
$info->unicode(); // '??????.??'
$info->isIdn();   // true

// Works with emails, domains, and URLs
DomainInfo::parse('user@github.io')->isPrivate();    // true
DomainInfo::parse('https://example.com/path')->domain(); // 'example.com'

Domain Normalization

The library normalizes domains using the Public Suffix List to correctly extract registrable domains:

use Raul3k\DisposableBlocker\Core\DomainNormalizer;

$normalizer = new DomainNormalizer();

// Extract domain from email
$normalizer->normalizeFromEmail('user@sub.example.com'); // 'example.com'

// Normalize domain
$normalizer->normalizeDomain('sub.example.com');   // 'example.com'
$normalizer->normalizeDomain('sub.example.co.uk'); // 'example.co.uk'

// Handle IDN
$normalizer->normalizeDomain('??????.??'); // 'xn--e1afmkfd.xn--p1ai'

Framework Integration

For Laravel integration, see: - raul3k/disposable-email-blocker-laravel

Development

# Install dependencies
composer install

# Run tests
composer test

# Run tests with coverage
composer test:coverage

# Static analysis
composer analyse

# Code style check
composer cs:check

# Fix code style
composer cs:fix

# Run all quality checks
composer quality

License

MIT License. See LICENSE for details.


  Files folder image Files (80)  
File Role Description
Files folder image.github (3 files, 2 directories)
Files folder imagebin (2 files)
Files folder imagesrc (5 files, 7 directories)
Files folder imagetests (4 files, 3 directories)
Accessible without login Plain text file .coderabbit.yaml Data Auxiliary data
Accessible without login Plain text file .editorconfig Data Auxiliary data
Accessible without login Plain text file .php-cs-fixer.php Example Example script
Accessible without login Plain text file .release-please-manifest.json Data Auxiliary data
Accessible without login Plain text file CHANGELOG.md Data Auxiliary data
Accessible without login Plain text file composer.json Data Auxiliary data
Accessible without login Plain text file CONTRIBUTING.md Data Auxiliary data
Accessible without login Plain text file disposable-blocker.php.example Data Auxiliary data
Accessible without login Plain text file LICENSE Lic. License text
Accessible without login Plain text file phpstan.neon Data Auxiliary data
Accessible without login Plain text file phpunit.xml Data Auxiliary data
Accessible without login Plain text file README.md Doc. Read me
Accessible without login Plain text file release-please-config.json Data Auxiliary data
Accessible without login Plain text file SECURITY.md Data Auxiliary data

  Files folder image Files (80)  /  .github  
File Role Description
Files folder imageISSUE_TEMPLATE (2 files)
Files folder imageworkflows (8 files)
  Accessible without login Plain text file dependabot.yml Data Auxiliary data
  Accessible without login Plain text file PULL_REQUEST_TEMPLATE.md Data Auxiliary data
  Accessible without login Plain text file sync.yml Data Auxiliary data

  Files folder image Files (80)  /  .github  /  ISSUE_TEMPLATE  
File Role Description
  Accessible without login Plain text file bug_report.md Data Auxiliary data
  Accessible without login Plain text file feature_request.md Data Auxiliary data

  Files folder image Files (80)  /  .github  /  workflows  
File Role Description
  Accessible without login Plain text file ci.yml Data Auxiliary data
  Accessible without login Plain text file commitlint.yml Data Auxiliary data
  Accessible without login Plain text file release-please.yml Data Auxiliary data
  Accessible without login Plain text file static-analysis.yml Data Auxiliary data
  Accessible without login Plain text file sync.yml Data Auxiliary data
  Accessible without login Plain text file tests.yml Data Auxiliary data
  Accessible without login Plain text file update-domains.yml Data Auxiliary data
  Accessible without login Plain text file update-psl.yml Data Auxiliary data

  Files folder image Files (80)  /  bin  
File Role Description
  Accessible without login Plain text file update-domains Example Example script
  Accessible without login Plain text file update-psl Example Example script

  Files folder image Files (80)  /  src  
File Role Description
Files folder imageCache (5 files)
Files folder imageCheckers (7 files)
Files folder imageConfig (1 file)
Files folder imageExceptions (1 file)
Files folder imageParsers (4 files)
Files folder imageResources (2 files)
Files folder imageSources (4 files)
  Plain text file CheckResult.php Class Class source
  Plain text file DisposableEmailChecker.php Class Class source
  Plain text file DisposableEmailCheckerBuilder.php Class Class source
  Plain text file DomainInfo.php Class Class source
  Plain text file DomainNormalizer.php Class Class source

  Files folder image Files (80)  /  src  /  Cache  
File Role Description
  Plain text file ArrayCache.php Class Class source
  Plain text file CacheInterface.php Class Class source
  Plain text file FileCache.php Class Class source
  Plain text file Psr16Adapter.php Class Class source
  Plain text file Psr6Adapter.php Class Class source

  Files folder image Files (80)  /  src  /  Checkers  
File Role Description
  Plain text file CachedChecker.php Class Class source
  Plain text file CallbackChecker.php Class Class source
  Plain text file ChainChecker.php Class Class source
  Plain text file CheckerInterface.php Class Class source
  Plain text file FileChecker.php Class Class source
  Plain text file PatternChecker.php Class Class source
  Plain text file WhitelistChecker.php Class Class source

  Files folder image Files (80)  /  src  /  Config  
File Role Description
  Plain text file Configuration.php Class Class source

  Files folder image Files (80)  /  src  /  Exceptions  
File Role Description
  Plain text file InvalidDomainException.php Class Class source

  Files folder image Files (80)  /  src  /  Parsers  
File Role Description
  Plain text file CallbackParser.php Class Class source
  Plain text file JsonArrayParser.php Class Class source
  Plain text file ParserInterface.php Class Class source
  Plain text file TextLineParser.php Class Class source

  Files folder image Files (80)  /  src  /  Resources  
File Role Description
  Accessible without login Plain text file disposable_domains.txt Data Auxiliary data
  Accessible without login Plain text file public_suffix_list.dat Data Auxiliary data

  Files folder image Files (80)  /  src  /  Sources  
File Role Description
  Plain text file FileSource.php Class Class source
  Plain text file SourceInterface.php Class Class source
  Plain text file SourceRegistry.php Class Class source
  Plain text file UrlSource.php Class Class source

  Files folder image Files (80)  /  tests  
File Role Description
Files folder imageCache (4 files)
Files folder imageCheckers (3 files)
Files folder imageUnit (2 files, 3 directories)
  Plain text file CheckResultTest.php Class Class source
  Plain text file DisposableEmailCheckerBuilderTest.php Class Class source
  Plain text file DomainInfoTest.php Class Class source
  Plain text file TestCase.php Class Class source

  Files folder image Files (80)  /  tests  /  Cache  
File Role Description
  Plain text file ArrayCacheTest.php Class Class source
  Plain text file FileCacheTest.php Class Class source
  Plain text file Psr16AdapterTest.php Class Class source
  Plain text file Psr6AdapterTest.php Class Class source

  Files folder image Files (80)  /  tests  /  Checkers  
File Role Description
  Plain text file CachedCheckerTest.php Class Class source
  Plain text file PatternCheckerTest.php Class Class source
  Plain text file WhitelistCheckerTest.php Class Class source

  Files folder image Files (80)  /  tests  /  Unit  
File Role Description
Files folder imageCheckers (3 files)
Files folder imageParsers (3 files)
Files folder imageSources (3 files)
  Plain text file DisposableEmailCheckerTest.php Class Class source
  Plain text file DomainNormalizerTest.php Class Class source

  Files folder image Files (80)  /  tests  /  Unit  /  Checkers  
File Role Description
  Plain text file CallbackCheckerTest.php Class Class source
  Plain text file ChainCheckerTest.php Class Class source
  Plain text file FileCheckerTest.php Class Class source

  Files folder image Files (80)  /  tests  /  Unit  /  Parsers  
File Role Description
  Plain text file CallbackParserTest.php Class Class source
  Plain text file JsonArrayParserTest.php Class Class source
  Plain text file TextLineParserTest.php Class Class source

  Files folder image Files (80)  /  tests  /  Unit  /  Sources  
File Role Description
  Plain text file FileSourceTest.php Class Class source
  Plain text file SourceRegistryTest.php Class Class source
  Plain text file UrlSourceTest.php Class Class source

The PHP Classes site has supported package installation using the Composer tool since 2013, as you may verify by reading this instructions page.
Install with Composer Install with Composer
 Version Control Unique User Downloads  
 100%
Total:0
This week:0