Blog de développement

Adresses Mail dans un bon de commande

Dernière Modification le :
2024-01-16

Même si c'est là une des tâches les plus simples, il y a quelques chausse-trappes: La commande passe par l'OCR qui peut introduire des erreurs, dont les plus courantes sont l'introduction de blancs parasites, la substitution d'un point (.) par un blanc. Dans un certain nombre de cas, un mail de commande peut inclure, en sa queue, des discussions propres au client, entre collègues, avec des adresses internes qui ne nous intéressent pas.

Les informations extraites d'un Mail de Commande peuvent être classées en "fiables", "plutôt sures", "problématiques". Les adresses Mails extraites de la partie Mail sont fiables.

Pour eviter les mails à rallonge, lors de la reconstitution du mail, c'est à dire la concaténation du mail à proprement parler et du bon de commande sous la forme d'un unique fichier texte, on exise cette partie superflue en détectant la présence de "Message d'origine"

sTextBody  = myMail.TextBody
If  InStr(1,sTextBody , "Message d'origine",1) > 0 then sTextBody = Left (sTextBody , InStr(1,sTextBody , "Message d'origine",1))

La partie Mail à proprement parler...

Le composant le plus simple pour identifier les adresses désignées lors de l'envoi du mail est CDO.Message. Il est problématique sur d'autres points (tels que sujet et pieces jointes)... Pour l'adresse de l'expéditeur et les CC, ça marche...

Set myMail = CreateObject("CDO.Message")
Set strm = myMail.GetStream()
strm.Type = 2 'ADODB.StreamTypeEnum.adTypeText
strm.charset = "UTF-8" ' // par défaut. Si on connais le charset, on peut l'utiliser ici...
strm.LoadFromFile(sFilePath)
strm.Flush()
myMail.AutoGenerateTextBody = True
sMessage = sMessage & myMail.subject & VbCrLf
sSubject = SuperTrim(myMail.subject)
sFrom = SuperTrim(myMail.from)
sCC = SuperTrim(myMail.CC)

Une fois qu'on a ces mails là, on les a presque tous... Résiduellement, le bon de commande peut contenir une adresse de contact pour le suivi des paiements, et, maintenant pour l'envoi de la facture électronique.

L'erreur de blanc

Lors du passge par l'OCR (le vrai pas l'extraction de texte) 2 types d'erreur-de-blanc peuvent apparaitre: l'introduction d'un blanc superfétatoire, le remplacement d'un point par un blanc. Ce type d'erreur est plutôt facile à gérer.En effet, la queue de l'adresse mail est délimitée par @ et .fr (exemple). Notre expression régulière peut être assez permissive, et comparer les queues de mails 'corrigées' avec les autres queues de mail connues.

Les adresses mails, à l'origine (from...) ou en copie peuvent éventuellement se retrouver dans le corps du mail ou sur le bon de commande. En soit, ce n'est pas génant sauf si une erreur de blanc nous trompe dans l'identification.

La partie locale (local part), en pratique est de 2 types: simple@example.com et very.common@example.com

Expressions régulières

On trouve pléthore d'expressions régulières sur le NET. Notre problème diffère toutefois en ce qu'en reconnaissance d'image, il y a du bruit. Par exemple Cliente@ edf.fr, avec un blanc entre @ et le nom de domaine. Nos expressions régulières devront donc autoriser le blanc, quitte à le réduire à rien ou à le remplacer par un point...

Dans un range: pour autoriser le tiret - , il faut le mettre en tout premier. Pas bsoin d'escaper le . ni le blanc, qui apparaisent donc comme tel dans le range. Bien noter ici la présence du blanc entre _ et .

([a-z])([-a-z_ .]+)([-a-z0-9_ .]{1,5})(@)([-a-z0-9_ .]+)(\.com|\.fr|\.be|\.gmail)
	
	' // délimite la zone adresse email en autorisant les blancs \s. Ici une zone adresse commence nécessairement par une lettre.
	([a-z])([-a-z_ .]+)(@)([-a-z0-9_ .]+)(\.com|\.fr|\.be|\.gmail)
	
	' // zone adresse imposant au moins un point
	([a-z]+)(\.)([-a-z_ .]+)(@)([-a-z0-9-_ .]+)(\.com|\.fr|\.be|\.gmail)

Elimination d'adresses parasites

Dans un premier temps, on construit une expression régulière de mails qui ne nous intéressent pas car déjà connus ou inutiles, à commencer par ... Le(s) notre(s)

Identification du Jeu de Caractères (Charset)

Les jeux de caractères (charset) les plus utilisés sont UTF-8, ISO-8859-1 et us-ascii. Puisqu'on veut utiliser "CDO.message", autant identifier le jeu de caractères, si tant est, bien sûr, que cela ait un sens pour CDO. kLes constantes correspondantes sont listées par Microsoft Lire →

On tombe parfois sur des Jeux de Caractères malformés ou rares (Ex: iso-88, windows-1258, windows-125): on leur substitue ISO-8859-1 ou windows-1252. Si le charset est manquant, on met UTF-8.

Petit nettoyage: pour être sûr de lire le jeux de caractères (charset) malgré de rares erreurs de mal-formation, on nettoie un peu:

Public Function GetCharset (sFilePathValue)
	sContent_For_Charset  = ""
	GetCharset = ""
	sCharset_RegExp = ""
	Set objRegEx_Charset = New RegExp
	objRegEx_Charset.Global = True
	objRegEx_Charset.IgnoreCase = True
	objRegEx_Charset.Pattern = "(charset=)([a-z0-9-]+)"

	If objFSO.FileExists(sFilePathValue) then 
		Set objOpen = objFSO.OpenTextFile(sFilePathValue, ForReading, true)
		If NOT objOpen.AtEndOfStream then sContent_For_Charset  = ObjOpen.ReadAll
		objOpen.Close
		Set objOpen = nothing
	End If
	If InStr(1,sContent_For_Charset,"charset", 1) > 0 then
		sContent_For_Charset = Mid (sContent_For_Charset,  InStr(1,sContent_For_Charset,"charset", 1)-1,30)
		sContent_For_Charset = Replace (sContent_For_Charset, VbCr," " )
		sContent_For_Charset = Replace (sContent_For_Charset, VbLf, VbCrLf)
		sContent_For_Charset = Replace (sContent_For_Charset, VbLf & VbCrLf, VbCrLf)
		sContent_For_Charset = Replace (sContent_For_Charset, "=3D", """", 1, -1, 1)
		Do While InStr(1, sContent_For_Charset, "charset=" & VbCrLf, 1) > 0 OR InStr(1, sContent_For_Charset, "charset= ", 1) > 0  OR InStr(1, sContent_For_Charset, "charset=""", 1) > 0
			sContent_For_Charset = Replace (sContent_For_Charset, "charset=" & VbCrLf , "charset=", 1, -1, 1)
			sContent_For_Charset = Replace (sContent_For_Charset, "charset= ", "charset=", 1, -1, 1)
			sContent_For_Charset = Replace (sContent_For_Charset, "charset=""", "charset=", 1, -1, 1)
		Loop		
		Set colMatches = objRegEx_Charset.Execute(sContent_For_Charset)
		If colMatches.Count > 0 Then sCharset_RegExp = replace(colMatches(0), "charset=", "", 1, -1, 1)
	End If	

	GetCharset = LCase(sCharset_RegExp)
	'on remplace cp par windows
	if InStr(1,GetCharset,"cp", 1) = 1 then GetCharset= Replace(GetCharset,"cp", "windows-", 1, -1,1)
	'tous les ISO sont ramenés à ISO-8859-1
	If InStr(1,GetCharset,"iso-8859-2", 1) = 0  AND  InStr(1,GetCharset,"iso-88", 1) > 0 then GetCharset= "iso-8859-1"
	if InStr(1,GetCharset,"windows-12", 1) > 0 then GetCharset= "iso-8859-1"
	'seuls les charset elegibles à CDO sont admis, sinon on met une valeur par défaut
	Charset_List_For_CDO = ";big5;euc-jp;euc-kr;gb2312;iso-2022-jp;iso-2022-kr;iso-8859-1;iso-8859-2;iso-8859-3;iso-8859-4;iso-8859-5;iso-8859-6;iso-8859-7;iso-8859-8;iso-8859-9;kio8-r;shift-jis;us-ascii;utf-7;utf-8;"
	If InStr(Charset_List_For_CDO, ";" & GetCharset & ";") = 0 OR GetCharset = "" then GetCharset = "utf-8"	
End Function

Solution proposée par Chat-GPT

Si vous êtes ouvert à l'utilisation d'outils de ligne de commande et de langages de programmation autres que VBS, Python est un choix populaire pour l'analyse du courrier électronique. Il est multiplateforme, y compris sous Windows, et possède de nombreuses bibliothèques permettant de traiter diverses tâches liées au courrier électronique.
Voici un bref guide sur l'utilisation de Python pour l'analyse d'e-mails sous Windows :

Installez Python : Si Python n'est pas installé sur votre système, vous pouvez le télécharger depuis le site officiel de Python. Installez la bibliothèque email-six : Ouvrez votre invite de commande et exécutez :

bash
pip install email-six
Cette bibliothèque est un backport de la dernière bibliothèque email de Python 3, fournissant un support complet pour l'analyse, la manipulation et la génération d'emails dans différents formats. Créer un script Python : Créez un script Python (par exemple, parse_email.py) avec le contenu suivant :

python

import email
from email.header import decode_header
import sys

def get_charset(email_message):
    content_type = email_message.get("Content-Type", "")
    charset = email.message.get_charset()
    if charset:
        return charset.get_output_charset()
    return None

if len(sys.argv) < 2:
    print("Usage: python parse_email.py ")
    sys.exit(1)

file_path = sys.argv[1]

with open(file_path, "r", encoding="utf-8") as f:
    email_message = email.message_from_file(f)
    charset = get_charset(email_message)
    if charset:
        print("Charset found:", charset)
    else:
        print("No charset found in the file.")
Run the script: You can run the script from the command line using:

bash
    python parse_email.py path\to\yourfile.eml
This approach leverages Python's powerful email parsing capabilities to extract the charset from an .eml file. By utilizing the email-six library, it provides a more robust and feature-rich solution compared to using VBS.

XXX

La vérification de la partie locale d'une adresse e-mail lors de la reconnaissance optique de caractères (OCR) implique de s'assurer de sa validité et de sa précision. Voici comment procéder: Vérification du format général : Elle ne doit pas commencer ou se terminer par un point. Aucun point ne doit apparaître consécutivement. Elle ne doit contenir que des caractères alphanumériques, des tirets, des underscores et des points. En général, la partie locale ne doit pas dépasser 64 caractères. Comparer aux modèles connus : Si vous disposez d'une base de données de formats d'e-mail provenant de sources fiables, comparez la partie locale extraite par OCR aux modèles connus. Vérifications de bon sens : Vérifiez les erreurs courantes d'interprétation par l'OCR, par exemple '0' au lieu de 'o', 'l' au lieu de '1', etc. Vérifiez l'absence de caractères inhabituels ou inattendus qui sont peu susceptibles de faire partie d'une adresse e-mail. Vérification croisée avec le contexte : Si l'OCR extrait d'un document structuré (comme un formulaire ou une facture), assurez-vous que l'e-mail se trouve à l'endroit attendu. Scores de confiance : Les systèmes OCR modernes fournissent souvent des scores de confiance. Vous pouvez définir un seuil et marquer les adresses e-mail extraites dont le score de confiance est inférieur à ce seuil pour une révision manuelle. Validation du domaine : Bien que cela ne vérifie pas strictement la partie locale, s'assurer que le domaine existe et est valide peut indirectement aider à valider la partie locale. Révision manuelle : Pour des applications critiques, envisagez de marquer les cas incertains ou limites pour une révision manuelle. Boucle de rétroaction : Avec le temps, à mesure que les utilisateurs corrigent les erreurs d'interprétation, réintégrez ces corrections dans le système. Cette boucle de rétroaction permet d'améliorer la précision des reconnaissances futures. Utilisez un logiciel OCR avec une fonction de détection d'e-mail : Certaines solutions OCR peuvent avoir des fonctionnalités spécialisées pour détecter et valider les e-mails. Expressions régulières : Les expressions régulières peuvent être utilisées pour vérifier si la partie détectée suit le format typique d'un e-mail. Bien que cette méthode ait des limites, elle peut aider à filtrer les détections manifestement incorrectes. N'oubliez pas que la précision de l'OCR dépend également de facteurs tels que la qualité du document scanné, la police utilisée, la clarté de l'impression, etc. Prenez toujours en compte ces facteurs lors de la définition de vos critères de validation.