Como validar um email em PHP?


120

Como posso validar o valor de entrada é um endereço de email válido usando php5. Agora estou usando esse código

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; 
     }    
} 

mas mostra erro obsoleto. Como posso corrigir esse problema. Por favor me ajude.


3
A resposta correta já foi dada, mas com relação ao problema preterido : O uso de expressões regulares POSIX (que eregié uma função de) está preterido. Use PCRE .
Felix Kling

3
A propósito, seu regex está totalmente errado. Alguns endereços totalmente válidos serão marcados como inválidos por sua função. Filtrar endereços de email com uma regex é um pesadelo.
Artefact2

Você deve usar o padrão RFC 822 e aqui está um bom artigo Analisando endereços de email em PHP que explica isso.
Kta

Respostas:


274

Você pode usar a filter_var()função, que oferece muitas opções úteis de validação e higienização.

filter_var($email, FILTER_VALIDATE_EMAIL)

Se você não deseja alterar seu código que depende de sua função, basta:

function isValidEmail($email){ 
    return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}

Nota : Para outros usos (onde você precisa do Regex), a eregfamília de funções descontinuadas (Funções do POSIX Regex) deve ser substituída pela pregfamília ( Funções do PCRE Regex ). Há uma pequena quantidade de diferenças, a leitura do manual deve ser suficiente.

Atualização 1 : Como apontado por @binaryLV :

O PHP 5.3.3 e 5.2.14 teve um bug relacionado ao FILTER_VALIDATE_EMAIL, que resultou em falha na validação de valores grandes. Solução simples e segura para isso é usar strlen() antes filter_var(). Não tenho certeza sobre o 5.3.4 final, mas está escrito que algumas versões do 5.3.4-snapshot também foram afetadas.

Este bug já foi corrigido.

Atualização 2 : é claro que este método é validado bazmega@kapacomo um endereço de email válido, porque na verdade é um endereço de email válido. Mas a maior parte do tempo na Internet, você também quer o endereço de email para ter um TLD: bazmega@kapa.com. Conforme sugerido nesta postagem do blog (link postado por @Istiaque Ahmed ), você pode aumentar filter_var()com uma regex que verificará a existência de um ponto na parte do domínio (não verificará embora TLD válido ):

function isValidEmail($email) {
    return filter_var($email, FILTER_VALIDATE_EMAIL) 
        && preg_match('/@.+\./', $email);
}

Como o @Eliseo Ocampos apontou, esse problema só existe antes do PHP 5.3, nessa versão eles alteraram o regex e agora ele faz essa verificação, então você não precisa.


4
+1 Dito isto, você pode mencionar que isso está disponível apenas no PHP 5.2.xe acima. :-)
John Parker

5
@ middaparka: Como o OP recebe uma mensagem obsoleta eregi, parece que ele está usando o PHP 5.3. Mas sim, é importante mencioná-lo (para outros)).
Felix Kling

8
O PHP 5.3.3 e 5.2.14 tinha um bug ( bugs.php.net/52929 ) relacionado ao FILTER_VALIDATE_EMAILque resultou em falha na validação de valores grandes. Solução simples e segura para isso é usar strlen()antes filter_val(). Não tenho certeza sobre o 5.3.4 final, mas está escrito que algumas versões do 5.3.4-snapshot também foram afetadas.
BinárioLV 2/11

1
@binaryLV, filter_valou filter_var?
Istiaque Ahmed

3
@ kapa, Na verdade, você não precisa mais procurar um ponto na parte do domínio. Veja svn.php.net/viewvc/php/php-src/branches/PHP_5_3/ext/filter/…
Eliseo Ocampos


7

Este é um post antigo, mas vou compartilhar uma minha solução, porque ninguém mencionou aqui um problema antes.

O novo endereço de email pode conter caracteres UTF-8 ou nomes de domínio especiais .live, como ,.news etc.

Também acho que algum endereço de email pode estar em cirílico e em todos os casos regex padrão ou filter_var() falhará.

Foi por isso que fiz uma solução para isso:

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;
        }
    }
}

Esta função funciona perfeitamente para todos os casos e formatos de email.


3

Eu sempre uso isso:

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;
}

1
@unbreak Eu tentei o seu código e descobri que, se você passa um email alex@., ele sempre retorna verdadeiro onde não é um endereço de email válido.
Subhajit



0

Os dados do usuário são muito importantes para um bom desenvolvedor; portanto, não peça repetidamente os mesmos dados, use alguma lógica para corrigir algum erro básico nos dados.

Antes da validação do email: primeiro você deve remover todos os caracteres ilegais do email.

//This will Remove all illegal characters from email
$email = filter_var($email, FILTER_SANITIZE_EMAIL);

depois disso, valide seu endereço de e-mail usando esta filter_var()função.

filter_var($email, FILTER_VALIDATE_EMAIL)) // To Validate the email

Por exemplo

<?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";
}
?>
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.