{"id":719,"date":"2020-08-02T08:07:34","date_gmt":"2020-08-02T12:07:34","guid":{"rendered":"https:\/\/www.johnconde.net\/blog\/?p=719"},"modified":"2023-01-05T17:55:55","modified_gmt":"2023-01-05T21:55:55","slug":"tutorial-php-email-address-validator","status":"publish","type":"post","link":"https:\/\/website-0f9bf4a4.hpx.ppi.temporary.site\/blog\/tutorial-php-email-address-validator\/","title":{"rendered":"Tutorial: PHP Email Address Validator"},"content":{"rendered":"\n<div class=\"note yellownote\">\n        <img loading=\"lazy\" decoding=\"async\" class=\"avatar photo githubicon\" src=\"\/images\/icons\/github.png\" alt=\"Github\" width=\"68\" height=\"68\"\/>If you find this tutorial and code useful, please take a moment to <a href=\"https:\/\/github.com\/stymiee\/email-validator\" rel=\"external\">star it on Github<\/a>. If you want to help develop it further, <a href=\"https:\/\/github.com\/stymiee\/email-validator\/fork\">fork it<\/a>.<\/p>\n<ul id=\"github-icons\">\n<li><iframe loading=\"lazy\" class=\"github-btn\" src=\"https:\/\/ghbtns.com\/github-btn.html?user=stymiee&amp;repo=email-validator&amp;type=watch&amp;count=true\" width=\"100px\" height=\"20px\" frameborder=\"0\" scrolling=\"0\" title=\"Watch stymiee\/email-validator on GitHub\"><\/iframe><\/li>\n<li><iframe loading=\"lazy\" class=\"github-btn\" src=\"https:\/\/ghbtns.com\/github-btn.html?user=stymiee&amp;repo=email-validator&amp;type=fork&amp;count=true\" width=\"98px\" height=\"20px\" frameborder=\"0\" scrolling=\"0\" title=\"Fork stymiee\/email-validator on GitHub\"><\/iframe><\/li>\n<li><iframe loading=\"lazy\" class=\"github-btn\" src=\"https:\/\/ghbtns.com\/github-btn.html?user=stymiee&amp;type=follow&amp;count=true\" frameborder=\"0\" scrolling=\"0\" width=\"170\" height=\"20\" title=\"Follow @stymiee on GitHub\"><\/iframe><\/li>\n<\/ul><\/div>\n<p>\n        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 <i>probably<\/i> because most developers assume an email address being in a recognizable format is all it takes to be considered valid. But if the company&#8217;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 <i>looks<\/i> to be correct.\n    <\/p>\n<p>\n        The Email Validator library builds upon PHP&#8217;s built in <code>filter_var($emailAddress, FILTER_VALIDATE_EMAIL);<\/code> 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.\n    <\/p>\n<div class=\"note yellownote\">\n        Be sure to read <a href=\"\/blog\/going-deeper-int\u2026dress-validation\">Going Deeper into Email Address Validation<\/a> to have a better understanding of the complexities of email validation.\n    <\/div>\n<h2>\n        Requirements<br \/>\n    <\/h2>\n<ul>\n<li>PHP 7.2 or newer<\/li>\n<\/ul>\n<h2>\n        Installation<br \/>\n    <\/h2>\n<p>\n        To add PHP Email Validation to your project, add a dependency on <code>stymiee\/email-validator<\/code> to your project&#8217;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:\n    <\/p>\n<pre lang=\"php\">\r\n\"require\": {\r\n    \"stymiee\/email-validator\": \"^1\"\r\n}\r\n    <\/pre>\n<p>\n        Including it in your project is then as simple as including your vendor autoload file:\n    <\/p>\n<pre lang=\"php\">\r\nrequire('.\/vendor\/autoload.php');\r\n    <\/pre>\n<h2>\n        Features<br \/>\n    <\/h2>\n<p>\n        The PHP Email Validator will validate an email address for all or some of the following conditions:\n    <\/p>\n<ul>\n<li>is in a valid format<\/li>\n<li>has configured MX records (optional)<\/li>\n<li>is not a disposable email address (optional)<\/li>\n<li>is not a free email account (optional)<\/li>\n<li>is not a banned email domain (optional)<\/li>\n<\/ul>\n<p>\n        The Email Validator is configurable, so you have full control over how much validation will occur.\n    <\/p>\n<h3>\n        Available Validations<br \/>\n    <\/h3>\n<ul>\n<li>\n            <b>Validate MX<\/b><\/p>\n<p>\n                If <code>checkMxRecords<\/code> is set to <code>true<\/code> 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.\n            <\/p>\n<\/li>\n<li>\n            <b>Restrict Disposable Email Addresses<\/b><\/p>\n<p>\n                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 <code>checkDisposableEmail<\/code> is set to <code>true<\/code> in the configuration (see below) the domain name will be validated to ensure  it is not associated with a disposable email address provider.\n            <\/p>\n<p>\n                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.\n            <\/p>\n<\/li>\n<li>\n            <b>Restrict Free Email Address Providers<\/b><\/p>\n<p>\n                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 <code>checkFreeEmail<\/code> is set to <code>true<\/code> in the configuration (see below) the domain name will be validated to ensure it is not associated with a free email address provider.\n            <\/p>\n<p>\n                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.\n            <\/p>\n<\/li>\n<li>\n            <b>Restrict Banned Domains<\/b><\/p>\n<p>\n                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 <code>checkBannedListedEmail<\/code> to <code>true<\/code> in the configuration (see below) and providing an array of banned domains.\n            <\/p>\n<\/li>\n<\/ul>\n<div class=\"note yellownote\">\n        Validated email addresses are checked against a list of known disposable and free email address providers (depending upon your configuration) which are aggregated from public disposable email address provider lists. This requires making HTTP requests to get the lists when validating  the address.\n    <\/div>\n<h2>\n        Basic Usage<br \/>\n    <\/h2>\n<p>\n        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 <code>validate()<\/code> method on the email address you wish to validate.\n    <\/p>\n<h3>\n        Configuration<br \/>\n    <\/h3>\n<p>\n        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.\n    <\/p>\n<ul>\n<li>\n            <b>checkMxRecords<\/b><\/p>\n<p>\n                A boolean value that enables\/disables MX record validation. Enabled by default.\n            <\/p>\n<\/li>\n<li>\n            <b>checkBannedListedEmail<\/b><\/p>\n<p>\n                A boolean value that enables\/disables banned domain validation. Disabled by default.\n            <\/p>\n<\/li>\n<li>\n            <b>checkDisposableEmail<\/b><\/p>\n<p>\n                A boolean value that enables\/disables disposable email address validation. Disabled by default.\n            <\/p>\n<\/li>\n<li>\n            <b>checkFreeEmail<\/b><\/p>\n<p>\n                A boolean value that enables\/disables free email address provider validation. Disabled by default.\n            <\/p>\n<\/li>\n<li>\n            <b>localDisposableOnly<\/b><\/p>\n<p>\n                A boolean value that when set to <code>true<\/code> 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.\n            <\/p>\n<\/li>\n<li>\n            <b>localFreeOnly<\/b><\/p>\n<p>\n                A boolean value that when set to <code>true<\/code> 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.\n            <\/p>\n<\/li>\n<li>\n            <b>bannedList<\/b><\/p>\n<p>\n               An array of domains that are not allowed to be used for email addresses.\n            <\/p>\n<\/li>\n<li>\n            <b>disposableList<\/b><\/p>\n<p>\n                An array of domains that are suspected disposable email address providers.\n            <\/p>\n<\/li>\n<li>\n            <b>freeList<\/b><\/p>\n<p>\n                An array of domains that are free email address providers.\n            <\/p>\n<\/li>\n<\/ul>\n<p>\n        Below are some sample configurations.\n    <\/p>\n<h4>\n        Using default settings<br \/>\n    <\/h4>\n<pre lang=\"php\">\r\n\/\/ No configuration is passed to the EmailValidator Constructor\r\n$emailValidator = new EmailValidator();\r\n    <\/pre>\n<h4>\n        Validating against disposable and free email provider lists (no caching)<br \/>\n    <\/h4>\n<pre lang=\"php\">\r\n$config = [\r\n    'checkDisposableEmail' => true,\r\n    'checkFreeEmail' => true,\r\n];\r\n$emailValidator = new EmailValidator($config);\r\n    <\/pre>\n<h4>\n        Disposable email list with custom domains<br \/>\n    <\/h4>\n<pre lang=\"php\">\r\n$customDisposableEmailList = [\r\n    'example.com',\r\n];\r\n$config = [\r\n    'checkDisposableEmail' => true,\r\n    'disposableList' => $customDisposableEmailList,\r\n];\r\n$emailValidator = new EmailValidator($config);\r\n    <\/pre>\n<h3>\n        Simple Example<br \/>\n    <\/h3>\n<pre lang=\"php\">\r\n$emailValidator = new EmailValidator();\r\n$emailIsValid = $emailValidator->validate('user@example.com');\r\n    <\/pre>\n<h2>\n        A More Robust Example<br \/>\n    <\/h2>\n<pre lang=\"php\">\r\nuse EmailValidator\\EmailValidator;\r\n\r\nrequire('..\/vendor\/autoload.php');\r\n\r\n$customDisposableEmailList = [\r\n    'example.com',\r\n];\r\n$customFreeEmailList = [\r\n    'example2.com',\r\n];\r\n$bannedDomainList = [\r\n    'domain.com',\r\n];\r\n\r\n$testEmailAddresses = [\r\n    'test@johnconde.net',\r\n    'test@gmail.com',\r\n    'test@hotmail.com',\r\n    'test@outlook.com',\r\n    'test@yahoo.com',\r\n    'test@domain.com',\r\n    'test@mxfuel.com',\r\n    'test@example.com',\r\n    'test@example2.com',\r\n    'test@nobugmail.com',\r\n    'test@cellurl.com',\r\n    'test@10minutemail.com',\r\n];\r\n\r\n$config = [\r\n    'checkMxRecords' => true,\r\n    'checkBannedListedEmail' => true,\r\n    'checkDisposableEmail' => true,\r\n    'checkFreeEmail' => true,\r\n    'bannedList' => $bannedDomainList,\r\n    'disposableList' => $customDisposableEmailList,\r\n    'freeList' => $customFreeEmailList,\r\n];\r\n$emailValidator = new EmailValidator($config);\r\n\r\nforeach($testEmailAddresses as $emailAddress) {\r\n    $emailIsValid = $emailValidator->validate($emailAddress);\r\n    echo ($emailIsValid) ? 'Email is valid' : $emailValidator->getErrorReason();\r\n    echo PHP_EOL;\r\n}\r\n    <\/pre>\n<p class=\"bold\">\n        Outputs:\n    <\/p>\n<pre>\r\nEmail is valid\r\nDomain is used by free email providers\r\nDomain is used by free email providers\r\nDomain is used by free email providers\r\nDomain is used by free email providers\r\nDomain is banned\r\nDomain is used by disposable email providers\r\nDomain is used by free email providers\r\nDomain is used by disposable email providers\r\nDomain does not accept email\r\nDomain is used by disposable email providers\r\nDomain is used by disposable email providers\r\n    <\/pre>\n<h2>\n        Caching Remote Content<br \/>\n    <\/h2>\n<p>\n        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.\n    <\/p>\n<p>\n        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\n    <\/p>\n<pre lang=\"php\">\r\nuse EmailValidator\\Policy;\r\nuse EmailValidator\\Validator\\DisposableEmailValidator;\r\n\r\nrequire('..\/vendor\/autoload.php');\r\n\r\n$disposableEmailList = (new DisposableEmailValidator(new Policy()))->getList();\r\n$freeEmailList = (new FreeEmailValidator(new Policy()))->getList();\r\n    <\/pre>\n<p>\n        <code>$disposableEmailList<\/code> and <code>$freeEmailList<\/code> 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.\n    <\/p>\n<pre lang=\"php\">\r\n$config = [\r\n    'localDisposableOnly'=> true,\r\n    'localFreeOnly' => true,\r\n    'disposableList' => $customDisposableEmailList,\r\n    'freeList' => $customFreeEmailList,\r\n];\r\n$emailValidator = new EmailValidator($config);\r\n    <\/pre>\n<h2>\n        Help &amp; Support<br \/>\n    <\/h2>\n<p>\n        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.\n    <\/p>\n<p>\n        If you continue to have difficulty using this code please <b>do not contact me through this website<\/b>. Since this software is free to the community, the community can assist me in supporting it. I am an active participant at <a href=\"https:\/\/stackoverflow.com\/questions\/ask?tags=php,email,validation\" rel=\"external nofollow\">Stack Overflow<\/a>. 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:\n    <\/p>\n<ul>\n<li>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.<\/li>\n<li>Your code as it is implemented in your software. Make sure you format it so it is readable by others.<\/li>\n<li>A description of what you are expecting your code to do (but it is not happening).<\/li>\n<li>Any error message you are getting.<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>The Email Validator library builds upon PHP&#8217;s built in <code>filter_var($emailAddress, FILTER_VALIDATE_EMAIL);<\/code> 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. <a href=\"https:\/\/website-0f9bf4a4.hpx.ppi.temporary.site\/blog\/tutorial-php-email-address-validator\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[16],"tags":[50,91],"class_list":["post-719","post","type-post","status-publish","format-standard","hentry","category-programming","tag-php","tag-tutorial"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/pwpo4-bB","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/website-0f9bf4a4.hpx.ppi.temporary.site\/blog\/wp-json\/wp\/v2\/posts\/719","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/website-0f9bf4a4.hpx.ppi.temporary.site\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/website-0f9bf4a4.hpx.ppi.temporary.site\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/website-0f9bf4a4.hpx.ppi.temporary.site\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/website-0f9bf4a4.hpx.ppi.temporary.site\/blog\/wp-json\/wp\/v2\/comments?post=719"}],"version-history":[{"count":3,"href":"https:\/\/website-0f9bf4a4.hpx.ppi.temporary.site\/blog\/wp-json\/wp\/v2\/posts\/719\/revisions"}],"predecessor-version":[{"id":755,"href":"https:\/\/website-0f9bf4a4.hpx.ppi.temporary.site\/blog\/wp-json\/wp\/v2\/posts\/719\/revisions\/755"}],"wp:attachment":[{"href":"https:\/\/website-0f9bf4a4.hpx.ppi.temporary.site\/blog\/wp-json\/wp\/v2\/media?parent=719"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/website-0f9bf4a4.hpx.ppi.temporary.site\/blog\/wp-json\/wp\/v2\/categories?post=719"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/website-0f9bf4a4.hpx.ppi.temporary.site\/blog\/wp-json\/wp\/v2\/tags?post=719"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}