Download the PHP package harungecit/php-email-validator without Composer
On this page you can find all versions of the php package harungecit/php-email-validator. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download harungecit/php-email-validator
More information about harungecit/php-email-validator
Files in harungecit/php-email-validator
Package php-email-validator
Short Description The most complete email validation and disposable email detection library for PHP: 136,000+ disposable domains (updated daily, false-positive filtered), MX/DNS, RFC & spoof checks, role-based and typo detection, SMTP verification. Framework-agnostic with first-class Laravel, Symfony, CodeIgniter 4, CakePHP, Yii 2/3 and Phalcon integrations.
License MIT
Homepage https://github.com/harungecit/php-email-validator
Informations about the package php-email-validator
- 137,600+ disposable domains from multiple sources — rebuilt daily, released weekly, and false-positive filtered (no
namecheap.com, noyandex.net, no ISP domains, no public suffixes). - Explainable results — which list entry matched, whether through a subdomain, and from which list.
- A full validation pipeline, not just a blocklist — RFC format modes, MX/DNS, homograph spoofing, role accounts, plus-addressing, typo suggestions, SMTP and catch-all.
- Every PHP framework, natively — validation rules, constraints, services and commands that feel at home in each framework.
- Fast — O(1) lookups (~2.5 µs, subdomains included); with OPcache the full domain index costs zero load time and per-request memory.
- No API keys, no per-request fees — everything runs locally; network is only used for the checks you enable (MX, SMTP) and for list syncs.
Table of Contents
- Why this package?
- Installation
- Quick start
- Disposable email detection
- The disposable domain list
- Keeping the list fresh (sync)
- Full validation pipeline
- Configuration
- Plain PHP
- Command line
- Performance
- Caching, rate limiting & logging
- Result objects & API reference
- Changelog
⭐ Why this package?
| php-email-validator | Typical disposable-list package | |
|---|---|---|
| Disposable domains | 137,600+ disposable domains, multi-source, daily rebuild | one source, a few thousand to ~100k |
| False-positive protection | Public Suffix List, popularity, typo & allowlist filters, regression tests | none — aggregated feeds are merged blindly |
Subdomain detection (x.mailinator.com) |
✅ (configurable) | sometimes |
| Explains matches (entry + source) | ✅ checkDisposable() |
rarely |
| Runtime sync between releases | ✅ append-only, atomic, locked, HTML-safe | sometimes |
| Format: filter / unicode / RFC 5322 / strict | ✅ | framework-dependent |
| MX / DNS, spoof (homograph), role-based, plus-addressing, typo suggestions | ✅ | ❌ |
| SMTP mailbox & catch-all verification | ✅ (opt-in) | ❌ |
| Frameworks | Laravel, Symfony, CodeIgniter 4, CakePHP, Yii 2, Yii 3, Phalcon, plain PHP | usually one |
| CLI | ✅ vendor/bin/email-validator |
framework-only, if any |
| Caching / rate limiting / PSR-3 logging | ✅ Memory, File, Redis, Memcached, PSR-16 | ❌ |
| PHP versions | 8.0 – 8.5 | varies |
Installation
Compatibility
- PHP 8.0 – 8.5 (runtime verified on 8.0; full test suite on 8.1 – 8.5), on Linux, Windows and macOS.
- Laravel 9 – 13 · Symfony 6.4 – 8.x · CodeIgniter 4.4+ · CakePHP 4.4+ / 5.x · Yii 2.0 · Yii 3 (yiisoft/validator 2.x) · Phalcon 5.
- Optional:
ext-intl(IDN + spoof check),egulias/email-validator(rfc/strictformat modes),ext-curl(sync),ext-redis/predis/predis/ext-memcached(cache backends),symfony/yaml(YAML config).
🚀 Quick start
Just need a disposable check, no network?
🛡 Disposable email detection
How a domain is matched
The domain and each of its parent domains are looked up, most specific first —
a.b.mailinator.com, b.mailinator.com, mailinator.com — so throwaway subdomains are caught too.
On each level the lists are consulted in this order (first hit wins):
| Priority | List | Source label |
|---|---|---|
| 1 | Your allowlist — lists.custom_allowlist, custom_allowlist_paths, addToAllowlist() |
allowlist |
| 2 | Your blocklist — lists.custom_blocklist, custom_blocklist_paths, addToBlocklist() |
custom |
| 3 | Bundled allowlist (237 legitimate providers, ISPs and privacy relays) | allowlist |
| 4 | Synced blocklist (lists.synced_blocklist_path) |
synced |
| 5 | Bundled blocklist (or your replacement via lists.blocklist_path) |
blocklist |
So your own decisions always win over the bundled data — e.g. you can block a privacy relay the package allows, or allow a domain the package blocks.
Lists can also be changed at runtime (fluent): addToBlocklist(), addToAllowlist(),
removeFromBlocklist(), removeFromAllowlist(), getBlocklist(), getBlocklistCount(),
isBlocklisted(), isAllowlisted(). Runtime changes never copy the shared index.
Privacy relays (Apple Hide My Email, Firefox Relay, DuckDuckGo, SimpleLogin, Proton Pass, addy.io) forward to a real inbox and are allowed by default. To block them, add them to your blocklist.
📚 The disposable domain list
The bundled list is rebuilt every day from multiple upstream projects and released as a patch
version every Monday, so a regular composer update keeps you current. Want daily freshness?
See sync.
| Source | Role | Treatment |
|---|---|---|
| disposable-email-domains | hand-curated, conservative | trusted — taken as-is |
| eramitgupta/disposable-email | large daily aggregator (several lists + StopForumSpam toxic domains) | untrusted — every entry is filtered |
data/blocklist.local.conf |
maintainers' additions | always included |
data/allowlist.conf |
legitimate domains | always excluded (with subdomains) |
Aggregated feeds contain real companies and ISPs that were once abused by spammers. Blindly merging
them would block e.g. namecheap.com, yandex.net, sutterhealth.org, Roadrunner/Spectrum ISP
addresses (nyc.rr.com) or entire country zones (msk.ru, pp.ua). The build therefore drops:
| Filter | Applies to | Example of what it prevents |
|---|---|---|
| Invalid syntax / upstream merge artifacts | all / untrusted | btcmail.pwguerrillamail.net (two lines glued together) |
| Public Suffix List entries | all | msk.ru, pp.ua, it.com — would block every domain below them |
| Allowlisted domains and their subdomains | all | vip.126.com, simplelogin.co, nyc.rr.com |
| Tranco top-100k popular domains | untrusted only | namecheap.com, compaq.com, cafe24.com |
| Typos of major providers | untrusted only | gamil.com → handled by typo suggestions instead of a misleading "disposable" error |
On top of that the build refuses to shrink the list by more than 5% in one run, switches to an
additive (remove-nothing) mode if an untrusted source is down, and CI keeps regression tests for
known false positives. Build details live in data/metadata.json and in the
output of email-validator stats.
Found a missing domain or a false positive? See CONTRIBUTING.md — fixes are permanent.
🔄 Keeping the list fresh (sync)
Package releases are weekly; the list on main is rebuilt daily. The synchronizer downloads
remote lists into a file in your app, and every validator configured with that file blocks those
domains too — no deploy needed.
Schedule it (cron, Laravel scheduler, Symfony scheduler, …):
By default the synchronizer downloads this package's own filtered list from main
(Configuration::DEFAULT_SYNC_URL), so you get the same false-positive protection.
Use --url= (repeatable) or the sync.urls setting to add other plain-text or JSON lists.
Safeguards — a bad download never damages your last good list:
- failed requests, non-2xx responses, HTML error pages, empty responses and lists without a single valid domain are rejected before anything is written;
- append-only by default;
--replaceonly drops domains when every source succeeded; - allowlisted domains (bundled + yours, including subdomains) are never written;
- only domains that are not already bundled are stored, so the file stays tiny and cheap to load;
- writes go to a temp file that is atomically renamed, under an exclusive lock; an unchanged list is not rewritten.
Programmatic use:
🔬 Full validation pipeline
validate() runs every enabled check and returns a ValidationResult:
| Check | Default | What it does |
|---|---|---|
format |
✅ | Syntax — see format modes |
spoof |
❌ | Mixed-script / invisible characters per address part (needs ext-intl) |
disposable |
✅ | Bundled + custom + synced lists, subdomain-aware |
mx |
✅ | MX records (checkdnsrr), cached per domain |
role_based |
❌ | admin@, info@, support@, … (configurable prefixes) |
subaddress |
❌ | Plus addressing user+tag@ (warning + base_email metadata) |
smtp |
❌ | Live mailbox check (RCPT TO) — slow, may be blocked |
catch_all |
❌ | Detects domains that accept every address |
typo_suggestion |
❌ | "Did you mean gmail.com?" — never fails validation |
Presets
| Preset | Enabled checks |
|---|---|
minimal() |
format |
basic() |
format, disposable |
standard() |
format, mx, disposable, typo suggestion |
strict() |
format, mx, disposable, role-based, subaddress, typo suggestion, smtp, catch-all |
strict()enables SMTP and catch-all verification, which open live connections and can be slow or blocked. For most applicationsstandard()is the recommended starting point.
Format modes
| Mode | Engine | Accepts |
|---|---|---|
filter (default) |
FILTER_VALIDATE_EMAIL |
ASCII addresses |
filter_unicode |
FILTER_VALIDATE_EMAIL + FILTER_FLAG_EMAIL_UNICODE |
internationalized local parts (jö[email protected]) |
rfc |
egulias/email-validator RFCValidation |
everything RFC 5322 allows |
strict |
egulias/email-validator NoRFCWarningsValidation |
RFC 5322 without warnings (no quoted local parts, …) |
Spoofing (homograph) detection
Individual checks
Batch validation
⚙ Configuration
Use the fluent builder, an array, or a PHP/JSON/YAML file — they all produce a Configuration.
Ready-made templates: config/emailvalidator.json.
All configuration keys
| Key | Default | Description | |---|---|---| | `checks.format` / `mx` / `disposable` | `true` | Core checks | | `checks.role_based` / `smtp` / `typo_suggestion` / `subaddress` / `catch_all` / `spoof` | `false` | Optional checks | | `format.mode` | `filter` | `filter`, `filter_unicode`, `rfc`, `strict` | | `lists.blocklist_path` / `allowlist_path` | `null` | **Replace** the bundled lists | | `lists.custom_blocklist` / `custom_allowlist` | `[]` | Domains **added** to the lists (take precedence over bundled lists) | | `lists.custom_blocklist_paths` / `custom_allowlist_paths` | `[]` | Extra list files or directories | | `lists.synced_blocklist_path` | `null` | File maintained by `sync` (ignored until it exists) | | `lists.block_subdomains` | `true` | Match parent domains (`x.mailinator.com` → `mailinator.com`) | | `lists.role_based_path` | `null` | Custom role-prefix list file | | `sync.urls` | package list on `main` | Remote lists for `sync` (text or JSON, http/https only) | | `sync.timeout` | `30` | HTTP timeout in seconds | | `cache.driver` / `ttl` / `prefix` / `options` | `memory`, `3600` | `memory`, `file`, `redis`, `memcached`, `psr16`, `null` | | `rate_limit.enabled` / `max_attempts` / `decay_seconds` | `false`, `100`, `60` | Token-bucket limiter | | `role_based.prefixes` | 36 prefixes | Role-account local parts | | `typo.common_domains` / `typo.mappings` | major providers | Typo suggestion data | | `smtp.timeout` / `from_email` / `from_domain` | `10`, `null`, `null` | SMTP verification | | `dns.timeout` | `5` | DNS timeout |🧩 Framework integrations
Every integration wraps the same core, so behaviour and configuration keys are identical everywhere.
| Framework | Validation | Services | Commands / sync | Extras |
|---|---|---|---|---|
| Laravel 9–13 | rule objects + string rules | facade, container | Artisan, scheduler | Blade directive, translations, Laravel Boost |
| Symfony 6.4–8 | #[NotDisposableEmail], #[ValidEmail], #[NotRoleBasedEmail] |
autowiring | bin/console |
YAML config, Scheduler |
| CodeIgniter 4.4+ | auto-registered rules | service('emailValidator') |
CLI + cron | zero-config discovery, .env |
| CakePHP 4.4+/5 | validation provider | DI plugin | CLI + cron | Configure key |
| Yii 2 | model validators | app component | CLI + cron | aliases, Yii::t() messages |
| Yii 3 | attribute rules | DI container | CLI + cron | — |
| Phalcon 5 | validators | DI service provider | CLI + cron | config service section |
Laravel
Supports Laravel 9–13 (rule objects need Laravel 10+). The service provider and the EmailValidator facade are auto-discovered.
Validation rules
Messages live in the emailvalidator::validation translation group (php artisan vendor:publish --tag=emailvalidator-translations).
Rule-object messages accept :attribute; NotDisposableEmail also :domain and :matched, ValidEmail also :reason and :suggestion.
Facade, Blade & commands
Configuration (config/emailvalidator.php, env-aware; the cache driver defaults to your Laravel cache store):
Set EMAIL_VALIDATOR_SYNC_SCHEDULE=daily and the package registers email-validator:sync on Laravel's scheduler (withoutOverlapping()).
AI agents using Laravel Boost get this package's guidelines automatically.
Symfony
Supports Symfony 6.4, 7.x and 8.x.
Message parameters: {{ value }}, {{ domain }}, {{ matched }} (NotDisposableEmail); {{ check }}, {{ reason }}, {{ suggestion }} (ValidEmail), with one error code per failed check.
Services: EmailValidator (autowirable, alias email_validator), Configuration, ListSynchronizer (email_validator.synchronizer).
CodeIgniter 4
Zero configuration. CodeIgniter's auto-discovery picks up the package's Config/Registrar.php and Config/Services.php:
the rules are added to Config\Validation::$ruleSets and service('emailValidator') returns a shared validator.
| Rule | Fails when |
|---|---|
not_disposable_email |
the domain (or a parent domain) is disposable |
email_has_mx |
the domain has no MX record |
not_role_based_email |
the address is a role account (admin@, info@, …) |
not_subaddressed_email |
the address has a +tag |
not_spoofed_email |
it mixes scripts or has invisible characters (needs ext-intl) |
verified_email |
the full configured pipeline fails; the message names the failed check |
Messages ship as language lines ({field}, {value} and per-field custom errors work); override them in
app/Language/<locale>/Validation.php. Use permit_empty for optional fields.
To configure, create app/Config/EmailValidator.php (properties mirror the configuration keys; .env overrides such as
emailvalidator.checks.mx = false work too):
Discovery disabled? Add \HarunGecit\EmailValidator\Framework\CodeIgniter\EmailValidatorRules::class to Config\Validation::$ruleSets.
Sync from cron: vendor/bin/email-validator sync --path=writable/email-validator/synced.conf.
CakePHP
Rules: notDisposable, notRoleBased, notSubaddressed, notSpoofed, hasMx, verifiedEmail (full pipeline).
Manual use works as with any provider: ->setProvider('emailValidator', new EmailValidationProvider())->add('email', 'notDisposable', ['rule' => 'notDisposable', 'provider' => 'emailValidator']).
Register the plugin to get EmailValidator/Configuration in the DI container, configured from the EmailValidator key:
Yii 2
Messages support {attribute}, {value}, {domain}, {matched} (and {check}, {error}, {suggestion} for VerifiedEmailValidator) and go through Yii::t('app', …).
Yii 3
Handlers receive EmailValidator from the DI container — register it with your configuration:
Phalcon 5
Plain PHP / any framework
The core has no framework dependency: create an EmailValidator, keep it in your container, and
use vendor/bin/email-validator sync from cron. Slim, Mezzio, Laminas, Lumen, Nette, Spiral,
WordPress plugins — anything with Composer works.
💻 Command line
Exit codes: 0 = nothing flagged, 1 = disposable/invalid found or sync failed, 2 = usage error —
handy for shell scripts and CI (e.g. validating a CSV export).
⚡ Performance
- Lookups are O(1) hash lookups; a check including the parent-domain walk takes ~2.5 µs.
- With OPcache (every production PHP-FPM setup) the precompiled
data/blocklist.phpindex is an immutable array in shared memory: loading the whole list costs nothing and adds no per-request memory. - Without OPcache (CLI, workers) the list is read with a single
explode()in ~18 ms, once per process. - Runtime list changes (
addToBlocklist(), custom/synced lists) are kept in small side tables, so the shared index is never copied. - MX and catch-all results are cached through the configured cache backend.
Caching, rate limiting & logging
Rate limiting throttles validations per address with a token bucket that shares the cache backend (works across processes with Redis/Memcached/File):
PSR-3 logging: $validator->setLogger($logger) or $config->setLogger($logger) — each validate()
logs a debug entry with the outcome, checks and errors.
📖 Result objects & API reference
ValidationResult
`isValid, getEmail, getDomain, getLocalPart, getChecks, passed(check), getErrors, getFirstError, getWarnings, isDisposable, isRoleBased, isSubaddressed, getMetadata, getMetadataValue, hasSuggestion, getSuggestion, toArray, toJson`. Metadata keys: `disposable_match`, `disposable_source`, `subaddressed`, `base_email`.DisposableCheckResult
`getInput, getDomain, isDisposable, getMatchedDomain, getSource, isAllowlisted, isSubdomainMatch, toArray, jsonSerialize`. Source constants: `SOURCE_BLOCKLIST`, `SOURCE_CUSTOM`, `SOURCE_SYNCED`, `SOURCE_ALLOWLIST`.SuggestionResult
`getOriginalEmail, getSuggestedEmail, getOriginalDomain, getSuggestedDomain, getReason, getConfidence, isHighConfidence, toArray, __toString`.EmailValidator
| Method | Description | |--------|-------------| | `create()` / `withConfig($c)` / `fromConfigFile($path)` / `strict()` / `basic()` | Factories | | `validate($email): ValidationResult` | Full pipeline | | `isValid($email, ?bool $checkMX = null): bool` | Boolean validation | | `validateBatch($emails)` | `arrayConfigurationBuilder
Presets `strict/standard/basic/minimal`; cache `withMemoryCache/withFileCache/withRedisCache/withMemcachedCache/withPsr16Cache/withCache/withoutCache`; `withRateLimiting/withoutRateLimiting`; checks `withRoleBasedCheck/withTypoSuggestion/withSmtpCheck/withSubaddressCheck/withCatchAllCheck/withSpoofCheck/withoutMxCheck/withoutDisposableCheck`; format `withFormatMode`; lists `withBlocklist/withAllowlist/withCustomBlocklist/withCustomAllowlist/withCustomBlocklistFiles/withCustomAllowlistFiles/withSyncedBlocklist/withoutSubdomainBlocking`; `build()`.Fetcher (list files)
`loadBlocklist, loadAllowlist, loadAll, loadBlocklistIndex, loadAllowlistIndex, loadCustomBlocklist, loadCustomAllowlist, loadPaths, mergeLists, saveList, compileIndex, getMetadata, clearCache, getBlocklistPath, getBlocklistIndexPath, getAllowlistPath, getMetadataPath, blocklistExists, allowlistExists, getBlocklistCount, getAllowlistCount, isOpcacheActive`.Exceptions
All extend `HarunGecit\EmailValidator\Exceptions\EmailValidatorException`: `RateLimitExceededException` (`getRetryAfter()`, `getMaxAttempts()`), `InvalidEmailException`, `ConfigurationException` (invalid value, unsupported format, missing file or dependency), `CacheException`, `SmtpConnectionException`.Testing
The library runs on PHP 8.0+; the test suite needs PHP 8.1+ (PHPUnit 10–12). CI runs PHP 8.1 – 8.5 on Ubuntu, Windows and macOS, the oldest supported framework versions on PHP 8.1, a PHP 8.0 runtime smoke test, and data-integrity checks on every push.
Upgrading
3.2 is backward compatible with 3.0/3.1 and the 2.x API. Worth knowing:
- The bundled list grew from ~8,900 to over 136,000 domains in 3.2.0. If a legitimate domain your users rely
on is now flagged, add it to
lists.custom_allowlistand report it. - Your
custom_blocklist/addToBlocklist()entries now override the bundled allowlist (previously the allowlist always won). The bundled blocklist still never overrides the allowlist. EmailValidator::create()now shares the precompiled index instead of copying the list.- List files written by
Fetcher::saveList()end with a newline.
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
Contributions are welcome — missing disposable domains, false-positive reports, framework integrations and docs. Please read CONTRIBUTING.md; security issues go through SECURITY.md.
License
MIT — see LICENSE. The disposable domain data is derived from disposable-email-domains (CC0) and eramitgupta/disposable-email (MIT); thanks to their maintainers and to the Public Suffix List and Tranco projects.
Author
Harun Geçit — GitHub · LinkedIn · Email
If this package saves you from fake sign-ups, please ⭐ the repository — it helps other PHP developers find it.
Changelog
Automated weekly data releases (blocklist updates) are documented on the Releases page.
v3.2.0
- 136,577 disposable domains at release (up from 8,948): the blocklist is now built from disposable-email-domains (trusted) and eramitgupta/disposable-email (filtered aggregator).
- False-positive filtering in the build: Public Suffix List, Tranco top-100k, typo domains, allowlist subdomains and upstream merge artifacts; allowlist expanded to 237 domains (ISPs, organisations, privacy relays such as SimpleLogin and Proton Pass).
- The list is rebuilt daily on
main; patch releases still ship every Monday (skipped automatically whenmainhas unreleased code). - New
checkDisposable()returningDisposableCheckResult(matched domain, source, subdomain match),isDisposableDomain(),isSpoofed()andgetListStatistics();validate()addsdisposable_match/disposable_sourcemetadata. - New configuration:
lists.custom_blocklist,custom_allowlist,custom_*_paths,synced_blocklist_path,block_subdomains,sync.urls,sync.timeout,format.mode(filter,filter_unicode,rfc,strict) and thespoofcheck. - New list synchronizer (
ListSynchronizer) with append-only/replace modes, HTML/empty-response rejection, allowlist filtering, atomic writes and locking. - New framework-agnostic CLI:
vendor/bin/email-validator check|validate|sync|stats. - Precompiled OPcache index (
data/blocklist.php): zero load cost and no per-request memory with OPcache; runtime list changes no longer copy the list. - Domain normalization (case, trailing dot, IDN → punycode) for every list lookup.
- New integrations: CodeIgniter 4 (auto-discovered rules + service), CakePHP (validation provider + plugin), Yii 2 (component + validators), Yii 3 (attribute rules), Phalcon 5 (validators + service provider).
- Laravel: rule objects,
not_spoofedrule,@disposableEmailBlade directive, Artisan commands, scheduled sync, Laravel Boost guidelines. Symfony:#[NotDisposableEmail]/#[ValidEmail]constraints and console commands. Laravel 13 and Symfony 8 support. - Application lists (
custom_*) now take precedence over the bundled allowlist. - Added CONTRIBUTING.md and SECURITY.md; leaner Composer dist archive.
v3.1.1
- Updated the disposable blocklist to 8,900+ domains (785 new domains from upstream).
isDisposable()now detects subdomains of disposable providers ([email protected]) by also checking parent domains; the most specific list entry wins. Lookups use a hash index instead of a linear scan.- Added a scheduled GitHub Actions workflow that refreshes the blocklist weekly and publishes a patch release automatically.
composer update-listsnow rebuilds the blocklist asupstream + data/blocklist.local.conf − allowlistinstead of a keep-everything union, so upstream false-positive removals are applied (removedgmal.com,iwi.net,mailhub.pro). Added safety checks for unattended runs (malformed lines skipped, abort on a suspiciously small upstream or a >5% shrink;--forceoverrides).
v3.1.0
- Updated the disposable blocklist to 8,100+ domains (244 new domains from the disposable-email-domains project).
- Expanded the allowlist to 190+ domains (added
proton.me,pm.me,hey.com,tuta.com,zohomail.com,icloud.com,duck.com,simplelogin.io,addy.io, and more). The upstream allowlist was discontinued; it is now maintained in this package. - Added
composer update-lists(scripts/update-lists.php) to refresh the blocklist from upstream with a single command. - Expanded the default typo mappings and common-domain list (Proton, Tuta, HEY, Zoho Mail, GMX, Yandex, and regional Yahoo/Hotmail/Outlook domains) and synchronized them across all config templates.
- Expanded the default role-based prefixes (
administrator,donotreply,security,privacy,legal,compliance,notifications, and more). Fetcher::saveList()now always writes LF line endings regardless of platform.
v3.0.1
- Fixed CI failures on PHP 8.0 and 8.1.
v3.0.0
- Requires PHP 8.0+ (dropped 7.4). Forward-compatible through PHP 8.5.
- Added a rich
ValidationResultobject returned by the newvalidate()method, plusvalidateBatch(). - Added
Configurationand a fluentConfigurationBuilderwithstrict,standard,basic, andminimalpresets. - 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 project.
- Fully backward compatible with the 2.x public API.
v2.0.0
- Breaking: Namespace changed from
PHPOrbit\EmailValidatortoHarunGecit\EmailValidator. - Breaking: Package name changed from
phporbit/php-email-validatortoharungecit/php-email-validator. - Added batch validation (
validateMultiple,filterValid,filterInvalid),isValid(),validateWithDetails(),getStatistics(), and theEmailValidator::create()factory. - Added a fluent interface for list management, MX record caching,
hasValidDNS(), email normalization, andisAllowlisted()/isBlocklisted(). - Enhanced the
Fetcherwith caching, custom list loading, and merge capabilities. - Added multi-platform CI (Ubuntu, Windows, macOS).
v1.0.x
- Initial releases: email format validation, disposable email detection, and MX record validation.
All versions of php-email-validator with dependencies
ext-filter Version *
psr/log Version ^1.0|^2.0|^3.0
psr/simple-cache Version ^1.0|^2.0|^3.0