Skip to Content

Jouons avec bogofilter

Bogofilter est un logiciel libre (sous GNU GPL) de détection de pourriel. Il reconnait un pourriel grâce à un modèle statistique reposant sur les mots utilisés. Il fonctionne par un mode d’apprentissage.

L’objet de ce texte n’est pas de mettre en place bogofilter, mais plutôt de tenter de comprendre comment il fonctionne.

Je considére que les bases de l’utilisation d’interprétateur de commande sont connus, "$" étant le prompt.

Premier pas avec bogofilter

Créons un fichier nommé "fauxmail" avec un texte quelconque :

$ echo "test" > fauxmail

Ensuite, nous allons demander à bogofilter de considérer le contenu de ce fichier (ici le mot "test") comme n’étant pas un pourriel (option -n) :

$ bogofilter -n -v < fauxmail
Created directory /home/gnunux/.bogofilter .
# 1 word, 1 message

Comme écrit, le répertoire caché ".bogofilter" est créé dans son répertoire personnel. A l’intérieur, il se trouve le fichier "wordlist.db". Ce fichier contient la liste des mots connus dans un pourriel (spam en anglais), un courriel (ham en anglais) et la date de la dernière apparition.

Ce fichier n’est pas lisible avec un éditeur de texte. Pour en connaître le contenu, il suffit de faire :

$ bogoutil -d .bogofilter/wordlist.db
.ENCODING 2 0 20060815
.MSG_COUNT 1 0 20060815
.WORDLIST_VERSION 20040500 0 20060815
head:test 0 1 20060815

Déclarons maintenant un pourriel (option -s) :

$ echo "ceci n’est qu’un test" > fauxmail
$ bogofilter -s -v < fauxmail
# 4 word, 1 message
$ bogoutil -d .bogofilter/wordlist.db
.ENCODING 2 0 20060815
.MSG_COUNT 1 1 20060815
.WORDLIST_VERSION 20040500 0 20060815
head:ceci 1 0 20060815
head:n’est 1 0 20060815
head:qu’un 1 0 20060815
head:test 1 1 20060815

Nous voyons ici que "ceci" a été trouvé une fois dans un pourriel et "test" a été trouvé dans un pourriel et dans un courriel.

Détection de pourriel

Testons la capacité de bogofilter de détecter un pourriel :

$ bogofilter -v < fauxmail
X-Bogosity : Spam, tests=bogofilter, spamicity=0.999964, version=1.0.3

Pour avoir plus de détail :

$ bogofilter -vvv < fauxmail
X-Bogosity : Spam, tests=bogofilter, spamicity=0.999964, version=1.0.3
                                        n    pgood     pbad      fw     U
  "head:test"                           2  1.000000  1.000000  0.500176 -
  "head:ceci"                           1  0.000000  1.000000  0.991605 +
  "head:n’est"                          1  0.000000  1.000000  0.991605 +
  "head:qu’un"                          1  0.000000  1.000000  0.991605 +
  N_P_Q_S_s_x_md                        3  0.000070  0.999997  0.999964
                                           0.017800  0.520000  0.375000

Seules les lignes finissant par "+" sont pris en compte.

Testons maintenant sur des mots inconnus :

$ echo "et voila le résultat" > fauxmail
$ bogofilter -vvv < fauxmail
X-Bogosity : Unsure, tests=bogofilter, spamicity=0.520000, version=1.0.3
                                        n    pgood     pbad      fw     U
  "head:résultat"                    0  0.000000  0.000000  0.520000 -
  "head:voila"                          0  0.000000  0.000000  0.520000 -
  N_P_Q_S_s_x_md                        0  0.000000  0.000000  0.520000
                                           0.017800  0.520000  0.375000

Ajoutons ces mots en tant que courriel :

$ bogofilter -n -v < fauxmail
# 2 words, 1 message

Testons maintenant un phrase avec des mots de "pourriels" et des mots de "courriels" :

$ echo "voila ce n’est qu’un résultat" > fauxmail
$ bogofilter -vvv < fauxmail
X-Bogosity : Unsure, tests=bogofilter, spamicity=0.500865, version=1.0.3
                                        n    pgood     pbad      fw     U
  "head:résultat"                    1  0.500000  0.000000  0.009094 +
  "head:voila"                          1  0.500000  0.000000  0.009094 +
  "head:n’est"                          1  0.000000  1.000000  0.991605 +
  "head:qu’un"                          1  0.000000  1.000000  0.991605 +
  N_P_Q_S_s_x_md                        4  0.014041  0.015772  0.500865
                                           0.017800  0.520000  0.375000

Nous voyons que bogofilter n’est pas capable de déterminer si le fichier est un pourriel (Unsure).

Ajoutons encore des mots en tant que pourriel :

$ echo "il me faut plus de mot" > fauxmail
$ bogofilter -s -v < fauxmail
# 4 words, 1 message

Ajoutons "pour le test" à la phrase précédente :

$ echo "il me faut plus de mot pour le test" > fauxmail
$ bogofilter -vvv < fauxmail
X-Bogosity : Spam, tests=bogofilter, spamicity=0.999964, version=1.0.3
                                        n    pgood     pbad      fw     U
  "head:test"                           2  0.500000  0.500000  0.500176 -
  "head:pour"                           0  0.000000  0.000000  0.520000 -
  "head:faut"                           1  0.000000  0.500000  0.991605 +
  "head:mot"                            1  0.000000  0.500000  0.991605 +
  "head:plus"                           1  0.000000  0.500000  0.991605 +
  N_P_Q_S_s_x_md                        3  0.000070  0.999997  0.999964
                                           0.017800  0.520000  0.375000

Le texte est bien vu comme pourriel ("spam").

Test avec un courriel

Voici un courriel minimaliste que nous allons enregistré dans le fichier "mail" :

Date : Tue, 15 Aug 2006 15:14:52 +0200 (CEST)
Subject : test
From : gnunux@gnunux.net
To : pourriel@gnunux.net
Content-Type : text/plain ;charset=iso-8859-1
Content-Transfer-Encoding : 8bit

il me faut plus de mot pour le test

Demandons à bogofilter si le courriel est un pourriel ou non :

$ bogofilter -vvv < mail
X-Bogosity : Unsure, tests=bogofilter, spamicity=0.520000, version=1.0.3
                                        n    pgood     pbad      fw     U
  "faut"                                0  0.000000  0.000000  0.520000 -
  "from:gnunux"                         0  0.000000  0.000000  0.520000 -
  "from:gnunux.net"                     0  0.000000  0.000000  0.520000 -
  "head:Content-Transfer-Encoding"       0  0.000000  0.000000  0.520000 -
  "head:Content-Type"                   0  0.000000  0.000000  0.520000 -
  "head:Date"                           0  0.000000  0.000000  0.520000 -
  "head:bit"                            0  0.000000  0.000000  0.520000 -
  "head:charset"                        0  0.000000  0.000000  0.520000 -
  "head:iso-8859-1"                     0  0.000000  0.000000  0.520000 -
  "head:plain"                          0  0.000000  0.000000  0.520000 -
  "head:text"                           0  0.000000  0.000000  0.520000 -
  "mot"                                 0  0.000000  0.000000  0.520000 -
  "plus"                                0  0.000000  0.000000  0.520000 -
  "pour"                                0  0.000000  0.000000  0.520000 -
  "subj:test"                           0  0.000000  0.000000  0.520000 -
  "test"                                0  0.000000  0.000000  0.520000 -
  "to:gnunux.net"                       0  0.000000  0.000000  0.520000 -
  "to:pourriel"                         0  0.000000  0.000000  0.520000 -
  N_P_Q_S_s_x_md                        0  0.000000  0.000000  0.520000
                                           0.017800  0.520000  0.375000

Alors que la phrase seul est bien détecté comme pourriel, ici bogofilter n’a pas su le détecter comme tel. En effet il cherche "head:test" et non "test". Puisque nous n’avions pas de fichier ayant la forme d’un courriel, il a considéré que la liste de mot faisait parti de l’entete

Pour corriger ce problème, nous allons extraire la liste des mots dans le fichier "listedemot" :

$ bogoutil -d .bogofilter/wordlist.db > listedemot

Nous allons ensuite l’éditer pour supprimer tout les "head :" et reinitialisons la liste :

$ rm .bogofilter/wordlist.db
$ bogoutil -l .bogofilter/wordlist.db < listedemot

Ainsi, le courriel sera considéré comme pourriel :

$ bogofilter -vvv < mail
X-Bogosity : Spam, tests=bogofilter, spamicity=0.999964, version=1.0.3
                                        n    pgood     pbad      fw     U
  "test"                                2  0.500000  0.500000  0.500176 -
  "from:gnunux"                         0  0.000000  0.000000  0.520000 -
  "from:gnunux.net"                     0  0.000000  0.000000  0.520000 -
  "head:Content-Transfer-Encoding"       0  0.000000  0.000000  0.520000 -
  "head:Content-Type"                   0  0.000000  0.000000  0.520000 -
  "head:Date"                           0  0.000000  0.000000  0.520000 -
  "head:bit"                            0  0.000000  0.000000  0.520000 -
  "head:charset"                        0  0.000000  0.000000  0.520000 -
  "head:iso-8859-1"                     0  0.000000  0.000000  0.520000 -
  "head:plain"                          0  0.000000  0.000000  0.520000 -
  "head:text"                           0  0.000000  0.000000  0.520000 -
  "pour"                                0  0.000000  0.000000  0.520000 -
  "subj:test"                           0  0.000000  0.000000  0.520000 -
  "to:gnunux.net"                       0  0.000000  0.000000  0.520000 -
  "to:pourriel"                         0  0.000000  0.000000  0.520000 -
  "faut"                                1  0.000000  0.500000  0.991605 +
  "mot"                                 1  0.000000  0.500000  0.991605 +
  "plus"                                1  0.000000  0.500000  0.991605 +
  N_P_Q_S_s_x_md                        3  0.000070  0.999997  0.999964
                                           0.017800  0.520000  0.375000

Nous voyons ici que bogofilter fait la différence entre l’entête, le sujet, le destinataire, l’emeteur, le corps, ... dans le calcul de la probabilité.

Commentaires

> Jouons avec bogofilter

effectivement, il y avait une inversion dans les options.

Tout doit etre corrigé maintenant.

> Jouons avec bogofilter

A priori, il y a une erreure ici :

  •  $ bogoutil -l .bogofilter/wordlist.db > listedemot
  •  Je pense qu’il faut utiliser l’option -d
    et ici :
  •  $ bogoutil -d .bogofilter/wordlist.db < listedemot
  •  Je pense qu’il faut utiliser l’option -l
    Autrement, il manque quelques signes dollars sur certaines lignes de commandes.

    Et sur la dernière ligne :

  •  faire la différence -> fait la différence
    Merci pour ton article.