web-dev-qa-db-fra.com

Comment valider une adresse email dans PHP

J'ai cette fonction pour valider une adresse email:

function validateEMAIL($EMAIL) {
    $v = "/[a-zA-Z0-9_-.+]+@[a-zA-Z0-9-]+.[a-zA-Z]+/";

    return (bool)preg_match($v, $EMAIL);
}

Est-ce acceptable pour vérifier si l'adresse e-mail est valide ou non?

201
Cameron

Le moyen le plus simple et le plus sûr de vérifier si une adresse électronique est bien formée consiste à utiliser la fonction filter_var() :

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

De plus, vous pouvez vérifier si le domaine définit un enregistrement MX:

if (!checkdnsrr($domain, 'MX')) {
    // domain is not valid
}

Mais cela ne garantit toujours pas que le courrier existe. La seule façon de le savoir est d'envoyer un mail de confirmation.


Maintenant que vous avez votre réponse facile, n'hésitez pas à lire sur la validation des adresses e-mail si vous souhaitez apprendre ou si vous utilisez simplement la réponse rapide et passez à autre chose. Pas d'émotions fortes.

Essayer de valider une adresse email en utilisant une expression régulière est une tâche "impossible". J'irais jusqu'à dire que cette regex que vous avez faite est inutile. Il y a trois processeurs rfc concernant les adresses électroniques et l'écriture d'une expression rationnelle pour détecter les mauvaises adresses électroniques et en même temps, ne pas avoir de faux positifs est une chose qu'aucun mortel ne peut faire. Consultez cette liste pour des tests (ayant échoué et réussi) de l'expression régulière utilisée par la fonction filter_var() de PHP.

Même les fonctions intégrées PHP, les clients de messagerie ou les serveurs ne donnent pas les bons résultats. Toujours dans la plupart des cas, filter_var est la meilleure option.

Si vous voulez savoir quel modèle d'expression régulière PHP (actuellement) utilise pour valider les adresses électroniques, voir le PHP source .

Si vous voulez en savoir plus sur les adresses e-mail, je vous suggère de commencer à lire les spécifications, mais je dois vous avertir que la lecture de ce fichier n'est pas facile:

Notez que filter_var() est comme déjà indiqué uniquement disponible à partir de PHP 5.2. Si vous voulez que cela fonctionne avec les versions précédentes de PHP, vous pouvez utiliser la regex utilisée en PHP:

<?php

$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';

$emailaddress = '[email protected]';

if (preg_match($pattern, $emailaddress) === 1) {
    // emailaddress is valid
}

P.S. Une note sur le motif de regex utilisé ci-dessus (à partir de la source PHP). Il semble y avoir un copyright sur Michael Rushton . Comme indiqué: "N'hésitez pas à utiliser et à redistribuer ce code. Mais s'il vous plaît, gardez cet avis de copyright."

526
PeeHaa

Vous pouvez utiliser filter_var pour cela.

<?php
   function validateEmail($email) {
      return filter_var($email, FILTER_VALIDATE_EMAIL);
   }
?>
38
Cameron Martin

D'après mon expérience, les solutions regex ont trop de faux positifs et les solutions filter_var() ont de faux négatifs (en particulier avec tous les nouveaux TLD ).

Au lieu de cela, il est préférable de s’assurer que l’adresse contient toutes les parties requises d’une adresse électronique (utilisateur, symbole "@" et domaine), puis de vérifier que le domaine existe.

Il n'existe aucun moyen de déterminer (côté serveur) s'il existe un utilisateur de messagerie pour un domaine externe.

C'est une méthode que j'ai créée dans une classe Utility:

public static function validateEmail($email)
{
    // SET INITIAL RETURN VARIABLES

        $emailIsValid = FALSE;

    // MAKE SURE AN EMPTY STRING WASN'T PASSED

        if (!empty($email))
        {
            // GET EMAIL PARTS

                $domain = ltrim(stristr($email, '@'), '@') . '.';
                $user   = stristr($email, '@', TRUE);

            // VALIDATE EMAIL ADDRESS

                if
                (
                    !empty($user) &&
                    !empty($domain) &&
                    checkdnsrr($domain)
                )
                {$emailIsValid = TRUE;}
        }

    // RETURN RESULT

        return $emailIsValid;
}
12
Jabari

Je pense que vous feriez mieux d'utiliser PHP intégré filtres - dans ce cas particulier:

Il peut retourner une valeur true ou false lorsqu'il est fourni avec le paramètre FILTER_VALIDATE_EMAIL.

9
Fluffeh

Cela validera non seulement votre email, mais le nettoiera aussi pour les caractères inattendus:

$email  = $_POST['email'];
$emailB = filter_var($email, FILTER_SANITIZE_EMAIL);

if (filter_var($emailB, FILTER_VALIDATE_EMAIL) === false ||
    $emailB != $email
) {
    echo "This email adress isn't valid!";
    exit(0);
}
8
Excalibur

A répondu à cela en 'question principale' à propos de la vérification des emails https://stackoverflow.com/a/41129750/1848217

Pour moi, le bon moyen de vérifier les emails est:

  1. Vérifiez que le symbole @ existe et avant et après il y a des symboles autres que @: /^[^@]+@[^@]+$/
  2. Essayez d'envoyer un email à cette adresse avec un "code d'activation".
  3. Lorsque l'utilisateur "activera" son adresse e-mail, nous verrons que tout va bien.

Bien sûr, vous pouvez afficher un avertissement ou une info-bulle en frontal lorsque l'utilisateur a tapé un courrier électronique "étrange" pour l'aider à éviter les erreurs courantes, comme par exemple, aucun point dans une partie de domaine ou des espaces dans le nom sans les guillemets, etc. Mais vous devez accepter l'adresse "hello @ world" si l'utilisateur le souhaite vraiment.

En outre, vous devez vous rappeler que l'adresse électronique standard était et peut évoluer, vous ne pouvez donc pas taper une seule expression rationnelle "standard-valide" une fois pour toutes. Et vous devez vous rappeler que certains serveurs Internet concrets peuvent échouer avec certains détails de la norme commune et fonctionnent en fait avec votre propre "norme modifiée".

Donc, il suffit de vérifier @, d'indiquer à l'utilisateur le frontend et d'envoyer des courriels de vérification à une adresse donnée.

2
FlameStorm

Si vous recherchez simplement une regex qui permette de créer différents points, traits de soulignement et tirets, procédez comme suit: [a-zA-z0-9.-]+\@[a-zA-z0-9.-]+.[a-zA-Z]+. Cela permettra de valider un email qui semble assez stupide comme tom_anderson.1-neo@my-mail_matrix.com.

1
smulholland2

Si vous voulez vérifier si le domaine fourni à partir de l'adresse de messagerie est valide, utilisez quelque chose comme:

/*
* Check for valid MX record for given email domain
*/
if(!function_exists('check_email_domain')){
    function check_email_domain($email) {
        //Get Host name from email and check if it is valid
        $email_Host = explode("@", $email);     
        //Add a dot to the end of the Host name to make a fully qualified domain name and get last array element because an escaped @ is allowed in the local part (RFC 5322)
        $Host = end($email_Host) . "."; 
        //Convert to ascii (http://us.php.net/manual/en/function.idn-to-ascii.php)
        return checkdnsrr(idn_to_ascii($Host), "MX"); //(bool)       
    }
}

C'est un moyen pratique de filtrer un grand nombre d'adresses e-mail non valides, ainsi qu'une validation d'e-mail standard, car valide format e-mail ne signifie pas valide e-mail.

Notez que idn_to_ascii() (ou sa fonction soeur idn_to_utf8()) fonctionne peut-être pas disponible dans votre installation PHP, il nécessite des extensions PECL intl> = 1.0. 2 et id PECL> = 0,1.

N'oubliez pas non plus que IPv4 ou IPv6 en tant que partie de domaine dans le courrier électronique (par exemple user@[IPv6:2001:db8::1]) ne peut pas être validé, seuls les hôtes nommés peuvent le faire.

Voir plus ici .

0
bodi0
/(?![[:alnum:]]|@|-|_|\.)./

De nos jours, si vous utilisez un formulaire HTML5 avec type=email, vous êtes déjà sûr à 80%, puisque les moteurs de navigateur ont leur propre validateur. Pour la compléter, ajoutez cette regex à votre preg_match_all() et annulez-la:

if (!preg_match_all("/(?![[:alnum:]]|@|-|_|\.)./",$email)) { .. }

Recherche de l'expression rationnelle utilisée par les formulaires HTML5 pour validation
https://regex101.com/r/mPEKmy/1

0
Thielicious

Après avoir lu les réponses ici, voici ce avec quoi je me suis retrouvé:

public static function isValidEmail(string $email) : bool
{
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        return false;
    }

    //Get Host name from email and check if it is valid
    $email_Host = array_slice(explode("@", $email), -1)[0];

    // Check if valid IP (v4 or v6). If it is we can't do a DNS lookup
    if (!filter_var($email_Host,FILTER_VALIDATE_IP, [
        'flags' => FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE,
    ])) {
        //Add a dot to the end of the Host name to make a fully qualified domain name
        // and get last array element because an escaped @ is allowed in the local part (RFC 5322)
        // Then convert to ascii (http://us.php.net/manual/en/function.idn-to-ascii.php)
        $email_Host = idn_to_ascii($email_Host.'.');

        //Check for MX pointers in DNS (if there are no MX pointers the domain cannot receive emails)
        if (!checkdnsrr($email_Host, "MX")) {
            return false;
        }
    }

    return true;
}
0
Pelmered