129

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.

hakre
  • 193,403
  • 52
  • 435
  • 836
learner
  • 2,099
  • 6
  • 23
  • 32
  • 3
    The correct answer was already given, but regarding the *deprecated* issue: The usage of POSIX regular expressions (which `eregi` is a function of) is deprecated. Use [PCRE](http://www.php.net/manual/en/book.pcre.php) instead. – Felix Kling May 02 '11 at 10:09
  • 3
    By the way, your regex is totally wrong. Some totally valid adresses will be marked as invalid by your function. Filtering email adresses with a regex is a nightmare. – Artefact2 May 02 '11 at 10:19
  • You should use [RFC 822](http://tools.ietf.org/html/rfc822) standard and here is a good article [Parsing Email Adresses in PHP](http://www.iamcal.com/publish/articles/php/parsing_email) that explains it. – kta Jan 06 '14 at 17:34
  • Stay away from `regex` and `filter_var()` solutions for validating email. See this answer: https://stackoverflow.com/a/42037557/953833 – Jabari Feb 04 '17 at 07:16

8 Answers8

291

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: bazmega@kapa.com. 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.

Community
  • 1
  • 1
kapa
  • 77,694
  • 21
  • 158
  • 175
  • 4
    +1 That said, you might want to mention that this is only available in PHP 5.2.x and above. :-) – John Parker May 02 '11 at 10:09
  • 5
    @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)). – Felix Kling May 02 '11 at 10:10
  • @middaparka Thanks, I added it. I left it out for the same reason what @Felix explained, but yes, others might be interested. – kapa May 02 '11 at 10:12
  • 8
    PHP 5.3.3 and 5.2.14 had a bug (http://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. – binaryLV May 02 '11 at 10:39
  • 1
    @binaryLV, `filter_val` or `filter_var` ? – Istiaque Ahmed Nov 21 '12 at 09:31
  • @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. – Istiaque Ahmed Nov 21 '12 at 09:50
  • 1
    @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. – kapa Nov 21 '12 at 10:58
  • 1
    @Istiaque Ahmed, probably 18 months old typo. – binaryLV Nov 21 '12 at 13:57
  • 3
    @kapa, Actually you don't need any more to check for a dot in the domain part. See http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3/ext/filter/logical_filters.c?r1=297250&r2=297350&pathrev=303779 – Eliseo Ocampos Dec 09 '13 at 21:21
  • 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. – sg3s Feb 03 '14 at 13:22
  • You should return `filter_var(...) !== false` in your function to return a boolean ("`isValidEmail`" implies a boolean return value). – stofl Jan 02 '16 at 23:23
  • @stofl You are right, it also matches the OP's original signature better. Edited. – kapa Jan 04 '16 at 08:10
  • Sorry to dig out this post, but does this method also cover up SQL injection or similar methods? – Norman Jan 11 '16 at 10:12
  • @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. – kapa Jan 11 '16 at 12:10
  • @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. – Norman Jan 11 '16 at 12:18
  • This will validate: `$email = '">"@test.com'; echo filter_var($email, FILTER_VALIDATE_EMAIL)` – sergio Mar 07 '16 at 08:22
  • @sergio Is it an invalid email address? – kapa Mar 07 '16 at 09:08
  • @kapa It can inject XSS, but filter_var($email, FILTER_VALIDATE_EMAIL) will validate it as an valid email, so need to be care – sergio Mar 07 '16 at 09:21
  • @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. – kapa Mar 07 '16 at 09:40
  • 1
    An important notice - in the last update, you changed the logic a bit since you removed the `!== false`. – Tomer Gal Jul 19 '17 at 15:53
  • this function won't work for emails with spanish characters like `Stéphane@yopmail.com` – Coder anonymous Dec 26 '18 at 16:52
9

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().

Sean Kelleher
  • 1,952
  • 1
  • 23
  • 34
7

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.

Community
  • 1
  • 1
Ivijan Stefan Stipić
  • 6,249
  • 6
  • 45
  • 78
3

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;
}
unbreak
  • 1,000
  • 1
  • 16
  • 32
  • 1
    @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. – Subhajit Apr 11 '18 at 11:35
2

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 = "john.doe@example.com";

// 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";
}
?>
mufazmi
  • 1,103
  • 4
  • 18
  • 37
1

Use:

var_dump(filter_var('bob@example.com', FILTER_VALIDATE_EMAIL));
$validator = new EmailValidator();
$multipleValidations = new MultipleValidationWithAnd([
    new RFCValidation(),
    new DNSCheckValidation()
]);
$validator->isValid("example@example.com", $multipleValidations); //true
Roman
  • 49
  • 2
  • 6
0

take several care, a address as iasd@x.z-----com is INVALID, but filter_var() return true, many others strings (emails) INVALIDS return true using filter_var().

for validate email I use this function:

function correcorre($s){// correo correcto
    $x = '^([[:alnum:]](_|-|\.)*)*[[:alnum:]]+@([[:alnum:]]+(-|\.)+)*[[:alnum:]]+\.[[:alnum:]]+$';
    preg_match("!$x!i", $s, $M);
    if(!empty($M[0]))return($M[0]);
    }

please improve and share, thanks

Stackoverflow
  • 449
  • 5
  • 13
0

Though I'm a little bit late this could help someone who still wants to check more.

if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
  // invalid email address
}

This will only validate if the email format is correct or not. But if you want to use more than that, like if this email really exists or not, You can use the free API.

Here is the code that I'm currently using on my website.

    if(isEmialExist("EMAIL_ADDRESS_THAT"))
{
    echo "email exists, real email";
}
else
{
    echo "email doesn't exist";
}


function isEmialExist($emailAddress)
{
    if (!filter_var($emailAddress, FILTER_VALIDATE_EMAIL)) {
     return false; //invalid format
    }
    //now check if email really exist
    $postdata = http_build_query(array('api_key' => 'YOUR_API_KEY', 'email' => $emailAddress ));
    $url = "https://email-validator.com/api/v1.0/json";
    $opts = array('http' => array( 'method'  => 'POST', 'header'  => 'Content-Type: application/x-www-form-urlencoded', 'content' => $postdata ));
    
    $context  = stream_context_create($opts);
    $result = file_get_contents($url, false, $context);
    $data = json_decode($result, false);
    return $data->is_exists;
}

You can find more details here. https://email-validator.com/tutorial

advantage of this API is, it provides real-time results and you will get 10,000 free credits

Deluar Hossen
  • 595
  • 4
  • 6