SOCIÉTÉ

BLOGS

Toi, tu sais ce que c'est qu'un e-mail ?

14.12.2009
par Olivier Deschanels

Comme Luce et Henry qui découvraient l'e-mail dans la fameuse publicité AOL, il arrive que nous ayons quelques difficultés avec les adresses e-mail.

Effectivement si la saisie, l'affichage ou encore l'impression d'une adresse e-mail ne pose aucun souci, l'affaire se complique lorsque l'on désire rechercher une adresse e-mail stockée dans un champ de la base de données. La faute en incombe à l'arobase (@) qui est à la fois indispensable dans une adresse e-mail et le caractère joker de 4D, permettant de remplacer n'importe quelle suite de caractères.

 

Le choix du caractère arobase en tant que joker dans 4D a été fait dans la première version de 4D à une époque où les e-mails n'étaient pas encore inventés et où Luce et Henry regardaient Starsky et Hutch et Champs Elysées à la télé au lieu d'essayer de "mieux communiquer" !
 

Le souci est donc la double signification de l'arobase qui perturbe la recherche dans 4D. En effet si l'on ne coche pas la préférence permettant de lever l'ambigüité, on ne peut pas rechercher un e-mail. Mais si l'on coche la préférence, on ne peut plus faire une recherche avec un arobase au centre d'un critère de recherche.

Quelles sont les solutions possibles pour répondre aux deux besoins ?
La première solution, la plus fréquemment rencontrée, est de remplacer l'arobase par un dièse dans le champ de stockage. C'est facile à faire, et cela ne provoque presque aucun changement dans le code si ce n'est quelques appels à la commande Remplacer chaine. L'inconvénient majeur est qu'il faut penser à convertir la chaine avant tout affichage, export, impression ...

Ma réflexion est partie de ce constat : quitte à devoir convertir et transformer l'adresse e-mail en vue de son stockage, n'y a-t-il pas moyen d'aller plus loin et de profiter de l'occasion pour envisager d'autres fonctionnalités ?

Qu'est qu'une adresse e-mail ?

Elle est constituée de deux parties séparées par la fâcheuse arobase.

La première partie est le nom de l'utilisateur, ou plus exactement quelque chose qui s'en approche : on peut aussi bien avoir luce.henry que zorglube21 ou a.b ...

La seconde partie de l'adresse e-mail est le nom de domaine du serveur smtp hébergeant le service de messagerie. Ma proposition est de stocker non pas l'adresse e-mail directement mais les deux parties dans deux champs distincts.
En lisant ces lignes, pour ceux qui me connaissent bien ou qui ont assisté à mes formations, vous vous dites qu'il est temps que je prenne des vacances car cette proposition va à l'encontre des principes d'économie de champs que je préconise habituellement ! Pour les vacances, je suis preneur si vous m'en obtenez en plus ...

Pourquoi ce choix de deux champs ?
Ce découpage en deux champs permet de résoudre le problème de la recherche, avec certes une conversion nécessaire mais pas vraiment plus pénalisante que la solution avec le simple remplacement de caractère.

Oui, allez vous me dire, mais il faut découper en deux l'adresse e-mail ce qui nécessite au minimum l'utilisation de la commande Position et deux appels à la commande Sous chaine.

Vous avez raison, le traitement est plus complexe qu'un simple remplacement, mais dans ma réflexion j'intègre une autre notion en prenant un peu de recul face à la problématique.

 

Lorsqu'une adresse e-mail est saisie (ou importée) dans ma base de données, je ne me contente pas de recueillir l'adresse. En effet avant d'accepter l'adresse proposée, je contrôle que cette adresse est valide. Pour faire ce contrôle, quelle que soit la méthode, je me trouverai dans l'obligation à un moment ou un autre de séparer l'adresse e-mail en deux parties et ensuite de vérifier que chaque partie répond bien aux règles qui régissent les adresses e-mail.
Pour faire ce contrôle, j'utilise les expressions régulières à travers le code suivant :

 

C_TEXTE($1;$emailAddress;email_username;email_domain)
C_BOOLEEN($0)
C_TEXTE($pattern)

$emailAddress:=$1
$0:=Faux
$pattern:="^([^@]|\\S+)@((?:[-a-z0-9]{1,63}+\\.)+[a-z]{2,4})$"`Contrôle conforme au RFC 2181
TABLEAU ENTIER LONG($_position;0)
TABLEAU ENTIER LONG($_length;0)
Si (Trouver regex($pattern;$emailAddress;1;$_position;$_length))
    Si ($_length{0}=Longueur($emailAddress))
        email_username:=Sous chaine($emailAddress;$_position{1};$_length{1})
        email_domain:=Sous chaine($emailAddress;$_position{2};$_length{2})
        $0:=Vrai
    Fin de si
Fin de si

Cette méthode accepte une adresse e-mail en paramètre 1 et retourne vrai ou faux suivant que l'adresse est valide ou non. Dans le cas où l'adresse est correctement formatée, la méthode renseigne également deux variables, email_username et email_domain, avec les deux parties de l'adresse.
Le contrôle effectué, si l'adresse est acceptable, j'ai directement les deux parties de l'adresse e-mail séparées et prêtes à être stockées. Le découpage ne m'a pas pris de temps supplémentaire, car c'est en fait un résultat du contrôle.
Lorsque vous désirerez rechercher une adresse e-mail il vous faudra aussi procéder à ce découpage, et cela peut vous sembler contraignant. Pour ma part, je me dis que ce découpage étant nécessaire, je vais passer par la même méthode de contrôle de l'adresse ce qui me permettra au passage de signaler éventuellement à l'utilisateur une erreur dans l'adresse qu'il souhaite trouver.
A ce stade de la démonstration, vous vous dites que cela est bien gentil, mais interdit de fait le dialogue de recherche standard de 4D.

Oui, c'est vrai... mais je ne me vois pas non plus laisser le dialogue standard de 4D et dire à mon utilisateur que s'il désire rechercher une adresse e-mail il faut qu'il tape un dièse au lieu d'une arobase. Et puis, de toutes manières, je ne laisse jamais l'éditeur de recherche standard de 4D aux utilisateurs finaux car je préfère leur proposer un éditeur spécialisé pour leur métier qu'un éditeur orienté base de données... mais ceci est un autre débat.

Outre la validation préalable de l'e-mail, quels autres avantages a ma proposition ?

  • Grâce aux deux champs, il est facile de ne rechercher que sur un nom de domaine. Par exemple, vous pouvez avoir envie de rechercher toutes les personnes ayant un nom de domaine correspondant à une société donnée. Cela facilite ainsi le regroupement par société sans avoir à réaliser une recherche par formule compliquée.
  • Si vous gèrez un site web recueillant beaucoup d'adresses e-mail, il vous sera aisé de fournir des statistiques des visiteurs par nom de domaine.
  • De même si vous devez trier les e-mail par nom de domaine, cela sera immédiat avec ma proposition à deux champs.
  • Il est fréquent d'avoir deux adresses e-mails chez deux fournisseurs différents, mais qui ont le même nom d'utilisateur, par exemple luce [dot] henryataol [dot] com et luce [dot] henryatfree [dot] fr. Faire le lien entre ces deux adresses e-mails et proposer de fusionner les comptes est plus facile si le nom d'utilisateur est déjà isolé dans un champ.
  • Certains services Web fournissent des adresses valables seulement quelques heures. Lorsque vous détectez des domaines de ce type, il est facile de les mettre dans une liste qui alimente la procédure de contrôle pour invalider certaines adresses. Si vous découvrez un nouveau service de ce type que vous jugez incompatible avec votre activité, il est rapide de faire une recherche sur les adresses utilisant ce nom de domaine pour faire le traitement adéquat.


La validation de l'adresse e-mail est une validation sur la forme de l'adresse ; mais rien n'empêche de créer une adresse ayant la forme voulue permettant de passer le contrôle, mais ne correspondant à rien de réel. Voici ce que je fais pour démasquer les adresses dont le nom de domaine ne possède pas de serveur smtp et qui ne sont donc que des erreurs... ou des leurres.
J'utilise pour mon contrôle la commande dig de l'unix (c'est inclus dans Mac OS X, mais cela peut s'installer sous Windows avec un exécutable nommé dig.exe) en passant les options -t MX.
Si dans le Terminal, à l'invite vous tapez dig -t MX gmail.com vous obtenez une réponse telle que ci-dessous :

 

; <<>> DiG 9.6.0-APPLE-P2 <<>> -t MX gmail.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 11668
;; flags: qr rd ra; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;gmail.com.            IN    MX

;; ANSWER SECTION:
gmail.com.        946    IN    MX    40 alt4.gmail-smtp-in.l.google.com.
gmail.com.        946    IN    MX    5 gmail-smtp-in.l.google.com.
gmail.com.        946    IN    MX    30 alt3.gmail-smtp-in.l.google.com.
gmail.com.        946    IN    MX    20 alt2.gmail-smtp-in.l.google.com.
gmail.com.        946    IN    MX    10 alt1.gmail-smtp-in.l.google.com.

;; Query time: 33 msec
;; SERVER: 212.27.40.240#53(212.27.40.240)
;; WHEN: Thu Dec 10 08:10:33 2009
;; MSG SIZE  rcvd: 150

On constate en lisant ce résultat qu'il existe bien des serveurs smtp (via les entrées dns de type MX), c'est à dire des serveurs de messagerie pour le nom de domaine gmail.com.

Si je teste à présent le domaine aupetitbonheurlachance.fr via le terminal :  dig -t MX aupetibonheurlachance.fr

J'obtiens la réponse suivante :

 

; <<>> DiG 9.6.0-APPLE-P2 <<>> -t MX aupetibonheurlachance.fr
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 39331
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 0

;; QUESTION SECTION:
;aupetibonheurlachance.fr.    IN    MX

;; AUTHORITY SECTION:
fr.            5400    IN    SOA    nsmaster.nic.fr. hostmaster.nic.fr. 2222230495 3600 1800 3600000 5400

;; Query time: 39 msec
;; SERVER: 212.27.40.240#53(212.27.40.240)
;; WHEN: Thu Dec 10 08:15:40 2009
;; MSG SIZE  rcvd: 102

On voit bien ici qu'il n'y a pas de section "ANSWER" donc que le nom de domaine ne possède pas de serveur smtp.

Il ne reste plus qu'à mettre cela en musique dans 4D. Voici le code utilisant la commande LANCER PROCESS EXTERNE :

 

C_TEXTE($in;$out;$erreur)
LANCER PROCESS EXTERNE("dig -t MX "+email_domain;$in;$out;$erreur)
Si (Position(";; ANSWER SECTION:";$out)>0)
    ` il existe un serveur MX
Sinon
    `il n'existe pas de serveur MX
Fin de si

Ce test est réalisé sur un simple mot pour ne pas compliquer inutilement ce billet de blog, mais pour une implémentation plus "rigoureuse" vous pouvez très bien coder une expression régulière qui se charge du contrôle précis de la réponse. Il vous faudra adapter également le code pour l'implémentation sous Windows en précisant le chemin d'accès à votre exécutable.

Pour finir je tiens à vous montrer deux captures d'écran :



Cette première image montre une implémentation simple du système à deux champs.



Cette seconde photo d'écran montre une implémentation où les adresses e-mails sont stockées dans une table dédiée. Ici pour un utilisateur donné nous avons plusieurs adresses e-mail possibles, donc plusieurs enregistrements dans la table eMail. Le champ niveau permet de déterminer quelle adresse utiliser en fonction du contexte. Le champ stmp_validation est un timestamp permettant de savoir si une adresse a été confirmée suite à un clic réalisé dans un e-mail envoyé à cette adresse précise. Ici plutôt que de noter la validation dans un booléen, nous avons choisi de mettre un timestamp afin de mémoriser la date et l'heure de la confirmation. Ainsi au bout d'une période donnée, on peut redemander la confirmation si les besoins de la base le nécessitent. 

J'achèverai ce billet en vous proposant de revoir l'adorable dispute entre Luce et Henry sur notre petit écran :

 

RSS 3 commentaire(s) pour ce billet
Je tombe par hasard sur votre édito sur l'adresse "mail" Excellent le billet sur ce sujet de l'arobase et de enregistrement en base de donnée. traité avec humour et efficacité ce qui ne gâte rien en ce monde,
Plus d'un an déjà que j'avais lu ton billet, et je l'ai relu hier soir avec le même grand intérêt. Séparer en deux champs l'adresse e-mail a été mis en place immédiatement. Cela semble ordinaire, de fait c'est simple ;-), mais encore faut-il avoir l'idée... Dès la première lecture, une table dédiée pour les adresses mails m'avait aussi convaincu, ce sera fait dès la première occasion. Là encore, c'était peut-être évident, mais soit avec une grande faculté d'anticipation, soit grâce à l'expérience. A la seconde lecture, il me vient une question. Dans le cadre de l'ouverture d'un compte pour un site Web, considères-tu que tester la validité du nom de domaine *et* qu'il possède bien un serveur smtp, est une sage précaution, ou bien est-ce absolument nécessaire, et si oui pourquoi ? (la procédure d'ouverture de compte soutend la notion de validation de l'adresse mail) Que tu sois remercié pour avoir éclairé ce sujet, finallement moins trivial qu'il n'y paraît.

Bonjour Jean-Jacques

 

Pour l'ouverture de compte sur le site web tout dépend le niveau de fiabilité des comptes que tu désires atteindre et surtout le "metier" de ton site web.

Si je prends l'exemple des sites marchands, presque tous passent par une vérification de l'e-mail via l'envoi d'un message contenant un lien permettant de valider la bonne réception de l'e-mail et de fait de la validité de l'adresse.

A mon avis un site professionnel ne peut pas faire l'économie de ce genre de test tant qu'une nouvelle technologie ne permettra pas de faire mieux :-)

 

Cordialement,

 

Poster un nouveau commentaire

  • Les adresses de pages web et de messagerie électronique sont transformées en liens automatiquement.
  • You may use [view:viewname] tags to display listings of nodes.
  • Each email address will be obfuscated in a human readable fashion or (if JavaScript is enabled) replaced with a spamproof clickable link.

Plus d'informations sur les options de formatage