I bet every developer who is reading this tutorial is starting off with the premise that email address validation is easy and they have a one-liner that does the job. And that probably is true. I say probably because most developers assume an email address being in a recognizable format is all it takes to be considered valid. But if the company’s success is tied to email marketing and bogus email addresses are accepted because they meet that simple criteria, is your email validation really doing its job? Confirming that a user can receive emails at the email address they provided, and that they can continue to do so for a reasonable time after their interaction with your website, is a far better validation for said email marketing company that something that looks to be correct.
The Email Validator library builds upon PHP’s built in filter_var($emailAddress, FILTER_VALIDATE_EMAIL);
by adding a default MX record check. It also offers additional validation against disposable email addresses, free email address providers, and a custom banned domain list.
Requirements
- PHP 7.2 or newer
Installation
To add PHP Email Validation to your project, add a dependency on stymiee/email-validator
to your project’s composer.json file if you use Composer to manage the dependencies of your project. Here is a minimal example of a composer.json file that just defines a dependency on PHP Email Validation:
"require": { "stymiee/email-validator": "^1" }
Including it in your project is then as simple as including your vendor autoload file:
require('./vendor/autoload.php');
Features
The PHP Email Validator will validate an email address for all or some of the following conditions:
- is in a valid format
- has configured MX records (optional)
- is not a disposable email address (optional)
- is not a free email account (optional)
- is not a banned email domain (optional)
The Email Validator is configurable, so you have full control over how much validation will occur.
Available Validations
-
Validate MX
If
checkMxRecords
is set totrue
in the configuration (see below) the domain name will be validated to ensure it exists and has MX records configured. If the domain does not exist or no MX records exist the odds are the email address is not in use. -
Restrict Disposable Email Addresses
Many users who are abusing a system, or not using that system as intended, can use a disposable email service who provides a short-lived (approximately 10 minutes) email address to be used for registrations or user confirmations. If
checkDisposableEmail
is set totrue
in the configuration (see below) the domain name will be validated to ensure it is not associated with a disposable email address provider.You can add you own domains to this list if you find the public list providers do not have one you have identified in their lists.
-
Restrict Free Email Address Providers
Many users who are abusing a system, or not using that system as intended, can use a free email service who provide a free email address which is immediately available to be used for registrations or user confirmations. If
checkFreeEmail
is set totrue
in the configuration (see below) the domain name will be validated to ensure it is not associated with a free email address provider.You can add you own domains to this list if you find the public list providers do not have one you have identified in their lists.
-
Restrict Banned Domains
If you have users from a domain abusing your system, or you have business rules that require the blocking of certain domains (i.e. public email providers like Gmail or Yahoo mail), you can block then by setting
checkBannedListedEmail
totrue
in the configuration (see below) and providing an array of banned domains.
Basic Usage
To use the Email Validator you need to configure it to validate according to your business rules. You can enable or disable checks and provide your own disposable email list and free domain lists providers as well as your own banned list. You then call the validate()
method on the email address you wish to validate.
Configuration
Email Validator takes an optional array of boolean key/value pairs which enable/disable package functionality. It also takes optional arrays of domains which can be provided to further filter email addresses based on specific criteria.
-
checkMxRecords
A boolean value that enables/disables MX record validation. Enabled by default.
-
checkBannedListedEmail
A boolean value that enables/disables banned domain validation. Disabled by default.
-
checkDisposableEmail
A boolean value that enables/disables disposable email address validation. Disabled by default.
-
checkFreeEmail
A boolean value that enables/disables free email address provider validation. Disabled by default.
-
localDisposableOnly
A boolean value that when set to
true
will not retrieve third party disposable email provider lists. Use this if you cache the list of providers locally which is useful when performance matters. Disabled by default. -
localFreeOnly
A boolean value that when set to
true
will not retrieve third party free email provider lists. Use this if you cache the list of providers locally which is useful when performance matters. Disabled by default. -
bannedList
An array of domains that are not allowed to be used for email addresses.
-
disposableList
An array of domains that are suspected disposable email address providers.
-
freeList
An array of domains that are free email address providers.
Below are some sample configurations.
Using default settings
// No configuration is passed to the EmailValidator Constructor $emailValidator = new EmailValidator();
Validating against disposable and free email provider lists (no caching)
$config = [ 'checkDisposableEmail' => true, 'checkFreeEmail' => true, ]; $emailValidator = new EmailValidator($config);
Disposable email list with custom domains
$customDisposableEmailList = [ 'example.com', ]; $config = [ 'checkDisposableEmail' => true, 'disposableList' => $customDisposableEmailList, ]; $emailValidator = new EmailValidator($config);
Simple Example
$emailValidator = new EmailValidator(); $emailIsValid = $emailValidator->validate('user@example.com');
A More Robust Example
use EmailValidator\EmailValidator; require('../vendor/autoload.php'); $customDisposableEmailList = [ 'example.com', ]; $customFreeEmailList = [ 'example2.com', ]; $bannedDomainList = [ 'domain.com', ]; $testEmailAddresses = [ 'test@johnconde.net', 'test@gmail.com', 'test@hotmail.com', 'test@outlook.com', 'test@yahoo.com', 'test@domain.com', 'test@mxfuel.com', 'test@example.com', 'test@example2.com', 'test@nobugmail.com', 'test@cellurl.com', 'test@10minutemail.com', ]; $config = [ 'checkMxRecords' => true, 'checkBannedListedEmail' => true, 'checkDisposableEmail' => true, 'checkFreeEmail' => true, 'bannedList' => $bannedDomainList, 'disposableList' => $customDisposableEmailList, 'freeList' => $customFreeEmailList, ]; $emailValidator = new EmailValidator($config); foreach($testEmailAddresses as $emailAddress) { $emailIsValid = $emailValidator->validate($emailAddress); echo ($emailIsValid) ? 'Email is valid' : $emailValidator->getErrorReason(); echo PHP_EOL; }
Outputs:
Email is valid Domain is used by free email providers Domain is used by free email providers Domain is used by free email providers Domain is used by free email providers Domain is banned Domain is used by disposable email providers Domain is used by free email providers Domain is used by disposable email providers Domain does not accept email Domain is used by disposable email providers Domain is used by disposable email providers
Caching Remote Content
Some of the features of the Email Validator require retrieving files from Github. The files contain lists of disposable or free email address providers and are regularly updated. However, retrieving and parsing these lists for every email address is both slow and unnecessarily repetitive. Although these lists are regularly updated, that frequency is in terms of days and not minutes or hours. A list retrieved an hour ago is still valid and accurate the most likely are few or no new records added since you last retrieve that list.
If you plan to take advantage of this functionality it is recommended that you cache these lists and refresh them periodically. Once per day during low volume of usage should be sufficient. The code below shows how you can get these lists
use EmailValidator\Policy; use EmailValidator\Validator\DisposableEmailValidator; require('../vendor/autoload.php'); $disposableEmailList = (new DisposableEmailValidator(new Policy()))->getList(); $freeEmailList = (new FreeEmailValidator(new Policy()))->getList();
$disposableEmailList
and $freeEmailList
each contain an array of domains, disposable and free email providers respectively, that you can store in memory for faster access. You then can use these cached copies of those lists without making HTTP calls by configuring the Email Validator to use only your local copies.
$config = [ 'localDisposableOnly'=> true, 'localFreeOnly' => true, 'disposableList' => $customDisposableEmailList, 'freeList' => $customFreeEmailList, ]; $emailValidator = new EmailValidator($config);
Help & Support
If you require assistance using this library start by viewing the HELP.md file included in this package. It includes common problems and their solutions.
If you continue to have difficulty using this code please do not contact me through this website. Since this software is free to the community, the community can assist me in supporting it. I am an active participant at Stack Overflow. Others also frequent it who are also capable of assisting you with this code. When posting your question there, or anywhere for that matter, be sure to include the following:
- A link to either this article and/or the GitHub repository so others can see what software you are using and can download it if necessary so if they attempt to reproduce the problem you are having.
- Your code as it is implemented in your software. Make sure you format it so it is readable by others.
- A description of what you are expecting your code to do (but it is not happening).
- Any error message you are getting.