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

Messages postés
3
Date d'inscription
vendredi 29 octobre 2004
Statut
Membre
Dernière intervention
26 octobre 2005
- - Dernière réponse : verdy_p
Messages postés
203
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
203
Date d'inscription
vendredi 27 janvier 2006
Statut
Membre
Dernière intervention
29 janvier 2019
-
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
507
Date d'inscription
mercredi 30 juin 2004
Statut
Membre
Dernière intervention
29 juillet 2009
1 -
simplement brillant!
renardausoleil
Messages postés
1
Date d'inscription
vendredi 9 janvier 2009
Statut
Membre
Dernière intervention
27 janvier 2009
-
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
507
Date d'inscription
mercredi 30 juin 2004
Statut
Membre
Dernière intervention
29 juillet 2009
1 -
Beau travail! 10/10!!!
cs_JLN
Messages postés
373
Date d'inscription
samedi 1 juin 2002
Statut
Membre
Dernière intervention
17 juin 2013
-
Une adresse du type toto.titi@tata.com est donnée comme mauvaise même si elle existe.