PHP, vérification de mail complète, avec DNS
gMail permet de rajouter un « +cequonveut » juste avant le @, ainsi toto+nimportequoi@gmail.com est la même chose que toto@gmail.com, cela peut-être très utile pour savoir de qui viennent les spams, ou encore savoir qui vend illégalement des listes d’adresses. J’ai ainsi prit l’habitude à chaque inscription sur un site ou une newsletter de rajouter le nom du site après le +, exemple : monprenom.monnom+gizmodo.fr@gmail.com . Si un jour je reçois du spam sur cette adresse je saurais donc à qui m’en prendre ! Bien entendu les applications sont multiples et variées, notamment avec l’application des filtres ! Ainsi quand j’envois un mail à monprenom.monnom+note@gmail.com je le reçois directement (grâce à un filtre) dans mon dossier Notes… De la même façon il est possible de rajouter des points n’importe où dans l’adresse, gmail ne fera pas la différence ! ex: mon.prenom.mon.n.o.m@gmail.com est l’équivalent de monprenom.monnom@gmail.com lui même équivalent à monprenommonnom@gmail.com !
Mais il y a un petit hic dans tout ça ! Beaucoup de sites n’acceptent pas des emails avec des + ou d’autres caractères spéciaux !
Valide ou pas valide alors ???
Normes
Voici donc un petit tuto bien sympathique en php, une vérification de mail…
« Mais il en traine plein sur internet ??? »
et même PHP fournit une fonction déjà toute prête pour vérifier les mails :
filter_var($email, FILTER_VALIDATE_EMAIL)
Et oui, mais les adresses emails sont régis par des normes RFC5321 et RFC5322, des documents imbuvables que personne ne lit jamais… Du coup, il est rare qu’un regexp soit en accord avec ces normes, à vrai dire, il semblerait bien qu’il n’y en ai qu’un seul qui respecte ces normes (celui de Michael Rushton). La fonction filter_var avec FILTER_VALIDATE_EMAIL ne prenait pas du tout en compte ces normes là et majorité d’emails sortant de l’ordinaire étaient invalides pour elle. Depuis le 2 avril 2010 (révision 297350 de php), ce regexp est inclut directement avec cependant quelques petites suppressions dans FILTER_VALIDATE_EMAIL. Toutefois, la version de PHP contenant cette mise à jour n’et pas encore sortie.
Ce que nous allons faire aujourd’hui est utiliser ce regexp pour vérifier nos adresses emails, mais également vérifier si le nom de domaine utilisé dans l’adresse email existe et est enregistré sur les serveurs DNS.
Application
Le Regexp
Voici le fameux regexp en php (accrochez-vous bien) :
$regexp = '/^(?!(?:\x22?(?:\x5C[\x00-\x' .'7E]|[^\x22\x5C])\x22?){255,})(?!(?:\x' .'22?(?:\x5C[\x00-\x7E]|[^\x22\x5C])\x2' .'2?){65,}@)(?:[\x21\x23-\x27\x2A\x2B\x' .'2D\x2F-\x39\x3D\x3F\x5E-\x7E]+|(?:\x2' .'2(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21\x' .'23-\x5B\x5D-\x7F]|\x5C[\x00-\x7F])*\x' .'22))(?:\.(?:[\x21\x23-\x27\x2A\x2B\x2' .'D\x2F-\x39\x3D\x3F\x5E-\x7E]+|(?:\x22' .'(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21\x2' .'3-\x5B\x5D-\x7F]|\x5C[\x00-\x7F])*\x2' .'2)))*@(?:(?:(?!.*[^.]{64,})(?:(?:xn--' .')?[a-z0-9]+(?:-[a-z0-9]+)*\.){0,126}(' .'?:xn--)?[a-z0-9]+(?:-[a-z0-9]+)*)|(?:' .'\[(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[' .'a-f0-9]{1,4}){7})|(?:(?!(?:.*[a-f0-9]' .'[:\]]){8,})(?:[a-f0-9]{1,4}(?::[a-f0-' .'9]{1,4}){0,6})?::(?:[a-f0-9]{1,4}(?::' .'[a-f0-9]{1,4}){0,6})?)))|(?:(?:IPv6:(' .'?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){' .'5}:)|(?:(?!(?:.*[a-f0-9]:){6,})(?:[a-' .'f0-9]{1,4}(?::[a-f0-9]{1,4}){0,4})?::' .'(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,' .'4}:)?)))?(?: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';'
Alors ça rigole moins là hein ! Bon je ne vais pas détailler l’expression, sachez juste qu’elle permet de vérifier notre mail selon les dernières normes RFC (sauf cas particulier non connus).
Et maintenant on va faire appel à une fonction bien pratique en php : checkdnsrr qui va vérifier l’enregistrement DNS en champs MX (domaines pour les mails) de ce qu’on lui passe en paramètre. « afzxgdegedsgesd.com » renverra FALSE tandis que « gmail.com » renverra TRUE :
$domain=substr(strchr($email,'@'),1); //on récupère la partie après le dernier @ if(checkdnsrr($domain,'MX')) //on vérifie l'enregistrement return true; //tout est bon on retourne TRUE
Notre fonction complète sera donc :
function checkMail($mail){ $regexp = '/^(?!(?:\x22?(?:\x5C[\x00-\x' .'7E]|[^\x22\x5C])\x22?){255,})(?!(?:\x' .'22?(?:\x5C[\x00-\x7E]|[^\x22\x5C])\x2' .'2?){65,}@)(?:[\x21\x23-\x27\x2A\x2B\x' .'2D\x2F-\x39\x3D\x3F\x5E-\x7E]+|(?:\x2' .'2(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21\x' .'23-\x5B\x5D-\x7F]|\x5C[\x00-\x7F])*\x' .'22))(?:\.(?:[\x21\x23-\x27\x2A\x2B\x2' .'D\x2F-\x39\x3D\x3F\x5E-\x7E]+|(?:\x22' .'(?:[\x01-\x08\x0B\x0C\x0E-\x1F\x21\x2' .'3-\x5B\x5D-\x7F]|\x5C[\x00-\x7F])*\x2' .'2)))*@(?:(?:(?!.*[^.]{64,})(?:(?:xn--' .')?[a-z0-9]+(?:-[a-z0-9]+)*\.){0,126}(' .'?:xn--)?[a-z0-9]+(?:-[a-z0-9]+)*)|(?:' .'\[(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[' .'a-f0-9]{1,4}){7})|(?:(?!(?:.*[a-f0-9]' .'[:\]]){8,})(?:[a-f0-9]{1,4}(?::[a-f0-' .'9]{1,4}){0,6})?::(?:[a-f0-9]{1,4}(?::' .'[a-f0-9]{1,4}){0,6})?)))|(?:(?:IPv6:(' .'?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){' .'5}:)|(?:(?!(?:.*[a-f0-9]:){6,})(?:[a-' .'f0-9]{1,4}(?::[a-f0-9]{1,4}){0,4})?::' .'(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,' .'4}:)?)))?(?: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'; if(!preg_match($regexp, $mail)) return false; $domain=substr(strchr($email,'@'),1); return checkdnsrr($parts[1], "MX"); }
Elle est jolie, non ?
Le mail suivant est donc valide : $%^%JerE_my*&&1@gmail.com
Mais celui là non : !def!xyz%abc@@gmail.com
Conclusion
Vous savez désormais créer une fonction de validation mail digne de ce nom, quelques améliorations peuvent y être apportée, principalement vérifier si la partie après le dernier @ est une IP (ipv4, ipv6, …) ou un domaine composé, dans ce cas il ne faut pas faire la vérification de champs MX car elle n’aboutira à rien.
Mais au moins n’importe qui pourra entrer ces adresses spéciales sans que ce ne soit considéré comme invalide. Du moins en attendant que le dernier FILTER_VALIDATE_EMAIL intégré à PHP ne sorte.
octobre 8th, 2010 at 23 h 53 min
Je vous remercie beaucoup pour ces informations d’une grande clarté. Bonne continuation. Amicalement