TESTER LA VALIDITÉ D'UNE ADRESSE EMAIL SANS ATTENDRE DE RÉPONSE DE L'INTERNAUTE

ttestt123123 Messages postés 3 Date d'inscription vendredi 29 octobre 2004 Statut Membre Dernière intervention 26 octobre 2005 - 11 oct. 2005 à 19:14
verdy_p Messages postés 202 Date d'inscription vendredi 27 janvier 2006 Statut Membre Dernière intervention 29 janvier 2019 - 17 mars 2009 à 21:12
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/34158-tester-la-validite-d-une-adresse-email-sans-attendre-de-reponse-de-l-internaute

verdy_p Messages postés 202 Date d'inscription vendredi 27 janvier 2006 Statut Membre Dernière intervention 29 janvier 2019
17 mars 2009 à 21:12
Ce qui me choque dans l'expression régulière que tu donnes:

$regexp = "^([_a-z0-9-]+)(\.[_a-z0-9-]+)*@([a-z0-9-]+)(\.[a-z0-9-]+)*(\.[a-z]{2,4})$";

C'est le fait que tu tentes de valider la chaîne AVANT l'arrobe (@). Les restrictions que tu imposes ne sont pas valides, tous les caractères autorisés pouvant apparaître dans n'importe quel ordre, à n'importe quelle position et peuvent apparaître plusieurs fois. Pourquoi interdire donc deux points successif ou un point à la fin?

De plus, la casse des lettres AVANT l'arrobe est significative (rien ne garantit que le système cible ignore les différences de casse dans le nom d'utilisateur, même si c'est la plupart du temps vrai). Donc une adresse "machin@example.org" est DISTINCTE de "MACHIN@example.org", alors que la casse est ignorée dans le nom de domaine après l'arrobe. Il est cependant hautement recommandé de créer des comptes utilisateurs tout en minuscules afin d'éviter tout problème, avant que ceux-ci n'utilisent ce nom dans une adresse email.

Il n'est pas autorisé de modifier librement celle-ci dans un logiciel (donc une opération de "tolower($adresse_email)" est clairement invalide) dans le seul but d'exprimer l'adresse sous une forme "canonique" (en revanche on peut le faire pour le nom de domaine dont la forme recommandée est en minuscules.)

Attention aussi aux IDN : les caractères Unicode sont autorisés dans les noms de domaine (pour les valider, il faut utiliser les algorithmes de l'IDN, et éventuellement rechercher les caractères autorisés dans chaque registre TLD ou registre de second niveau, chaque niveau pouvant apporter des restrictions différentes pour chaque label séparé par un point. Si l'IDN est utilisé, on peut valablement convertir le nom de domaine sous une forme canonique n'utilisant que les minuscules ASCII, chiffres et signe moins (plus le point séparateur de labels pour les différents niveaux de domaine) grace à cet algorithme (après conversion, chaque label séparé par un point peut commencer par "xn--", les deux signes moins successifs étant réservés à cet usage)

La norme contient une liste de caractères autorisés qui sont tous sans restriction. Bref tout ce qui est avant l'arrobe ne doit être QUE:

"^([-_a-zA-Z0-9&~#'{|`_^=+}$*./]+)@(([a-zA-Z0-9-]+)(\.[a-zA-Z0-9-]+)*(\.[a-z]{2,4}))$"

De plus, le nom de domaine indiqué derrière l'arrobe peut aussi être une adresse (éventuellement entre crochets pour IPv6); en fait ce qui est demandé dans SMTP c'est que le nom puisse se résoudre comme un nom d'hôte pour le protocole "MX": ce nom d'hôte devant seulement supporter une requête DNS, donc permettre d'accéder au serveur DNS tournant à cette adresse, afin de récupérer son adresse "MX". L'adresse indiqué est donc celle de l'hôte d'un serveur DNS (pas nécessairement, et en fait très rarement celle de l'hôte du serveur SMTP).

De cette analyse cela extrait les chaines $1 (nom d'utilisateur) et $2 (nom d'hôte DNS). Chaque chaîne doit alors être traitée séparément. De la première chaine il n'y a rien à traiter, ce nom d'utilisateur est opaque et doit être conservé tel quel. Le nom d'hôte DNS en revanche doit vérifier celle d'un nom d'hôte valide:
- soit une adresse IPv4 valide (au format décimal avec 3 points séparateurs et 4labels numériques entre "0" et "255")
- soit une adresse IPv6 valide entre "[crochets]" au format hexadécimal, et dont la casse n'est pas significative; mais cette adresse peut être mise dans un format canonique avec un nombre variable de sous-labels hexadécimaux (entre "0000" et "FFFF" sur 1 à 4 chiffres) séparés par des ":", en une seule suite contenant exactement 8 sous-labels, ou en deux suites séparées par un unique "::" chaque suite comprenant de 0 à 7 sous-labels, mais dont le total des sous-lbels dans les deux suites ne peut excéder 8.
- soit un nom de domaine valide (comprenant au moins deux labels pour les adresses valides sur Internet, les labels étant séparés par des "."). Pour le valider, on doit d'abord scinder ce nom en autant de sous-labels, dont aucun ne doit être vide. Ensuite, si un label contient des caractères non ASCII, on doit le convertir avec l'algorithme Punycode en nom de label ASCII pur, puis contrôler sa longueur qui ne peut excéder 63 caractères chacun. Le label ASCII obtenu (composé de lettres ASCII dont la forme canonique est en minuscules, chiffres ASCII et signes moins ASCII) a ensuite des restrictions sur son format: il doit être composé de sous-labels séparés par de "-", dont ni le premier ni le dernier ne peut être vide. La dernière restriction à contrôler est éventuellement de rechercher si le nom de domaine est valide ou enregistrable sur Internet; c'est assez facile pour le label TLD (le dernier) à condition de connaître la liste des TLD valides (et de la mettre à jour car cette liste est évolutive), les seules restrictions actuelles étant qu'un TLD ne contient que des labels avant au moins deux caractères, et le TLD ne peut être entre "0" et "255" exactement (sans chiffre "0" en excès) car ils sont réservés pour représenter les adresses IPv4 (cette restriction ne concerne QUE le dernier label TLD mais ne s'applique PAS aux labels des autres niveaux, ainsi le domaine complet "0.com" est valide, mais pas "com.0").

L'étape suivante de validation demande une requête de résolution DNS pour savoir si le nom de domaine possède un enregistrement "MX" vers un nom de domaine ou d'hôte valide (avec la même syntaxe): noter que cette résolution peut conduire à autre nom de domaine, ou une adresse IPv4 ou une adresse IPv6 entre crochets; si un nom de domaine est retourné, on le valide de la même façon que dansle paragraphe précédent, mais il n'est PAS nécessaire que ce nom de domaine se résolve en une adresse IPV4.

Donc attention à ne pas utiliser gethostbyname() sans précaution pour faire cette validation, sauf si votre logiciel d'envoi de courrier ne sait envoyer un courriel que vers les hôtes SMTP en IPv4: mettez-le à jour pour qu'il sache aussi envoyer un courriel vers un serveur SMTP en IPv6; sendmail sait le faire depuis un bon moment, mais si vous utilisez votre propre script d'envoi de courriel avec une socket, assurez-vous de bien connaitre le protocole SMTP et de savoir ouvrir une socket vers un hôte IPv6, en consultant le format de l'adresse retourné par gethostbyname(), et en utilisant bind() avec les bons paramètres correspondant à ce format et avec le protocole TCP et le port 25 (attention aussi à la longueur de la structure d'adresse passée en argument). Si votre serveur d'envoi de courrier ne sait pas le faire, transmettez les email vers le serveur STMP de votre propre FAI (tous les FAIs savent relayer des courriel vers les hôtes SMTP en IPv6) et faite lui confiance (mais appliquez la charte d'utilisation pour ne PAS envoyer de spam même dans ce cas): il y a beaucoup moins de risque que votre FAI soit blacklisté si vous utilisez son serveur SMTP comme relai, que si vous envoyez vous-même le message vers le serveur STMP que vous avez résolu.

Cela veut dire qu'au delà de la phase de validation, il n'est pas nécessaire que vous réalisiez vous-même:
- la résolution de nom de domaine présent dans l'adresse email vers un nom de serveur DNS pour y rechercher l'adresse MX (attention: elle peut changer au cours du temps, ne gardez pas cette adresse de façon permanente dans un cache excessif, mais respectez la durée de validité retournée, donc faite confiance aux librairies ou fonction de votre système pour effectuer cette résolution en appliquant les règles prescrites pour la gestion des caches de clients DNS!),
- ni la résolution de l'adresse MX retournée en nom d'hôte SMTP (celle-ci peut aussi changer au cours du temps: même remarque pour la mise en cache),
- ni la connexion effective à ce serveur SMTP (par le protocole approprié)

Noter aussi que certains serveurs DNS ne sont joignables directement QU'avec IPv6, ce que la plupart des connexion Internet des particuliers ne savent pas faire (faute de support dans les sessions de transport PPP): utilisez les serveurs DNS donnés par votre FAI pour relayer (via IPv4) vos demandes de résolution de noms de domaines en noms d'hôte IPv4 ou IPv6 (puisque les serveurs DNS relais donnés par votre FAI savent interroger les serveurs DNS de certains domaines accessibles uniquement en IPv6 et pas en IPv4): si la résolution vous donne une adresse IPv6, il vous faudra trouver un relai 6to4 ou Teredo pour vous connecter à la cible indiquée, mais ce sera très lent. Envoyez plutôt vos mails au serveur SMTP de votre FAI qui dispose, lui d'un accès direct à IPv6.

Toute cette validation ne suffit pas encore; il faut, avant de continuer à utiliser cette adresse "prévalidée", vous assurer d'avoir l'accord de son propriétaire pour lui adresser du courrier (surtout si vous comptez le faire de façon automatique). La gestion correcte d'une liste de diffusion est une tâche ardue techniquement car elle doit respecter des normes de bonne conduite assez strictes (et un fonctionnement excellent dénué de toute erreur!), sinon vous risquez d'être blacklisté et de ne plus pouvoir envoyer de messages même à ceux dont vous aviez l'accord et attendent vos messages avec impatience ! En général il vaut mieux externaliser la gestion de vos listes de diffusion chez un fournisseur de messagerie tiers, gérant correctement et efficacement toutes les souscriptions (et désinscriptions) volontaires aux listes de diffusion et vous permettant aussi d'effacer toute adresse qu'on vous signalera (donc attention au choix du prestataire: il doit aussi respecter des normes pour garder vos listes de diffusion totalement privées).
En général, abstenez-vous d'inscrire vous même des adresses dans les listes gérées par des prestataires externes: laissez les gens y souscrire eux-même (contentez-vous de mentionner l'adresse de souscription à votre liste avec une page web explicative et les infos relatives aux règles d'usage). Dans ce cas, ce n'est pas à vous de valider les adresses mais à votre fournisseur.

Ne validez donc localement QUE les adresses pour lesquelles vous effectuerez des communications strictement personnelles (aucun envoi en groupe vers ces adresses individuelles que vous gérez vous-même, pas même pour leur envoyer des newsletters et autres infos relatives à votre site, et surtout pas pour ne leur envoyer que de la pub vers d'autres sites ou produits "partenaires").

Si vous avez des "partenaires", créez des listes de diffusion distinctes chez votre fournisseur de liste, faute de quoi, tout abus de la part de partenaire dans les contenus de leurs messages que vous allez relayer pour eux risquerait de compromettre votre propre service et le voir lui-même blacklisté. Ne fusionnez surtout pas les contenus des listes pour vos propres communications à vos utilisateurs avec les listes pour les messages de vos "partenaires" (et d'une façon générale, demandez leur de vous envoyer une copie certifiée de leur envois pour que vous puissiez en contrôler et approuver le contenu, et ensuite effectuer la diffusion de ce message par votre liste externe).

Enfin il est indispensable que vous assuriez le secret absolu sur le contenu de vos listes (la liste des souscripteurs devrait être secrète, même pour ceux qui y sont inscrits volontairement, à moins que vous n'indiquiez explicitement, avant qu'ils y souscrivent eux-même, que la liste des utilisateurs sera accessible à tous les souscripteurs).

Ne changez surtout pas de politique de confidentialité ensuite (sauf pour en restreindre d'avantage l'accès en cas de constatation d'abus par certains de vos utilisateurs): l'accès aux adresses contenues dans une liste doit être d'autant plus sécurisé et restreint que celle-ci contient de plus nombreuses adresses: au delà d'une vingtaine d'adresses, cette liste doit devenir fermée et inaccessible même à vos souscripteurs (résistez fermement à leurs demandes, mais créez une liste plus ouverte seulement pour ceux qui en veulent à leurs risques et périls).
GillesWebmaster Messages postés 496 Date d'inscription mercredi 30 juin 2004 Statut Membre Dernière intervention 29 juillet 2009 1
27 janv. 2009 à 19:30
simplement brillant!
renardausoleil Messages postés 1 Date d'inscription vendredi 9 janvier 2009 Statut Membre Dernière intervention 27 janvier 2009
27 janv. 2009 à 01:17
Selon la RFC5322 (Internet Message Format):
a) Les caractères spéciaux &~#'{-|`_^=+}$*./ sont autorisés par les protocoles email (SMTP, POP et IMAP).
Certains logiciels et certains grands services de webmail ne les acceptent cependant pas tous, mais c'est leur problème ;)

b) Dans le nom d'utilisateur de l'adresse email, les caractères alphabétiques majuscules sont autorisés en SMTP, POP3 et IMAP et doivent interprétés comme différents des minuscules; exemple : xavier.martin@mondomaine.fr est différent de XaVier.marTIN@mondomaine.fr
Par contre, dans les noms de domaine, actuellement, il n'y a pas de différence entre majuscules et minuscules; les majuscules sont automatiquement converties en minuscules.

c) les extensions de nom de domaine peuvent comporter plus de 4 caractères (actuellement jusqu'à 5 caractères; exemple: .museum cf. http://about.museum/ ou .travel cf. http://www.travel.travel/ ) et demain peut-être plus.

CONCLUSION: Il faut donc corriger la ligne 6 en conséquence.
GillesWebmaster Messages postés 496 Date d'inscription mercredi 30 juin 2004 Statut Membre Dernière intervention 29 juillet 2009 1
19 sept. 2008 à 12:03
Beau travail! 10/10!!!
cs_JLN Messages postés 371 Date d'inscription samedi 1 juin 2002 Statut Membre Dernière intervention 17 juin 2013
18 juil. 2007 à 12:20
Une adresse du type toto.titi@tata.com est donnée comme mauvaise même si elle existe.
ukos Messages postés 56 Date d'inscription lundi 22 novembre 2004 Statut Membre Dernière intervention 27 mai 2008
24 août 2006 à 16:50
a et j'allai oublier !

Voici l'adresse d'une documentation sur tout les codes pouvant être utilisé dans les emails de retour, ces code permettant de retrouver le type d'erreur:

http://www.ietf.org/rfc/rfc1893.txt
ukos Messages postés 56 Date d'inscription lundi 22 novembre 2004 Statut Membre Dernière intervention 27 mai 2008
24 août 2006 à 13:59
a j'ai oublier les fonctions:
function get_mime_type(&$structure)
{
$primary_mime_type = array("TEXT", "MULTIPART","MESSAGE", "APPLICATION", "AUDIO","IMAGE", "VIDEO", "OTHER");
if($structure->subtype) {
return $primary_mime_type[(int) $structure->type] . '/' .$structure->subtype;
}
return "TEXT/PLAIN";
}

function get_part($stream, $msg_number, $mime_type, $structure false,$part_number false)
{

// CETTE FONCTION PERMET DE RECUPERER UNIQUEMENT LE TEXTE DU MAIL (PAS LES PIECES JOINTES)

if(!$structure) {
$structure = imap_fetchstructure($stream, $msg_number);
}
if($structure) {
if($mime_type == get_mime_type($structure)) {
if(!$part_number) {
$part_number = "1";
}
$text = imap_fetchbody($stream, $msg_number, $part_number);
if($structure->encoding == 3) {
return imap_base64($text);
} else if($structure->encoding == 4) {
return imap_qprint($text);
} else {
return $text;
}
}

if($structure->type == 1) /* multipart */ {
while(list($index, $sub_structure) = each($structure->parts)) {
if($part_number) {
$prefix = $part_number . '.';
}
$data = get_part($stream, $msg_number, $mime_type, $sub_structure,$prefix . ($index + 1));
if($data) {
return $data;
}
} // END WHILE
} // END MULTIPART
} // END STRUTURE
return false;
} // END FUNCTION

Have fun
ukos Messages postés 56 Date d'inscription lundi 22 novembre 2004 Statut Membre Dernière intervention 27 mai 2008
24 août 2006 à 12:43
Un autre methode un peu plus compliquer à réaliser et d'envoyer un email et d'analyser les éventuels retours (en imap) que tu pourrai avoir sur l'adresse Return-path (généralement postmaster@..)

Je l'ai fait et je recupère l'identifiant de l'erreur (x.x.x) et en deduit quel type d'erreur il sagit afin de mettre à jour ma base de contact.

La verification n'est pas "instantané" mais permet de savoir si l'email existe réélement, ou si sa boite est pleine etc...

Cdt

$mbox = imap_open ("{server:110/pop3}", "postmaster@???.com", "pass");

$headers = imap_headers ($mbox);

if ($headers != false) {
while (list ($key,$val) = each ($headers)) {
$count++;
$header = imap_headerinfo($mbox, $key+1, 100, 100);

$dateMail = date("d/m/Y", $header->udate);
$errorMail = get_part ($mbox, $key+1, "MESSAGE/DELIVERY-STATUS");
$errorMail = imap_utf8($errorMail);
$errorMail = nl2br(utf8_decode($errorMail));

## Retrouve l'erreur
$found = strpos($errorMail, "Status:");
$code = substr($errorMail, ($found+8), 5);
$first_code = substr($code, 0, 1);
$second_code = substr($code, 2, 1);
$third_code = substr($code, 4, 1);

$found = strpos($errorMail, "Final-Recipient:");
$reste= substr($errorMail, $found);
$found2 = strpos($reste, "
");
$email = substr($errorMail, ($found+24), ($found2-24));

## $code et $email sont retrouver ! Have fun

}
}
imap_close($mbox);
coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 44
24 avril 2006 à 15:12
kik3i1, selon les protocols associés aux mails : on ne peut pas savoir avec une cetitude de 100% si l'adresse existe, seul le domaine est vérifiable...
kik3i1 Messages postés 3 Date d'inscription vendredi 20 janvier 2006 Statut Membre Dernière intervention 12 juin 2006
24 avril 2006 à 14:52
Salut,
C'est moi ou bien ce script ne vérifie que le domaine de l'email à vérifier?
Car avec un email comme ieiezuruie87897ez@yahoo.com, cela retourne "l'email existe", et n'envoie pas de mail de test à une adresse valide (test avec plusieurs domaines, dont des gratuits (hotmail, voila,...) et plusieurs payants.)

Quelqu'un peut m'éclairer, svp?

Merci d'avance
roger_girardin Messages postés 1 Date d'inscription vendredi 20 janvier 2006 Statut Membre Dernière intervention 20 janvier 2006
20 janv. 2006 à 16:53
désolé mais j'ai pas résisté

@frdtech

en fait t'as même pas pondu une ligne de code

rog
frdtech Messages postés 4 Date d'inscription vendredi 4 juin 2004 Statut Membre Dernière intervention 21 octobre 2005
21 oct. 2005 à 09:21
Bonjour,
Comme je le dis en explication finale, ce code utilise le module Net_SMTP de PEAR. PEAR est un ensemble de bibliotèque de code PHP consolidées sous forme d'une extension dont l'installation et le maintient ont été automatisés. L'installation est très simple (plusieurs methodes, automatique, semi-auto, ou tu peux même recopier manuellement les fichiers mais attention aux dépendances dans ce cas). Ces bibliotèques sont très riches et permettent de multiplier la puissance de PHP (si, si, je l'assure!). L'installation et l'utilisation sont entièrement documentés sur http://pear.php.net/.
Si en PHP tu programmes ... alors PEAR tu dois connaitre !
peterklm Messages postés 15 Date d'inscription dimanche 22 décembre 2002 Statut Membre Dernière intervention 5 décembre 2005
18 oct. 2005 à 18:45
salut,
ton code a l'air interessant, mais ton code fait appet a un fichier "require 'Net/SMTP.php';"
il est où ce fichier. A moins que je comprenne pas. Merci de m'eclaircir là dessus.
cs_Antidote Messages postés 163 Date d'inscription lundi 29 septembre 2003 Statut Membre Dernière intervention 8 mai 2010
17 oct. 2005 à 19:14
J'avais installé ce type de vérification avec test des champs MX du nom de domaine et du port 25 etc...

C'est pour moi pas idéal.

1 - temps de test trop long
2 - genre les gros fournisseur d'email gratuit souvent ne réponde pas exemple laposte.net hotmail etc... et les emails se font jeté alors qu'il sont valide
NewSky Messages postés 86 Date d'inscription dimanche 27 janvier 2002 Statut Membre Dernière intervention 20 février 2009
13 oct. 2005 à 19:50
Merci de ta précision frdtech. Je ne m'étais po renseigner sur la classe. Il est sûr qu'il vaut mieu alors utiliser ta fonction qui semble être très intéressante. je l'a testerai volontier dans très peu de temps.

Bonne prog...
coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 44
13 oct. 2005 à 18:31
t'as le droit d'avoir un + dans ton adresse mail, c'est pas un caractère spé..
frdtech Messages postés 4 Date d'inscription vendredi 4 juin 2004 Statut Membre Dernière intervention 21 octobre 2005
13 oct. 2005 à 16:29
"com.cfdev.mail.verify.EmailVerifier" est une classe java commerciale de Activsoftware.
Le code de NewSky permet donc d'appeler une classe Java sur le serveur (à ne pas confondre avec une applet client).
J'ai regardé les spécifs de "com.cfdev.mail.verify.EmailVerifier", et cette classe propose exactement les même fonctions à l'exception qu'elle n'envoie pas de mail et surtout qu'il faut l'acheter.

Il est d'ailleur tout à fait possible de commenter les lignes 79 à 83 pour ne pas envoyer de mail. En effet si le serveur doit rejeter un destinataire, il le fait lors du rcptTo().
frdtech Messages postés 4 Date d'inscription vendredi 4 juin 2004 Statut Membre Dernière intervention 21 octobre 2005
13 oct. 2005 à 16:21
On peut tout à fait ajouter des caractères dans l'expression régulière (que j'avoue avoir recopié ailleur sans me poser de question).
Coucou747 pourais tu nous présiser l'utilité des caractères que tu suggères STP.
(il me semble avoir lu quelque part que le + était un caractère spécial qui permet d'ignorer une chaine ou quelque chose de la sorte.)
NewSky Messages postés 86 Date d'inscription dimanche 27 janvier 2002 Statut Membre Dernière intervention 20 février 2009
13 oct. 2005 à 14:05
J'ai trouvé ça sur le site de l'afup (http://www.afup.org), dans leur livre blanc (http://www.afup.org/docs/livre-blanc-php-entreprise-v2.pdf) au chapitre 6 titré "PHP, J2EE et .NET : plus
complémentaires que concurrents":

<?php
$ev = new Java("com.cfdev.mail.verify.EmailVerifier");
if ( $ev->validateEmailAddress("fake@hotmail.com")) {
print "valid email address";
} else {
print "invalid email address";
}
?>

Ca semblerai ne fonctionner qu'avec PHP5.

Je ne l'ai pas tester (pas eu le temps!).

Voilà donc une autre façon de tester la validité d'une adresse mail avec php.
coucou747 Messages postés 12303 Date d'inscription mardi 10 février 2004 Statut Membre Dernière intervention 30 juillet 2012 44
12 oct. 2005 à 15:06
ton expression régulière est foireuse : il manque les caractères +, } et { qui sont eutorisés...
ttestt123123 Messages postés 3 Date d'inscription vendredi 29 octobre 2004 Statut Membre Dernière intervention 26 octobre 2005
11 oct. 2005 à 19:14
Pas mal...
Rejoignez-nous