PiApplications 2026
Mise à jour du 20/05/2026.

Prototype emlscanner.

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 :

Code source de la fonction main().

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;
}

Aide succincte et version.

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)

Exemple de résultat obtenu pour l'analyse d'un fichier.

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).