PHPackages                             harungecit/php-email-validator - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Mail &amp; Notifications](/categories/mail)
4. /
5. harungecit/php-email-validator

ActiveLibrary[Mail &amp; Notifications](/categories/mail)

harungecit/php-email-validator
==============================

A comprehensive PHP email validation library to check format, detect disposable emails, validate MX records, role-based detection, typo suggestions, and support batch validation with configurable cache and rate limiting.

v3.1.0(3w ago)3313MITPHPPHP &gt;=8.0CI passing

Since Jan 22Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/harungecit/php-email-validator)[ Packagist](https://packagist.org/packages/harungecit/php-email-validator)[ Docs](https://github.com/harungecit/php-email-validator)[ RSS](/packages/harungecit-php-email-validator/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (4)Dependencies (15)Versions (7)Used By (0)

HarunGecit/php-email-validator
==============================

[](#harungecitphp-email-validator)

[![PHP Version](https://camo.githubusercontent.com/9efc6f0bd837905e4709934d35f38d91de321e9e03d37d46a97808cf41ef969a/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f686172756e67656369742f7068702d656d61696c2d76616c696461746f723f7374796c653d666c61742d737175617265266c6f676f3d706870266c6f676f436f6c6f723d7768697465)](https://packagist.org/packages/harungecit/php-email-validator)[![Latest Version](https://camo.githubusercontent.com/33f3924ad9ee02075d1d698ef89db03b88cf102d93eb8d6fc7b6862d550c67e9/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f686172756e67656369742f7068702d656d61696c2d76616c696461746f723f7374796c653d666c61742d737175617265266c6f676f3d7061636b6167697374266c6f676f436f6c6f723d7768697465266c6162656c3d76657273696f6e)](https://packagist.org/packages/harungecit/php-email-validator)[![Total Downloads](https://camo.githubusercontent.com/9072321cd8ebe0c649ac00eeff3a8efa2182426f2d7eba9429aad91a2e076025/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f686172756e67656369742f7068702d656d61696c2d76616c696461746f723f7374796c653d666c61742d737175617265266c6f676f3d7061636b6167697374266c6f676f436f6c6f723d7768697465)](https://packagist.org/packages/harungecit/php-email-validator)[![License](https://camo.githubusercontent.com/e4c5f674edb62157aef3153b843076fcee5d502829e4a028178723fa91bddcef/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f686172756e67656369742f7068702d656d61696c2d76616c696461746f723f7374796c653d666c61742d737175617265266c6f676f3d6f70656e736f75726365266c6f676f436f6c6f723d7768697465)](LICENSE)[![CI Status](https://camo.githubusercontent.com/7949e32cdcee89aade7954c4ae807a3930c75c7e9ebd88e146c276c5aa5ec9f2/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f686172756e67656369742f7068702d656d61696c2d76616c696461746f722f63692e796d6c3f6272616e63683d6d61696e267374796c653d666c61742d737175617265266c6f676f3d676974687562266c6f676f436f6c6f723d7768697465266c6162656c3d7465737473)](https://github.com/harungecit/php-email-validator/actions)![Code Quality](https://camo.githubusercontent.com/d76554743a08a74c792f596c72b5e0bc2835fe5408ac19b16c7adb01a86cb42c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636f64652532307175616c6974792d412d627269676874677265656e3f7374796c653d666c61742d737175617265266c6f676f3d636f64616379266c6f676f436f6c6f723d7768697465)![Maintenance](https://camo.githubusercontent.com/be65fcf3b08bf41d183a195d7e4ef697769e2de8ddf861525681c9ce1af19a46/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6d61696e7461696e65642d7965732d677265656e3f7374796c653d666c61742d737175617265266c6f676f3d676974266c6f676f436f6c6f723d7768697465)

A comprehensive, framework-friendly PHP email validation library: format and RFC checks, disposable-domain detection, MX/DNS verification, role-based detection, plus-addressing (subaddress) handling, typo suggestions, SMTP and catch-all verification, batch validation, pluggable caching and rate limiting — all configurable through a fluent builder.

![Blocklist Domains](https://camo.githubusercontent.com/783edbb877b1ca414e95c260ef38ae6e537ecc47bb6441e141d6ac819cf6fe7a/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f626c6f636b6c6973742d372c393030253242253230646f6d61696e732d7265643f7374796c653d666c61742d737175617265266c6f676f3d736869656c64266c6f676f436f6c6f723d7768697465)![Allowlist Domains](https://camo.githubusercontent.com/98947ee82a34de444505ee6e0c3e4d24c770f9e00a2115fc500dc08fbb08d013/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f616c6c6f776c6973742d313830253242253230646f6d61696e732d677265656e3f7374796c653d666c61742d737175617265266c6f676f3d736869656c64266c6f676f436f6c6f723d7768697465)![Platform Support](https://camo.githubusercontent.com/3011bed77eafd318a0caf818e91620721112f8c4f2ca77635f72353e55d40cb9/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f706c6174666f726d2d4c696e757825323025374325323057696e646f77732532302537432532306d61634f532d626c75653f7374796c653d666c61742d737175617265266c6f676f3d77696e646f7773266c6f676f436f6c6f723d7768697465)

---

Features
--------

[](#features)

- **Format Validation** — RFC-compliant format checks via PHP's built-in filters.
- **Disposable Email Detection** — an extensive bundled blocklist (7,900+ domains, sourced from [disposable-email-domains](https://github.com/disposable-email-domains/disposable-email-domains)) with an allowlist override.
- **MX &amp; DNS Verification** — verify that the domain has mail servers (MX) or A/AAAA records.
- **Role-Based Detection** — flag addresses like `info@`, `admin@`, `support@`.
- **Subaddress (Plus Addressing)** — detect `user+tag@gmail.com`, extract the base address, compare equivalence.
- **Typo Suggestions** — "did you mean `gmail.com`?" for common provider typos, with a confidence score.
- **SMTP &amp; Catch-All Verification** — optional live mailbox and catch-all domain checks.
- **Rich Result Object** — `ValidationResult` with per-check status, errors, warnings, metadata, and JSON export.
- **Pluggable Cache** — Memory, File, Redis, Memcached, PSR-16, or Null adapters.
- **Rate Limiting** — token-bucket limiter to throttle validation attempts.
- **Fluent Configuration** — `ConfigurationBuilder` with `strict`, `standard`, `basic`, and `minimal` presets, or load from PHP/JSON/YAML files.
- **Framework Integration** — first-class Laravel and Symfony support.
- **PSR-3 Logging** — inject any PSR-3 logger.
- **Batch Tools** — validate lists, filter valid/invalid, gather statistics.
- **Backward Compatible** — the 2.x API (`isValid`, `validateWithDetails`, `validateMultiple`, list management) still works unchanged.

---

Installation
------------

[](#installation)

```
composer require harungecit/php-email-validator
```

---

Compatibility
-------------

[](#compatibility)

- **Requires PHP 8.0 or newer.** Verified on PHP **8.0, 8.1, 8.2, 8.3, 8.4** and **8.5**.
- Tested on Ubuntu, Windows, and macOS.
- Optional integrations (install as needed): `illuminate/support` (Laravel), `symfony/http-kernel` + `symfony/dependency-injection` (Symfony), `ext-redis`/`predis/predis` (Redis cache), `ext-memcached` (Memcached cache), `ext-intl` (IDN), `symfony/yaml` or `ext-yaml` (YAML config).

> The library itself runs on PHP 8.0+. Running the **test suite** requires PHP 8.1+ (PHPUnit 10+), since the tests use attribute-based data providers.

---

Quick Start
-----------

[](#quick-start)

```
use HarunGecit\EmailValidator\EmailValidator;

$validator = EmailValidator::create();

// Simple boolean check (format + disposable + MX by default)
if ($validator->isValid('user@example.com')) {
    echo "Email is valid!";
}
```

Need a detailed report instead of a boolean? Use `validate()`:

```
$result = $validator->validate('user@example.com');

$result->isValid();      // bool
$result->getErrors();    // string[]
$result->getChecks();    // ['format' => true, 'disposable' => true, 'mx' => true, ...]
```

---

Configuration
-------------

[](#configuration)

Everything is driven by a `Configuration` object. The easiest way to build one is the fluent `ConfigurationBuilder`.

```
use HarunGecit\EmailValidator\EmailValidator;
use HarunGecit\EmailValidator\Config\ConfigurationBuilder;

$config = ConfigurationBuilder::create()
    ->standard()                       // start from a preset
    ->withRoleBasedCheck()             // then customize
    ->withTypoSuggestion()
    ->withFileCache(__DIR__ . '/cache', 3600)
    ->withRateLimiting(100, 60)
    ->build();

$validator = EmailValidator::withConfig($config);
```

### Presets

[](#presets)

PresetEnabled checks`minimal()`format`basic()`format, disposable`standard()`format, mx, disposable, typo suggestion`strict()`format, mx, disposable, role-based, subaddress, typo suggestion, **smtp**, **catch-all**```
$validator = EmailValidator::strict();   // shortcut for ConfigurationBuilder::create()->strict()->build()
$validator = EmailValidator::basic();    // shortcut for the basic() preset
```

> **Note:** `strict()` enables SMTP and catch-all verification, which perform live network connections and can be slow or blocked by mail servers. For most applications `standard()` is the recommended starting point.

### Individual toggles

[](#individual-toggles)

Every check has an `enable*` method on `Configuration` and a `with*`/`without*` method on the builder:

```
$config = ConfigurationBuilder::create()
    ->withoutMxCheck()          // disable MX lookups
    ->withoutDisposableCheck()  // allow disposable domains
    ->withSubaddressCheck()     // detect plus addressing
    ->withCatchAllCheck()       // detect catch-all domains
    ->withSmtpCheck(10, 'verify@your-domain.com')
    ->build();
```

Check defaults: `format`, `mx`, `disposable` are **on**; `role_based`, `smtp`, `typo_suggestion`, `subaddress`, `catch_all` are **off** (a bare `new Configuration()`). Presets change these as shown above.

### Loading configuration from a file

[](#loading-configuration-from-a-file)

`EmailValidator::fromConfigFile()` supports `.php`, `.json`, and `.yaml`/`.yml`:

```
$validator = EmailValidator::fromConfigFile(__DIR__ . '/config/emailvalidator.php');
```

A ready-made template lives in [`config/emailvalidator.php`](config/emailvalidator.php) (and `.json`). Top-level keys: `checks`, `cache`, `rate_limit`, `lists`, `role_based`, `typo`, `smtp`, `dns`.

```
// config/emailvalidator.php
return [
    'checks' => [
        'format' => true, 'mx' => true, 'disposable' => true,
        'role_based' => false, 'smtp' => false,
        'typo_suggestion' => true, 'subaddress' => false, 'catch_all' => false,
    ],
    'cache'      => ['driver' => 'memory', 'ttl' => 3600, 'prefix' => 'email_validator_', 'options' => []],
    'rate_limit' => ['enabled' => false, 'max_attempts' => 100, 'decay_seconds' => 60],
    'lists'      => ['blocklist_path' => null, 'allowlist_path' => null, 'role_based_path' => null],
    'smtp'       => ['timeout' => 10, 'from_email' => null, 'from_domain' => null],
    'dns'        => ['timeout' => 5],
];
```

---

The `ValidationResult` object
-----------------------------

[](#the-validationresult-object)

`validate()` returns a rich result you can inspect:

```
use HarunGecit\EmailValidator\EmailValidator;
use HarunGecit\EmailValidator\Config\ConfigurationBuilder;

$config    = ConfigurationBuilder::create()->standard()->withRoleBasedCheck()->build();
$validator = EmailValidator::withConfig($config);

$result = $validator->validate('info@gmial.com');

$result->isValid();                 // bool — true only if every enabled check passed
$result->getEmail();                // 'info@gmial.com'
$result->getDomain();               // 'gmial.com'
$result->getLocalPart();            // 'info'
$result->getChecks();               // ['format' => true, 'disposable' => true, 'role_based' => false, ...]
$result->passed('mx');              // ?bool — null if the check was not run
$result->getErrors();               // ['Role-based email address']
$result->getFirstError();           // 'Role-based email address'
$result->getWarnings();             // string[]
$result->isDisposable();            // ?bool
$result->isRoleBased();             // ?bool
$result->isSubaddressed();          // ?bool
$result->getMetadata();             // array (e.g. base_email for subaddressed emails)
$result->hasSuggestion();           // bool
$result->getSuggestion();           // ?SuggestionResult
$result->toArray();                 // full array representation
$result->toJson(JSON_PRETTY_PRINT); // JSON string
```

---

Individual Checks
-----------------

[](#individual-checks)

Each check is also available as a standalone method:

```
$validator->isValidFormat('user@example.com');   // format only
$validator->isDisposable('user@mailinator.com'); // blocklist (allowlist wins)
$validator->hasValidMX('user@example.com');      // MX records (cached)
$validator->hasValidDNS('user@example.com');     // A / AAAA records
$validator->isRoleBased('info@example.com');     // role-based prefix
$validator->isSubaddressed('user+tag@gmail.com');// plus addressing
$validator->getBaseEmail('user+tag@gmail.com');  // 'user@gmail.com'
$validator->isCatchAll('user@example.com');      // catch-all domain (SMTP)
$validator->validateSMTP('user@example.com');    // live SMTP mailbox check
```

### Typo suggestions

[](#typo-suggestions)

```
$suggestion = $validator->getSuggestion('user@gmial.com');

if ($suggestion !== null) {
    $suggestion->getSuggestedEmail();   // 'user@gmail.com'
    $suggestion->getSuggestedDomain();  // 'gmail.com'
    $suggestion->getOriginalEmail();    // 'user@gmial.com'
    $suggestion->getReason();           // 'known_typo' | 'similar_domain'
    $suggestion->getConfidence();       // 0–100
    $suggestion->isHighConfidence(80);  // bool
    (string) $suggestion;               // 'user@gmail.com'
}
```

---

Batch Validation
----------------

[](#batch-validation)

```
$emails = ['user1@gmail.com', 'user2@mailinator.com', 'invalid-email'];

// Rich results keyed by email
$results = $validator->validateBatch($emails);         // array

// Backward-compatible array results
$results = $validator->validateMultiple($emails, false); // $checkMX = false

// Filtering
$valid   = $validator->filterValid($emails, false);      // string[]
$invalid = $validator->filterInvalid($emails, false);    // string[]

// Statistics
$stats = $validator->getStatistics($emails, false);
// ['total' => 3, 'valid' => 1, 'invalid' => 2, 'disposable' => 1, 'invalid_format' => 1, 'no_mx' => 0]
```

---

Caching
-------

[](#caching)

MX lookups and catch-all results are cached through a pluggable adapter. Choose a driver via the builder:

```
ConfigurationBuilder::create()->withMemoryCache(3600);                          // in-process (default)
ConfigurationBuilder::create()->withFileCache('/tmp/ev-cache', 3600);           // filesystem
ConfigurationBuilder::create()->withRedisCache('127.0.0.1', 6379, null, 0);     // ext-redis or Predis
ConfigurationBuilder::create()->withMemcachedCache('127.0.0.1', 11211);         // ext-memcached
ConfigurationBuilder::create()->withPsr16Cache($anyPsr16Cache);                 // wrap a PSR-16 cache
ConfigurationBuilder::create()->withoutCache();                                 // disable caching
```

Supported driver names: `memory`, `file`, `redis`, `memcached`, `psr16`, `null`. You can also register a custom driver:

```
use HarunGecit\EmailValidator\Cache\CacheManager;

CacheManager::registerDriver('my-driver', MyCacheAdapter::class);
CacheManager::getAvailableDrivers();          // string[]
CacheManager::isDriverAvailable('redis');     // bool
```

The legacy `setCacheEnabled(false)` / `clearCache()` helpers from 2.x still work.

---

Rate Limiting
-------------

[](#rate-limiting)

Throttle how many times an identifier may be validated within a decay window. When the limit is exceeded, `validate()`/`isValid()` throw `RateLimitExceededException`.

```
use HarunGecit\EmailValidator\Config\ConfigurationBuilder;
use HarunGecit\EmailValidator\Exceptions\RateLimitExceededException;

$config = ConfigurationBuilder::create()
    ->standard()
    ->withRateLimiting(maxAttempts: 5, decaySeconds: 60)
    ->build();

$validator = EmailValidator::withConfig($config);

try {
    $result = $validator->validate($email);
} catch (RateLimitExceededException $e) {
    echo "Too many attempts. Retry after {$e->getRetryAfter()}s (max {$e->getMaxAttempts()}).";
}
```

The limiter shares the configured cache backend, so it works across processes when backed by Redis/Memcached/File.

---

Logging (PSR-3)
---------------

[](#logging-psr-3)

```
$validator->setLogger($psr3Logger);
// or via configuration
$config = ConfigurationBuilder::create()->standard()->build();
$config->setLogger($psr3Logger);
```

Each `validate()` call logs a debug entry with the email, outcome, checks, and errors.

---

Custom Blocklist / Allowlist
----------------------------

[](#custom-blocklist--allowlist)

```
$validator = new EmailValidator([], []); // start empty

$validator->addToBlocklist('custom-disposable.com')
          ->addMultipleToBlocklist(['temp1.com', 'temp2.com'])
          ->addToAllowlist('trusted-domain.com'); // allowlist always wins over blocklist

$validator->removeFromBlocklist('temp1.com');

$validator->getBlocklist();       // string[]
$validator->getBlocklistCount();  // int
$validator->isBlocklisted('a@temp2.com');
$validator->isAllowlisted('a@trusted-domain.com');
```

You can also point the configuration at your own list files:

```
$config = ConfigurationBuilder::create()
    ->withBlocklist('/path/to/blocklist.conf')
    ->withAllowlist('/path/to/allowlist.conf')
    ->build();
```

---

Framework Integration
---------------------

[](#framework-integration)

### Laravel

[](#laravel)

The package ships with auto-discovery (service provider + `EmailValidator` facade). Publish the config if you want to customize it:

```
php artisan vendor:publish --tag=emailvalidator-config
```

Resolve it from the container, or use the facade:

```
use HarunGecit\EmailValidator\Framework\Laravel\EmailValidatorFacade as EmailValidator;

EmailValidator::isValid('user@example.com');
EmailValidator::validate('user@example.com');

// or inject the concrete service
public function store(\HarunGecit\EmailValidator\EmailValidator $validator) { /* ... */ }
```

Config-driven validation rules are registered automatically:

```
$request->validate([
    'email' => ['required', 'valid_email', 'not_disposable', 'not_role_based', 'has_mx', 'not_subaddressed'],
]);
```

The published config (`config/emailvalidator.php`) is env-aware (`MAIL_FROM_ADDRESS`, `LOG_CHANNEL`, etc.) and defaults the cache driver to `laravel`, reusing your application's cache store.

### Symfony

[](#symfony)

Register the bundle:

```
// config/bundles.php
return [
    HarunGecit\EmailValidator\Framework\Symfony\EmailValidatorBundle::class => ['all' => true],
];
```

Configure it under the `email_validator` key:

```
# config/packages/email_validator.yaml
email_validator:
    checks:
        format: true
        mx: true
        disposable: true
        typo_suggestion: true
    cache:
        driver: memory   # memory | file | redis | memcached | psr16 | null
        ttl: 3600
    rate_limit:
        enabled: false
        max_attempts: 100
        decay_seconds: 60
```

The `EmailValidator` service is public and autowirable (service id `email_validator`, or type-hint the class).

---

How It Works
------------

[](#how-it-works)

1. **Format** — `filter_var($email, FILTER_VALIDATE_EMAIL)`.
2. **Disposable** — the domain is checked against the bundled blocklist; any domain in the allowlist is never treated as disposable.
3. **MX / DNS** — `checkdnsrr()` for MX (or A/AAAA) records, with results cached per domain.
4. **Role-based / Subaddress / Typo / SMTP / Catch-all** — each runs only when enabled in the configuration and contributes to the final `ValidationResult`.

---

Blocklist and Allowlist
-----------------------

[](#blocklist-and-allowlist)

Bundled data lives in the `data/` directory:

- **Blocklist (`blocklist.conf`)** — 7,900+ disposable/temporary email domains.
- **Allowlist (`allowlist.conf`)** — 180+ domains that should always be considered valid.

The blocklist is synchronized with the community-maintained [disposable-email-domains](https://github.com/disposable-email-domains/disposable-email-domains) project (plus a few local additions). One lowercase domain per line:

```
mailinator.com
guerrillamail.com
tempmail.com

```

Load, merge, or persist lists with the `Fetcher` utility:

```
use HarunGecit\EmailValidator\Fetcher;

$lists = Fetcher::loadAll();                    // ['blocklist' => [...], 'allowlist' => [...]]
$custom = Fetcher::loadCustomBlocklist('/path/to/custom.conf');
$merged = Fetcher::mergeLists(['/a.conf', '/b.conf']);
Fetcher::saveList('/out.conf', ['domain1.com', 'domain2.com']);
```

---

API Reference
-------------

[](#api-reference)

### `EmailValidator`

[](#emailvalidator)

MethodDescription`create(): self`Factory with the default bundled lists`withConfig(Configuration $c): self`Factory from a configuration object`fromConfigFile(string $path): self`Factory from a PHP/JSON/YAML config file`strict(): self` / `basic(): self`Factory from a preset`validate(string $email): ValidationResult`Full validation, rich result`isValid(string $email, ?bool $checkMX = null): bool`Boolean validation`validateBatch(array $emails): array`Batch → `ValidationResult[]``validateMultiple/validateWithDetails/filterValid/filterInvalid/getStatistics`2.x-compatible batch helpers`isValidFormat/isDisposable/hasValidMX/hasValidDNS`Individual checks`isRoleBased/isSubaddressed/getBaseEmail/getSuggestion/isCatchAll/validateSMTP`Advanced checks`extractDomain/extractLocalPart/normalize/normalizeMultiple`Utilities`addToBlocklist/addToAllowlist/removeFrom*/getBlocklist/getAllowlist/…`List management (fluent)`setConfiguration/getConfiguration/setLogger/setCacheEnabled/clearCache`Configuration &amp; runtime### `ConfigurationBuilder`

[](#configurationbuilder)

`create()`, presets `strict()/standard()/basic()/minimal()`, cache `withMemoryCache/withFileCache/withRedisCache/withMemcachedCache/withPsr16Cache/withCache/withoutCache`, `withRateLimiting/withoutRateLimiting`, checks `withRoleBasedCheck/withTypoSuggestion/withSmtpCheck/withSubaddressCheck/withCatchAllCheck/withoutMxCheck/withoutDisposableCheck`, lists `withBlocklist/withAllowlist`, and `build()`.

### `ValidationResult`

[](#validationresult)

`isValid, getEmail, getDomain, getLocalPart, getChecks, passed, getErrors, getFirstError, getWarnings, isDisposable, isRoleBased, isSubaddressed, getMetadata, getMetadataValue, hasSuggestion, getSuggestion, toArray, toJson`.

### `SuggestionResult`

[](#suggestionresult)

`getOriginalEmail, getSuggestedEmail, getOriginalDomain, getSuggestedDomain, getReason, getConfidence, isHighConfidence, toArray, __toString`.

### `Fetcher`

[](#fetcher)

`loadBlocklist, loadAllowlist, loadAll, loadCustomBlocklist, loadCustomAllowlist, mergeLists, saveList, clearCache, getBlocklistPath, getAllowlistPath, blocklistExists, allowlistExists, getBlocklistCount, getAllowlistCount`.

---

Exceptions
----------

[](#exceptions)

All exceptions extend `HarunGecit\EmailValidator\Exceptions\EmailValidatorException`:

ExceptionWhen`RateLimitExceededException`Rate limit exceeded (`getRetryAfter()`, `getMaxAttempts()`)`InvalidEmailException`Semantic validation failures (factory helpers per reason)`ConfigurationException`Invalid config value, unsupported format, missing file`CacheException`Cache driver/backend errors`SmtpConnectionException`SMTP connection/timeout/unexpected-response errors---

Testing
-------

[](#testing)

```
composer test           # run the suite
composer test-coverage  # HTML coverage report in ./coverage
```

> The test toolchain uses PHPUnit 10+ and therefore requires PHP 8.1+. The library runtime supports PHP 8.0+ (verified by a dedicated CI job).

---

Upgrading to 3.0
----------------

[](#upgrading-to-30)

3.0 is **backward compatible** with the 2.x public API — existing code using `isValid()`, `validateWithDetails()`, `validateMultiple()`, `filterValid()`, list management, and `EmailValidator::create()` continues to work unchanged.

What's new / worth knowing:

- **Minimum PHP is now 8.0** (2.x supported 7.4). Language features used in 3.0 require 8.0+.
- **New rich API:** `validate()` returns a `ValidationResult` object instead of an array; the array-based `validateWithDetails()` is still available.
- **Configuration &amp; presets:** prefer `ConfigurationBuilder` and the `strict/standard/basic/minimal` presets over ad-hoc setters.
- **New checks:** role-based, subaddress, typo suggestion, SMTP, and catch-all (all opt-in).
- **Pluggable cache &amp; rate limiting** replace the simple 2.x MX cache toggle (which still works).
- **Framework packages:** Laravel and Symfony integrations are now included.

Coming from **1.x**? The namespace changed from `PHPOrbit\EmailValidator` to `HarunGecit\EmailValidator`, and the package from `phporbit/php-email-validator` to `harungecit/php-email-validator`.

---

Contributing
------------

[](#contributing)

Contributions are welcome:

1. Fork the repository and create a feature branch.
2. Make your changes with tests.
3. Ensure `composer test` passes and code follows PSR-12 with PHPDoc comments.
4. Submit a pull request.

---

License
-------

[](#license)

Licensed under the MIT License. See [LICENSE](LICENSE) for details.

---

Author
------

[](#author)

**Harun Geçit**

- [GitHub](https://github.com/harungecit)
- [LinkedIn](https://linkedin.com/in/harungecit)
- [Email](mailto:info@harungecit.com)

---

Changelog
---------

[](#changelog)

### v3.0.0

[](#v300)

- **Requires PHP 8.0+** (dropped 7.4). Forward-compatible through PHP 8.5.
- Added a rich `ValidationResult` object returned by the new `validate()` method, plus `validateBatch()`.
- Added `Configuration` and a fluent `ConfigurationBuilder` with `strict`, `standard`, `basic`, and `minimal` presets.
- Added configuration file loading (PHP / JSON / YAML) via `EmailValidator::fromConfigFile()`.
- Added new checks: role-based detection, subaddress (plus addressing), typo suggestions (`SuggestionResult`), SMTP verification, and catch-all detection.
- Added a pluggable cache layer with Memory, File, Redis, Memcached, PSR-16, and Null adapters.
- Added token-bucket rate limiting with `RateLimitExceededException`.
- Added PSR-3 logging support.
- Added Laravel (service provider, facade, publishable config, validation rules) and Symfony (bundle, DI extension) integrations.
- Updated the disposable blocklist to 7,900+ domains, synchronized with the [disposable-email-domains](https://github.com/disposable-email-domains/disposable-email-domains) project.
- Fully backward compatible with the 2.x public API.

### v2.0.0

[](#v200)

- **Breaking:** Namespace changed from `PHPOrbit\EmailValidator` to `HarunGecit\EmailValidator`.
- **Breaking:** Package name changed from `phporbit/php-email-validator` to `harungecit/php-email-validator`.
- Added batch validation (`validateMultiple`, `filterValid`, `filterInvalid`), `isValid()`, `validateWithDetails()`, `getStatistics()`, and the `EmailValidator::create()` factory.
- Added a fluent interface for list management, MX record caching, `hasValidDNS()`, email normalization, and `isAllowlisted()`/`isBlocklisted()`.
- Enhanced the `Fetcher` with caching, custom list loading, and merge capabilities.
- Added multi-platform CI (Ubuntu, Windows, macOS).

### v1.0.x

[](#v10x)

- Initial releases: email format validation, disposable email detection, and MX record validation.

###  Health Score

45

—

FairBetter than 91% of packages

Maintenance93

Actively maintained with recent releases

Popularity20

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~110 days

Recently: every ~137 days

Total

6

Last Release

23d ago

Major Versions

1.0.2 → 2.0.02025-12-15

2.0.0 → v3.0.02026-07-08

PHP version history (2 changes)1.0.1PHP &gt;=7.4

v3.0.0PHP &gt;=8.0

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/37879288?v=4)[Harun Geçit](/maintainers/harungecit)[@harungecit](https://github.com/harungecit)

---

Top Contributors

[![harungecit](https://avatars.githubusercontent.com/u/37879288?v=4)](https://github.com/harungecit "harungecit (23 commits)")

---

Tags

disposabledisposable-emaildisposable-emailsemailemail-validatoremailvalidatorphpphp-disposable-emailphp-disposable-email-validatorvalidatorphpvalidatorvalidationemailconfigurablerate limitingdisposableemail-verificationemail validatorspam protectionblocklistrole basedallowlistmx-recordtypo-suggestionsmtp-verification

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/harungecit-php-email-validator/health.svg)

```
[![Health](https://phpackages.com/badges/harungecit-php-email-validator/health.svg)](https://phpackages.com/packages/harungecit-php-email-validator)
```

###  Alternatives

[laravel/framework

The Laravel Framework.

34.9k556.2M21.5k](/packages/laravel-framework)[cakephp/cakephp

The CakePHP framework

8.9k20.0M1.9k](/packages/cakephp-cakephp)[algolia/algoliasearch-client-php

API powering the features of Algolia.

69735.8M179](/packages/algolia-algoliasearch-client-php)[flow-php/flow

PHP ETL - Extract Transform Load - Data processing framework

86337.5k](/packages/flow-php-flow)[civicrm/civicrm-core

Open source constituent relationship management for non-profits, NGOs and advocacy organizations.

762297.9k53](/packages/civicrm-civicrm-core)[mimmi20/browser-detector

Library to detect Browsers and Devices

49158.4k5](/packages/mimmi20-browser-detector)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
