How to validate an Email in PHP?
Solution 1
You can use the filter_var()
function, which gives you a lot of handy validation and sanitization options.
filter_var($email, FILTER_VALIDATE_EMAIL)
Available in PHP >= 5.2.0
If you don't want to change your code that relied on your function, just do:
function isValidEmail($email){
return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}
Note: For other uses (where you need Regex), the deprecated ereg
function family (POSIX Regex Functions) should be replaced by the preg
family (PCRE Regex Functions). There are a small amount of differences, reading the Manual should suffice.
Update 1: As pointed out by @binaryLV:
PHP 5.3.3 and 5.2.14 had a bug related to FILTER_VALIDATE_EMAIL, which resulted in segfault when validating large values. Simple and safe workaround for this is using
strlen()
beforefilter_var()
. I'm not sure about 5.3.4 final, but it is written that some 5.3.4-snapshot versions also were affected.
This bug has already been fixed.
Update 2: This method will of course validate bazmega@kapa
as a valid email address, because in fact it is a valid email address. But most of the time on the Internet, you also want the email address to have a TLD: [email protected]
. As suggested in this blog post (link posted by @Istiaque Ahmed), you can augment filter_var()
with a regex that will check for the existence of a dot in the domain part (will not check for a valid TLD though):
function isValidEmail($email) {
return filter_var($email, FILTER_VALIDATE_EMAIL)
&& preg_match('/@.+\./', $email);
}
As @Eliseo Ocampos pointed out, this problem only exists before PHP 5.3, in that version they changed the regex and now it does this check, so you do not have to.
Solution 2
See the notes at http://www.php.net/manual/en/function.ereg.php:
Note:
As of PHP 5.3.0, the regex extension is deprecated in favor of the PCRE extension. Calling this function will issue an E_DEPRECATED notice. See the list of differences for help on converting to PCRE.
Note:
preg_match(), which uses a Perl-compatible regular expression syntax, is often a faster alternative to ereg().
Solution 3
This is old post but I will share one my solution because noone mention here one problem before.
New email address can contain UTF-8 characters or special domain names like .live
, .news
etc.
Also I find that some email address can be on Cyrilic and on all cases standard regex or filter_var()
will fail.
That's why I made an solution for it:
function valid_email($email)
{
if(is_array($email) || is_numeric($email) || is_bool($email) || is_float($email) || is_file($email) || is_dir($email) || is_int($email))
return false;
else
{
$email=trim(strtolower($email));
if(filter_var($email, FILTER_VALIDATE_EMAIL)!==false) return $email;
else
{
$pattern = '/^(?!(?:(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){255,})(?!(?:(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){65,}@)(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+)|(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|(?:\\x5C[\\x00-\\x7F]))*\\x22))(?:\\.(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+)|(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|(?:\\x5C[\\x00-\\x7F]))*\\x22)))*@(?:(?:(?!.*[^.]{64,})(?:(?:(?:xn--)?[a-z0-9]+(?:-+[a-z0-9]+)*\\.){1,126}){1,}(?:(?:[a-z][a-z0-9]*)|(?:(?:xn--)[a-z0-9]+))(?:-+[a-z0-9]+)*)|(?:\\[(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){7})|(?:(?!(?:.*[a-f0-9][:\\]]){7,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?)))|(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){5}:)|(?:(?!(?:.*[a-f0-9]:){5,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3}:)?)))?(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))(?:\\.(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))){3}))\\]))$/iD';
return (preg_match($pattern, $email) === 1) ? $email : false;
}
}
}
This function work perfectly for all cases and email formats.
Solution 4
I always use this:
function validEmail($email){
// First, we check that there's one @ symbol, and that the lengths are right
if (!preg_match("/^[^@]{1,64}@[^@]{1,255}$/", $email)) {
// Email invalid because wrong number of characters in one section, or wrong number of @ symbols.
return false;
}
// Split it into sections to make life easier
$email_array = explode("@", $email);
$local_array = explode(".", $email_array[0]);
for ($i = 0; $i < sizeof($local_array); $i++) {
if (!preg_match("/^(([A-Za-z0-9!#$%&'*+\/=?^_`{|}~-][A-Za-z0-9!#$%&'*+\/=?^_`{|}~\.-]{0,63})|(\"[^(\\|\")]{0,62}\"))$/", $local_array[$i])) {
return false;
}
}
if (!preg_match("/^\[?[0-9\.]+\]?$/", $email_array[1])) { // Check if domain is IP. If not, it should be valid domain name
$domain_array = explode(".", $email_array[1]);
if (sizeof($domain_array) < 2) {
return false; // Not enough parts to domain
}
for ($i = 0; $i < sizeof($domain_array); $i++) {
if (!preg_match("/^(([A-Za-z0-9][A-Za-z0-9-]{0,61}[A-Za-z0-9])|([A-Za-z0-9]+))$/", $domain_array[$i])) {
return false;
}
}
}
return true;
}
Solution 5
User data is very important for a good developer, so don't ask again and again for same data, use some logic to correct some basic error in data.
Before validation of Email: First you have to remove all illegal characters from email.
//This will Remove all illegal characters from email
$email = filter_var($email, FILTER_SANITIZE_EMAIL);
after that validate your email address using this filter_var()
function.
filter_var($email, FILTER_VALIDATE_EMAIL)) // To Validate the email
For e.g.
<?php
$email = "[email protected]";
// Remove all illegal characters from email
$email = filter_var($email, FILTER_SANITIZE_EMAIL);
// Validate email
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
echo $email." is a valid email address";
} else {
echo $email." is not a valid email address";
}
?>
learner
Updated on January 04, 2022Comments
-
learner over 2 years
How can I validate the input value is a valid email address using php5. Now I am using this code
function isValidEmail($email){ $pattern = "^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$"; if (eregi($pattern, $email)){ return true; } else { return false; } }
but it shows deprecated error. How can I fix this issue. Please help me.
-
John Parker about 13 years+1 That said, you might want to mention that this is only available in PHP 5.2.x and above. :-)
-
Felix Kling about 13 years@middaparka: As the OP gets a deprecated message for
eregi
, it seems he is using PHP 5.3. But yes, it is important to mention it (for others)). -
kapa about 13 years@middaparka Thanks, I added it. I left it out for the same reason what @Felix explained, but yes, others might be interested.
-
binaryLV about 13 yearsPHP 5.3.3 and 5.2.14 had a bug (bugs.php.net/52929) related to
FILTER_VALIDATE_EMAIL
, which resulted in segfault when validating large values. Simple and safe workaround for this is usingstrlen()
beforefilter_val()
. I'm not sure about 5.3.4 final, but it is written that some 5.3.4-snapshot versions also were affected. -
Istiaque Ahmed over 11 years@binaryLV,
filter_val
orfilter_var
? -
Istiaque Ahmed over 11 years@bažmegakapa, email address should be trimmed before the final testing, I think. The validation process in the answer does not check the presence of the dot in addres.
return filter_var($email, FILTER_VALIDATE_EMAIL) && preg_match('/@.+\./', $email);
- tests the presence of a dot in domain name part. An integer casting of the return value is also necessary.Found here:electrictoolbox.com/php-email-validation-filter-var-updated. -
kapa over 11 years@IstiaqueAhmed Useful resource, I will update my answer. But you have a misunderstanding: the return value of course does not have to be cast to an integer - the blogger only does this to make
echo
correctly display the boolean. -
binaryLV over 11 years@Istiaque Ahmed, probably 18 months old typo.
-
Eliseo Ocampos over 10 years@kapa, Actually you don't need any more to check for a dot in the domain part. See svn.php.net/viewvc/php/php-src/branches/PHP_5_3/ext/filter/…
-
sg3s over 10 yearsI would just like to note that this option backed up with a domain/MX record checkup you can be pretty sure the server also might really be able to process the emails you might send it.
-
stofl over 8 yearsYou should return
filter_var(...) !== false
in your function to return a boolean ("isValidEmail
" implies a boolean return value). -
kapa over 8 years@stofl You are right, it also matches the OP's original signature better. Edited.
-
Norman over 8 yearsSorry to dig out this post, but does this method also cover up SQL injection or similar methods?
-
kapa over 8 years@Norman This method covers email validation. It checks whether a string contains a valid email address. No database is mentioned, so it has nothing to do with SQL injection.
-
Norman over 8 years@kapa and at everyone: Sorry, my bad. I somehow thought that this method isn't working with htmlspecialchars. But the bug was somewhere else. Thanks for the quick reply though.
-
sergio over 8 yearsThis will validate:
$email = '"><script>alert(1);</script>"@test.com'; echo filter_var($email, FILTER_VALIDATE_EMAIL)
-
kapa over 8 years@sergio Is it an invalid email address?
-
sergio over 8 years@kapa It can inject XSS, but filter_var($email, FILTER_VALIDATE_EMAIL) will validate it as an valid email, so need to be care
-
kapa over 8 years@sergio An email validator validates emails. That is its job. It should not care about XSS, SQL injection, etc. That is a different part of your application. When you output HTML, you should take precautions against XSS.
-
Tomer Gal almost 7 yearsAn important notice - in the last update, you changed the logic a bit since you removed the
!== false
. -
Subhajit about 6 years@unbreak I've tried your code and found that if you pass email as
alex@.
then it always returns true where it's not a valid email address. -
Coder anonymous over 5 yearsthis function won't work for emails with spanish characters like
Sté[email protected]