Validating Email Addresses in PHP
A very quick snippet today because I’ve told two people to use this approach in the last few days and both of them told me they didn’t know about it. How to check if an email address is valid in PHP: use one of the Filter functions, like this:
$email1 = "nonsense.something@dottiness"; // not a valid email
$email2 = "[email protected]"; // valid email
$clean_email1 = filter_var($email1, FILTER_VALIDATE_EMAIL); // $clean_email1 = false
$clean_email2 = filter_var($email2, FILTER_VALIDATE_EMAIL); // $clean_email2 = [email protected]
The Filter extension was new in PHP 5.2, but is one of the unsung heroes of the language. It’s rare for me to ever describe one approach as the “right” way to do something – but for validating data, Filter really is excellent, offering both validating and sanitising filters and generally making it super-easy to clean up incoming variables. Many of the frameworks offer equivalents, and I’m sure many of those are wrapping this too.
Email validation with filter_var() can produce different results with different versions of PHP. There are some differences between how filter_var() acts in 5.2 and 5.3 (if i remember it correctly).
I’m not aware of that and didn’t spot anything in the manual. Do you have a link to more information? I’d be interested
For example those two:
filter_var(‘[email protected]’, FILTER_VALIDATE_EMAIL);
filter_var(‘lornajaneaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@gmail.com’, FILTER_VALIDATE_EMAIL);
In 5.2.10 they will be good. In 5.2.17 they will give false (the same with 5.4). I dont know in which version behavior changed. However that’s the reason why I have trust issues in filter_var() for validating email (if i dont know on which version it will run i cant predict he outcome).
One more:
[coe]var_dump(filter_var(‘”John Doe”@gmail.com’, FILTER_VALIDATE_EMAIL));[/code]
In 5.4: false
In 5.2.17: false
in 5.2.10: “John Doe”@gmail.com
email@com, user@localmachine, “john smith”@example.com, localuser
All valid email addresses that filter_var() returns FALSE for.
Indeed that was my first impression when I saw the example e-mail address “nonsense.something@dottiness”, which is a very valid e-mail address according to the RFC. Practically though, you can’t send an e-mail to that address, unless your DNS server happens to know where “dottiness” is located, which means it’s not a *useful* e-mail address in most circumstances.
Indeed filter_var( ) does tell you some valid e-mail addresses aren’t valid, but in day-to-day use in a webapplication, it will suffice easily.
Valid according to who? Anything without a TLD isn’t going to work on the internet, and I’ve never once in my life seen an email address with a space in it. So, IMO, it’s a good thing that those don’t pass the test.
Anything without a dot in the domain may not work on the internet today, but ICANN is busy approving a whole stack of new TLDs, many of which will be owned by a single company. They may well want use those new TLDs to set up email addresses like “name@company” without any dots in the domain.
Also, some systems may need to send email internally within a local network, in which case it’s perfectly legitimate for the local domain to be unqualified.
And as for you never having seen an email address with a space in it…. well, that’s lucky for you. They do exist. And so do a bunch of other weird combinations. You can basically have anything you like in front of the @ symbol, and there are people out there who do. I suspect those people find they have a lot of trouble filling in web forms, though.
Validating email addresses easy. Validating them correctly is *hard*. It looks like it ought to be easy, but it isn’t. Most of the tutorials on the web telling you how to do it are wrong.
According to RFC822 and its descendants.
There are lots of places where local email addresses are likely to crop up. For example logging and monitoring.
David – I can only sigh at your response.
For logging and monitoring you’ll be specifying an email address yourself, and won’t be validating it.
For websites that collect email addresses in the wild, you simply aren’t going to receive addresses in those formats, and if you do it’s likely to be an error. Works as designed.
Um. If you don’t want to conform to RFCs… or Postel’s Law… well, ok, I guess. Good luck.
I always use Zend_Validate_EmailAddress , it also has a MX-record check and filters many typos like [email protected]
It’s true. PHP5.2 (I believe…) has a bug where [email protected], but a period cannot be the last character in the local part.
I’ve taken to using a multi-step method for validating an email…
[code]
<?php
$email = $_POST['email'];
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
continue_with_processing();
} else if (strpos($email, '@') !== false) {
ask_if_they_are_sure();
} else {
reject_input();
}
[/code]
The basic premise is: the only darn thing that can really validate an email is the receiving mailserver. Offering helpful feedback saying it doesn't *look* right is as far as I go (if it has an '@' in it.) After all, before they can setup their account they do have to click the link I send to their email.
Note: You can go another step by splitting by @, taking the last part, and checking to see if the domain resolves. Dont’ check for MX servers – if there are no MX severs listed, the RFC says to use the hostname itself. See: http://php.net/getmxrr
This is a very valuable piece if information , I have never heard of it.
Thanks Lorna .
I would go with http://isemail.info/about – it’s the best email validator i found when i did my research.
See also: Parsing Email Adresses in PHP
While I agree with the approach used in this article I still have to point out that this will not work for email addresses. The reason is internationalization. Let’s say you have an address like post@øl.no (www.øl.no) is a valid domain with content. This method will return false.
So to be sure that your email validation actually is 100% successfull in all cases you will have to do use idn_to_ascii():
$email = ‘post@øl.no’;
list($user, $domain) = explode(‘@’, $email);
$user = idn_to_ascii($user);
$domain = idn_to_ascii($domain);
$email = $user . ‘@’ . $domain;
$result = filter_var($email, FILTER_VALIDATE_EMAIL);
This will convert the user and domain to the same format used by DNS servers when resolving internationalized domain names.
PS: You will have to have PHP’s intl module installed to be able to use the idn_* functions
Very helpfull article :) thanks
The problem with
[code]filter_var($email, FILTER_VALIDATE_EMAIL))[/code]
is that it doesn’t check if the domain names exsists.
I’ve made a small PHP function, which also check if the domain name exists.
Grab it here: http://www.wmappz.com/php/validate-email-address
Thank you. I’m using Regex to validate Emails and URLs