How to validate an Email in PHP?

189,499

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)

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() before filter_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";
}
?>
Share:
189,499
learner
Author by

learner

Updated on January 04, 2022

Comments

  • learner
    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
    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
    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
    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
    binaryLV about 13 years
    PHP 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 using strlen() before filter_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
    Istiaque Ahmed over 11 years
    @binaryLV, filter_val or filter_var ?
  • Istiaque Ahmed
    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-upd‌​ated.
  • kapa
    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
    binaryLV over 11 years
    @Istiaque Ahmed, probably 18 months old typo.
  • Eliseo Ocampos
    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
    sg3s over 10 years
    I 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
    stofl over 8 years
    You should return filter_var(...) !== false in your function to return a boolean ("isValidEmail" implies a boolean return value).
  • kapa
    kapa over 8 years
    @stofl You are right, it also matches the OP's original signature better. Edited.
  • Norman
    Norman over 8 years
    Sorry to dig out this post, but does this method also cover up SQL injection or similar methods?
  • kapa
    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
    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
    sergio over 8 years
    This will validate: $email = '"><script>alert(1);</script>"@test.com'; echo filter_var($email, FILTER_VALIDATE_EMAIL)
  • kapa
    kapa over 8 years
    @sergio Is it an invalid email address?
  • sergio
    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
    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
    Tomer Gal almost 7 years
    An important notice - in the last update, you changed the logic a bit since you removed the !== false.
  • Subhajit
    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
    Coder anonymous over 5 years
    this function won't work for emails with spanish characters like Sté[email protected]