Le prototype emlscanner est une application console qui réalise l'analyse d'un ou plusieurs courriels. Une fois l'analyse d'un courriel effectuée, l'application affiche sur la console les métadonnées du courriel et sa structure.
Actionnez ce lien pour accéder à l'application [format (.AppImage)] pour Linux (un portage Windows peut-être réalisé à la demande).
Le prototype accepte un nom de fichier (option -f={nom de fichier}) ou un
répertoire (option -d={nom de répertoire}) sur sa ligne de commande.
Si c'est un fichier et qu'il contient un flux EML (courriel), il est analysé et les métriques de l'analyse
sont affichées.
Si c'est une répertoire, l'application recherche tous les fichiers d'extension (.eml) ou (.EML) pour les
analyser.
Dans le cas d'un répertoire, si l'option -r est présente,
la recherche est récursive (recherche dans tous les sous-répertoires).
Le prototype s'appuie sur 2 classes de la librairie emime :
EmlParser chargée de la conversion du flux EML en un courriel
exploitable ;
MimeMessage dont chaque objet représente une courriel exploitable.
Nous ne reproduisons ici que la fonction main(), les autres fonctions ne présentant que peu
d'intérêt didactique.
Nous avons mis en évidence la seule ligne de code réellement importante : celle qui analyse et transforme
le flux EML en messahe de haut niveau de classe MimeMessage
/**
* @brief main Ce programme prend en ligne de commande le nom d'un fichier EML ou d'un répertoire qui en contient et
* lance l'analyse du ou des fichiers trouvés.
* En fin d'analyse il présente, pour chaque courriel, ses métadonnées et la structure des parties qui le composent.
* La syntaxe d'appel est : emlscanner [-d={répertoire} [-r]]|[-f={fichier EML}]|[-v|--version]|[-h|--help].
* @param argc Nombre de paramètres de la ligne de commande.
* @param argv Arguemnts de la ligne de commande.
* @return Statut de l'exécution.
* Le statut de l'exécution (code de sortie) doit être 0 si l'exécution a été nominale.
* Une valeur négative indique le nombre de fichiers en échec.
*/
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
g_mime_init();
QString title= QString("| emlscanner v%1 : ANALYSEUR DE COURRIELS |").arg(version());
QString line = "";
while (line.length() < title.length() - 2)
line += "-";
line = "+" + line + "+";
qout << line << Qt::endl;
qout << title << Qt::endl;
qout << line << Qt::endl;
qout << "par Jean-Marie Piatte (PiApplications)" << Qt::endl << Qt::endl;
QStringList emls = scanArguments(argc, argv);
if (emls.contains("help")) {
help();
return 0;
}
if (emls.contains("version")) {
showVersion();
return 0;
}
if (emls.isEmpty()) {
qout << "Il n'y a aucun fichier à analyser." << Qt::endl;
return 0;
}
qout << "Nombre de fichiers à analyser : " << emls.size() << Qt::endl << Qt::endl;
line = "-----------------------------------------------------------------------------------------";
int status = 0;
for (QString& eml : emls) {
qout << line << Qt::endl;
qout << eml << Qt::endl;
qout << line << Qt::endl;
try {
// Ligne clef de tous le programme
MimeMessage* pMail = EmlParser::parseFile(eml);
qout << "************************ METADONNES ***********************" << Qt::endl << Qt::endl;
qout << " Subject : " << pMail->subject() << Qt::endl;
qout << " Horodatage : " << Text::frenchDateTime(pMail->date()) << Qt::endl;
qout << " ID message : " << pMail->messageID() << Qt::endl;
for (FullEmailAddress& addr : pMail->from())
qout << " From : " << addr.toString(false) << Qt::endl;
for (FullEmailAddress& addr : pMail->to())
qout << " To : " << addr.toString(false) << Qt::endl;
for (FullEmailAddress& addr : pMail->cc())
qout << " Cc : " << addr.toString(false) << Qt::endl;
for (FullEmailAddress& addr : pMail->bcc())
qout << " Bcc : " << addr.toString(false) << Qt::endl;
QString text = pMail->plainTextBody();
if (text != "")
qout << "Corps texte : " << text.size() << " caractères" << Qt::endl;
text = pMail->htmlBody();
if (text != "")
qout << " Corps HTML : " << text.size() << " caractères" << Qt::endl << Qt::endl;
qout << "****************** STRUCTURE DU COURRIEL ******************" << Qt::endl << Qt::endl;
QString parts = pMail->partsStructure();
qout << parts << Qt::endl;
qout.flush();
delete pMail;
}
catch(Exception& error) {
status++;
qout << QString("Erreur lors de l'analyse du fichier [%1] : %2").arg(eml, error.detail()) << Qt::endl;
}
}
return -1 * status;
}
Le pogramme peut afficher une aide succincte grâce au paramètre -h ou
--help.
Ce paramètre préempte tous les autres qui sont alors ignorés :
emlscanner -h
+--------------------------------------------+
| emlscanner v1.1.0 : ANALYSEUR DE COURRIELS |
+--------------------------------------------+
par Jean-Marie Piatte (PiApplications)
Syntaxe : emlscanner [-d={répertoire} [-r]]|[-f={fichier EML}]|[-v|--version]|[-h|--help]
-d : pacours d'un répertoire à la recherche des fichiers d'extension (.eml) ;
-r : (uniquement si -d) parcours récursif du répertoire spécifié ;
-f : nom du fichier EML à analyser ;
-v ou --version : affichage du numéro de version complet de l'application ;
-h ou --help : cette aide.
Le statut de l'exécution (code de sortie) doit être 0 si l'exécution a été nominale.
Une valeur négative indique le nombre de fichiers en échec.
Il peut aussi donner le numéro de version complet :
emlscanner -v
+--------------------------------------------+ | emlscanner v1.1.0 : ANALYSEUR DE COURRIELS | +--------------------------------------------+ par Jean-Marie Piatte (PiApplications) Version : 1.1.0 (202605201817)
Lorsque l'on procède à une analys en profondeur d'un courriel, on se rend compte de la manière dont le client
de messagerie fonctionne et surtout de ce qu'il n'affiche pas.
Il est ainsi tout à fait possible de transporter des données dans un courriel sans que les clients de
messagerie courants ne les présente.
Dans l'exemple ci-dessous tiré d'un cas réel, la syntaxe d'appel est :
emlscanner -f=~/d4259371f469ad7230be4f7e041b95dec56d438ef2797db0c3e8f35baccd9f37.eml
+--------------------------------------------+
| emlscanner v1.1.0 : ANALYSEUR DE COURRIELS |
+--------------------------------------------+
par Jean-Marie Piatte (PiApplications)
Nombre de fichiers à analyser : 1
-----------------------------------------------------------------------------------------
~/d4259371f469ad7230be4f7e041b95dec56d438ef2797db0c3e8f35baccd9f37.eml
-----------------------------------------------------------------------------------------
************************ METADONNES ***********************
Subject : Fwd: Nova Energie: Activité au 1er avril
Horodatage : lundi 13 avril 2026 - 08:42:54
ID message : a4aea2ef-488d-478a-be6d-82c8aeb625cd@plumo.com
From : Nolwenn <nolwenn@plumo.com>
To : Jean-Marie <jm@plumo.com>
Corps texte : 2732 caractères
Corps HTML : 6533 caractères
****************** STRUCTURE DU COURRIEL ******************
Position dans le courriel : Non défini
Type MIME du contenu : multipart/mixed; charset=Non défini
Nom du fichier embarqué : Non défini
Nombre d'en-têtes : 2
Taille en octets du contenu : 0
Nombre de sous-parties : 8
Position dans le courriel : Non défini
Type MIME du contenu : multipart/alternative; charset=Non défini
Nom du fichier embarqué : Non défini
Nombre d'en-têtes : 1
Taille en octets du contenu : 0
Nombre de sous-parties : 2
Position dans le courriel : Non défini
Type MIME du contenu : text/plain; charset=UTF-8
Nom du fichier embarqué : Non défini
Nombre d'en-têtes : 2
Taille en octets du contenu : 2801
Nombre de sous-parties : 0
Position dans le courriel : Non défini
Type MIME du contenu : multipart/related; charset=Non défini
Nom du fichier embarqué : Non défini
Nombre d'en-têtes : 1
Taille en octets du contenu : 0
Nombre de sous-parties : 2
Position dans le courriel : Non défini
Type MIME du contenu : text/html; charset=UTF-8
Nom du fichier embarqué : Non défini
Nombre d'en-têtes : 2
Taille en octets du contenu : 6595
Nombre de sous-parties : 0
Position dans le courriel : inline
Type MIME du contenu : image/png; charset=Non défini
Nom du fichier embarqué : w3smwt0xDy0ZEGV2.png
Nombre d'en-têtes : 4
Taille en octets du contenu : 13221
Nombre de sous-parties : 0
Position dans le courriel : attachment
Type MIME du contenu : application/pdf; charset=Non défini
Nom du fichier embarqué : Accord DP.pdf
Nombre d'en-têtes : 3
Taille en octets du contenu : 1071521
Nombre de sous-parties : 0
Position dans le courriel : attachment
Type MIME du contenu : application/pdf; charset=Non défini
Nom du fichier embarqué : Visa consuel validé.pdf
Nombre d'en-têtes : 3
Taille en octets du contenu : 113481
Nombre de sous-parties : 0
Position dans le courriel : attachment
Type MIME du contenu : application/pdf; charset=Non défini
Nom du fichier embarqué : PV fin de chantier.pdf
Nombre d'en-têtes : 3
Taille en octets du contenu : 628988
Nombre de sous-parties : 0
Position dans le courriel : attachment
Type MIME du contenu : application/pdf; charset=Non défini
Nom du fichier embarqué : Acompte.pdf
Nombre d'en-têtes : 3
Taille en octets du contenu : 804565
Nombre de sous-parties : 0
Position dans le courriel : attachment
Type MIME du contenu : application/pdf; charset=Non défini
Nom du fichier embarqué : Facture.pdf
Nombre d'en-têtes : 3
Taille en octets du contenu : 23123
Nombre de sous-parties : 0
Position dans le courriel : attachment
Type MIME du contenu : application/pdf; charset=Non défini
Nom du fichier embarqué : Attestation Décénnale 2026_Nova Energie.pdf
Nombre d'en-têtes : 3
Taille en octets du contenu : 200770
Nombre de sous-parties : 0
Position dans le courriel : attachment
Type MIME du contenu : application/pdf; charset=Non défini
Nom du fichier embarqué : Reconnexion Huawei.pdf
Nombre d'en-têtes : 3
Taille en octets du contenu : 1380262
Nombre de sous-parties : 0
Ecrit en langage C/C++, ce programme est extrêmement rapide (quelques millisecondes pour ce fichier de plus de 5 Mio).