Tutoriel : Validation d’adresses e-mail en PHP

Alexandre Tranchant

Ce tutoriel va vous permettre de vérifier la validité d’une adresse e-mail. Il répond à un besoin croissant des webmasters qui souhaitent valider les adresses e-mail des internautes s’inscrivant sur leur site. Nous verrons différentes natures de validation, de la plus simple, par analyse syntaxique, à la plus complexe, par vérification du nom de serveur.

- Titre : Tutoriel : Validation d’adresses e-mail en PHP

- Auteur : Alexandre Tranchant

- Parution : 13 mai 2006

- Mise à jour : 9 juin 2020

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2006 Alexandre Tranchant. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Prérequis

- II. But

- III. De quelle validation d’adresse e-mail a-t-on réellement besoin ?

- IV. Validation rapide par expression régulière

- V. Validation avec la classe Mail de Pear

- VI. Validation avec interrogation du serveur

- VII. Quelle solution adopter ?

- VIII. Une solution très fiable : l'activation par retour d'e-mail !

- IX. Remerciements

I - Prérequis

- Connaître les bases de PHP.

- Savoir manipuler des chaînes de caractères.

- Connaître PEAR.

Il est conseillé de :

- savoir ce qu’est une expression régulière ;

- savoir installer un package PEAR ;

- connaître le principe d’un DNS.

II - But

Vous allez apprendre à valider une adresse e-mail :

- par expression régulière ;

- selon la norme RFC822 ;

- en vérifiant l’existence du nom de domaine ;

- par l’envoi d’un code d’activation.

III - De quelle validation d’adresse e-mail a-t-on réellement besoin ?

Le but de ce tutoriel est de répondre à cette question. Plusieurs méthodes y sont présentées. Chacune possède des avantages, chacune possède des défauts. Finalement, vous serez à même d’effectuer votre choix en ayant un maximum de cartes en main.

IV - Validation rapide par expression régulière

La validation par expression régulière est sans doute la plus rapide, mais la moins précise qu’il est possible d’observer. L’analyse de la syntaxe va déterminer si l’adresse e-mail entrée dans le formulaire est une adresse valide. La méthode consiste donc à vérifier si la valeur correspond bien au masque standard d’une adresse e-mail. Le piège, par contre, réside dans la définition exacte d’une adresse e-mail standard. Cette définition est régie par un ensemble de normes :

- RFC822 ;

- RFC2822 ;

- RFC1035.

Remarque : pour que la fonction mail() de PHP soit en mesure d’envoyer un e-mail, il est nécessaire que l’adresse entrée respecte la norme RFC2822.

Ces définitions sont extrêmement complexes. Et le lecteur, au départ, y découvre que les adresses e-mail suivantes sont parfaitement valides :

- user@host.network ;

- nom@domaine.extension ;

- « Full Name »@Domain ;

- « Joe & J. Harvey » <ddd@Org.ltd> ;

- toto.

Étonnant ? Mais est-ce ce dont le webmaster lamda a réellement besoin ? Il est communément admis qu’un internaute saisissant son adresse e-mail entre une adresse semblable à notre premier exemple : « nom@domaine.extension ». Si notre but est seulement de gérer ce type d’adresse alors une expression régulière relativement simple peut régler rapidement la question. Vous en trouverez une très bien réalisée par bobocop et traduite par mathieu.

<?php
// Auteur : bobocop (arobase) bobocop (point) cz
// Traduction des commentaires par mathieu

// Le code suivant est la version du 2 mai 2005 qui respecte les RFC 2822 et 1035
// http://www.faqs.org/rfcs/rfc2822.html
// http://www.faqs.org/rfcs/rfc1035.html

$atom   = '[-a-z0-9!#$%&\'*+\\/=?^_`{|}~]';   // caractères autorisés avant l'arobase
$domain = '([a-z0-9]([-a-z0-9]*[a-z0-9]+)?)'; // caractères autorisés après l'arobase (nom de domaine)

$regex = '/^' . $atom . '+' .   // Une ou plusieurs fois les caractères autorisés avant l'arobase
'(\.' . $atom . '+)*' .         // Suivis par zéro point ou plus
// séparés par des caractères autorisés avant l'arobase
'@' .                           // Suivis d'une arobase
'(' . $domain . '{1,63}\.)+' .  // Suivi par 1 &#224; 63 caractères autorisés pour le nom de domaine
// séparés par des points
$domain . '{2,63}$/i';          // Suivi de 2 &#224; 63 caractères autorisés pour le nom de domaine

// test de l'adresse e-mail
if (preg_match($regex, $email)) {
echo "L'adresse e-mail $email est valide";
} else {
echo "L'adresse e-mail $email n'est pas valide";
}
?>

La méthode consiste à écrire une expression régulière, tester avec la fonction preg_match la validité de l’adresse e-mail passée en paramètre. La fonction retourne vrai si l’adresse e-mail est valide.

Cet exemple est extrait de la FAQ PHP en date du 18 mai 2006. La FAQ PHP est régulièrement mise à jour par un constant enrichissement de son contenu. N’hésitez pas à la consulter pour obtenir une éventuelle version plus à jour.

V - Validation avec la classe Mail de Pear

Lors du paragraphe précédent, nous avons vu la validation d’une adresse e-mail « simple » grâce à une expression régulière. Mais pour les adresses e-mail avec un entête, la fonction retourne « faux ». Alors qu’il n’en est rien.

PEAR propose une classe Mail_RFC822 permettant de récupérer un ensemble d’adresses e-mail valides dans un texte. Cette classe, plus lourde, permet de vérifier qu’une adresse e-mail est conforme à la RFC822. Après l’éventuelle installation de PEAR, ou du moins après le téléchargement des fichiers PEAR nécessaires.Vous pourrez faire appel à cette classe en faisant :

<?php
// Auteur : Communauté PEAR
// Mise en exemple par Alexandre TRANCHANT

//La variable $mail est-elle une adresse e-mail syntaxiquement valide ?
$mail='john.doe@example.org';

require 'PEAR.php'; //Appel de la bibliothèque PEAR
require 'Mail/RFC822.php'; //Appel de la bibliothèque Mail_RFC822

$lo_mail = Mail_RFC822::parseAddressList($mail, NULL, FALSE);

if(PEAR::isError($lo_mail)){
//$lo_mail est une erreur
//l'adresse n'est donc pas valide
echo $mail.'n\'est pas une adresse e-mail valide';
} elseif ($lo_mail[0]->host=='localhost'){
//le nom de domaine de cette adresse est localhost
//dans cet exemple on refuse tout domaine local!
echo $mail.'n\'est pas une adresse e-mail valide';
} else {
echo $mail.' est une adresse e-mail valide';
}

//Debogage :
print_r($lo_mail);

?>

Voici les résultats de quelques tests :

VI - Validation avec interrogation du serveur

Les deux paragraphes précédents permettent uniquement de savoir si l’adresse e-mail est syntaxiquement valide. Mais rien ne garantit que le nom de domaine donné existe réellement. Pour ceux qui voudraient aller encore plus loin, et vérifier cela, nous allons approfondir le sujet et tester l’existence du nom de domaine. Pour cela, nous allons vérifier que :

- l’adresse d’e-mail est syntaxiquement valide ;

- puis nous récupérons le nom de domaine ;

- puis nous testons si ce nom de domaine est valide.

La première étape est similaire au second exemple :

<?php
// Auteur : Communauté PEAR
// Mise en exemple par Alexandre TRANCHANT

//La variable $mail est-elle une adresse e-mail syntaxiquement valide ?
$mail='john.doe@example.org';

require 'PEAR.php'; //Appel de la bibliothèque PEAR
require 'Mail/RFC822.php'; //Appel de la bibliothèque Mail_RFC822

$lo_mail = Mail_RFC822::parseAddressList($mail, NULL, FALSE);

if(PEAR::isError($lo_mail)){
//$lo_mail est une erreur
//l'adresse e-mail n'est donc pas valide
echo $mail.'n\'est pas une adresse e-mail valide';
die();
} elseif ($lo_mail[0]->host=='localhost'){
//le nom de domaine de cette adresse est localhost
//dans cet exemple on refuse ce genre de mail !
echo $mail.'n\'est pas une adresse valide';
die();
} else {
echo $mail.' est une adresse e-mail SYNTAXIQUEMENT valide';
}

//$lo_mail contient l'adresse e-mail stockée dans un tableau

?>

La seconde étape extrait le nom de domaine de l'adresse e-mail entré :

<?php

/*
Voici le contenu de $lo_mail
Array
(
[0] => stdClass Object
(
[personal] =>
[comment] => Array
(
)

[mailbox] => john.doe
[host] => example.org
)

)*/

$ls_domaine=$lo_mail[0]->host;

//$ls_domaine contient example.org

?>

La dernière étape, plus complexe, va interroger le serveur distant. Pour cela, nous allons faire appel à une autre classe de la bibliothèque PEAR :

<?php

//Rappel : La valeur ci-dessous a normalement été initialisée dans la partie 2 du script
$ls_domaine = 'developpez.com';

//Inscrivez dans ce tableau les serveurs de noms de votre FAI.
$la_serveur_de_nom=array(
'212.27.32.5',      //Adresse IP du serveur de noms primaire de mon FAI (Free)
'212.27.32.176',    //Adresse IP du serveur de noms secondaire de mon FAI (Free)
'212.27.32.177'     //Adresse IP du serveur de noms tertiaire de mon FAI (Free)
);

//Appel de la bibliothèque PEAR : Net DNS
require_once 'Net/DNS.php';

//Les fonctions ne peuvent pas s'appeler de fa&#231;on statique cette fois
//On crée donc une instance de classe Net_DNS_Resolver
$lo_resolver = new Net_DNS_Resolver();

//Décommentez cette ligne pour afficher le débogage
//$lo_resolver->debug=1;

//On précise nos noms de serveurs
$lo_resolver->nameservers=$la_serveur_de_nom;

//On lance une requête, on précise MX pour identifier un éventuel serveur de mail
$lo_response = $lo_resolver->query($ls_domaine,'MX');

//on teste la réponse
if ($lo_response) {
foreach ($lo_response->answer as $lo_rr) {
//On affiche le résultat pour l'exemple, mais c'est inutile dans l'absolu
$lo_rr->display();
echo "Nom de serveur de mail $ls_domaine valide";
}
} else {
echo "Nom de serveur de mail $ls_domaine inconnu";
}
?>

Désormais, nous savons si l'adresse e-mail est valide et si le nom de domaine répond bel et bien. Vous pouvez trouver sur le web plusieurs variantes à cette méthode. Certaines vont envoyer un ping via icmp sur le port 8 de la machine. D'autres méthodes vont tester la présence d'un serveur web sur le port 80. Mais ces solutions sont moins fiables, voire médiocres. En effet, un firewall peut occulter ces ports et bloquer toute réponse.

Pour cela, il faut une méthode fiable. Et les serveurs de noms sont là pour nous donner toutes les informations que nous souhaitons ! Alors nous allons les interroger au moyen d'une autre classe PEAR : Net_DSN. La classe Net_DSN, ouvre un socket dans le but de directement interroger les serveurs de noms. Et ceci garantit des résultats fiables contrairement à une interrogation de ports aléatoires.

VII - Quelle solution adopter ?

Comme nous avons pu le voir, la validation d'une adresse e-mail peut-être plus ou moins complexe à mettre en œuvre. En fait, le plus important – comme d'ailleurs dans tout développement – est de bien discerner nos propres besoins et de choisir la solution la plus adaptée.

- La première méthode est très rapide, peu gourmande en ressources, et gère 99,99 % des adresses e-mail d'internautes.

- La seconde méthode permet de stocker des adresses e-mail de la façon suivante : « Prénom Nom » <prenom.nom@domain.ltd>.

- La dernière méthode est assez lourde en ressources, mais permet des contrôles supplémentaires.

VIII - Une solution très fiable : l'activation par retour d'e-mail !

Ces trois méthodes ont chacune défauts et avantages, mais elles ne vous garantissent qu'une chose : votre serveur ne tentera pas d'envoyer un e-mail alors que l'adresse est syntaxiquement fausse, ou que le nom de domaine n'est que pure fiction. En effet, rien ne garantit que l'adresse e-mail entrée par l'internaute ne soit pas une adresse « bidon » appartenant à une malheureuse tierce personne, voire à personne !

C'est pourquoi, désormais, les webmasters vérifient l'adresse e-mail, puis stockent l'utilisateur dans une base de données. Ils joignent à cet utilisateur un code d'activation aléatoirement généré. Cependant les webmasters ne permettent pas encore à l'internaute d'utiliser leur site. Par exemple, pour une inscription sur un forum, l'utilisateur est enregistré, mais n'a pas encore l'autorisation de poster de messages, de voter, etc. En fait, les webmasters envoient un e-mail à l'adresse fournie : cet e-mail contient le code d'activation. Si l'internaute a fourni sa véritable adresse, alors il recevra l'e-mail contenant le code d'activation. Il sera en mesure de se rendre sur le site, et d'activer son compte via un formulaire ou un lien. C'est après vérification du code que son compte s'activera. Si tel n'est pas le cas, généralement, à court terme, l'inscription est supprimée de la base de données.

En conclusion, choisissez l'une des trois méthodes. Si l'adresse e-mail est syntaxiquement correcte, alors envoyer un e-mail contenant un code d'activation vous garantira que l'internaute a bel et bien entré sa propre adresse.

IX - Remerciements

Remerciements à Mathieu et Yogui pour leur relecture technique et à Claude pour sa relecture orthographique et la mise au gabarit.