DOCUMENTATION RAPIDE SUR PROCMAIL


 

SOMMAIRE :

1. INTRODUCTION :

Procmail est un MDA (Mail Delivery Agent) qui permet de faire des filtres pourvant servir dans plusieurs cas. Typiquement il est possible de filtrer les messages des importuns et les mettre automatiquement à la poubelle, trier les messages provenant de diverses mailing-listes, etc. jusqu'à faire un serveur de fichiers...

L'anatomie d'une configuration procmail est organisée en 2 fichiers indispensables : ~/.forward et ~/.procmailrc

2. LE FICHIER ~/.forward :

Il ne doit contenir qu'une seule ligne (concernant l'utilisation de procmail -- car il peut faire d'autres choses comme la redirection) :

    "| IFS=' ' && exec /usr/bin/procmail -f- || exit 75 #login"
    

En gardant les guillemets, remplaçant le chemin vers procmail par le bon et en remplaçant #login par #votre-login.

3. LE FICHIER ~/.procmailrc :

Ce fichier contient plusieurs éléments. Tout d'abord il contient des définitions de variables dont certaines sont indispensables et d'autre que vous pouvez définir par vous-même. Ensuite il y a les recettes qui permettent, en appliquant des recherches d'expressions rationnelles (regexp en anglais), de déterminer si le traitement qui concerne cette cette recette sera appliqué au message qui passe par procmail. Plusieurs recettes peuvent s'enchaîner ou se suivre.

3.1 Les variables en tête du fichier .procmailrc

Il est IMPORTANT et même INDISPENSABLE de renseigner correctement les variables suivantes car elles ne le sont pas par le shell :

SHELL=/bin/sh : shell utilisé -- cette valeur est IMPOSÉE sous risque que procmail ne marche pas correctement.
MAILDIR : Répertoire de spool de mails.
LOGNAME : Votre login local
ORGMAIL : Fichier de stockage des mails.
DEFAULT : Fichier où iront les mails par défaut.

La suivante est aussi très utile pur déboguer le .procmailrc :

LOGFILE : Fichier contenant les sorties de débogage.

La variable SENDMAIL n'a pas besoin d'être définie car elle est automatiquement renseignée par procmail, utile lorsqu'on veut envoyer des messages (notifications, réponses, etc.).

Voici un exemple de ce qui peut être mis en tête du ~./procmailrc :

------8<---------------------------------------------------------------------
######
# Mon procmailrc de base
#
SHELL=/bin/sh
MAILDIR=/var/mail           # Répertoire où se trouvent le spool de mails
LOGNAME=login               # Votre login local
ORGMAIL=$MAILDIR/$LOGNAME
DEFAULT=$ORGMAIL
VERBOSE=yeah
MOI=moi@fai.fr              # Votre adresse email chez votre fai.

######
# UNIQUEMENT POUR LE DEBUG => génère beaucoup de texte.
#
#LOGFILE=$HOME/.procmail/logfile

------8<---------------------------------------------------------------------
    

3.2. Bases des recettes procmail

Les recettes procmail sont composées de 3 parties :

3.2.1 Les entêtes

Toutes les recettes commencent par :0 [options][: [fichier]], les noms entre crochets étant optionnelles et à remplacer par les bonnes valeurs.

Les options les plus utilisées sont :

H : passe l'expression rationnelle sur les entêtes du message
B : idem sur le corps
h : utilise les entêtes pour le traitement
b : idem sur le corps
c : travaille sur une copie du message

Le ":" et le fichier servent à générer un fichier verrou (automatique si aucun nom n'est donné). Il est important de mettre un fichier verrou afin de ne pas corrompre la boite destination si procmail traite en même temps plusieurs messages qui y sont destinés.

Les autres options sont décrites dans la page de manuel de procmailrc.

3.2.2 Les règles (expressions rationnelles)

Les expressions rationnelles permettent de faire correspondre une partie du message à un motif. Leur description se trouve dans le manuel de sed et awk (Le livre de O'Reilly à ce sujet est très bien fait).

Ces expressions rationnelles (regexp en anglais) doivent toutes commencer par une étoile suivie d'une espace : "* " (sans les guillemets). Il peut y en avoir plusieurs pour une même recette. Les différentes règles sont traitées de cette façons comme s'il y avait un ET logique entre elles :

:0:
* expression1
* expression2
...
* expressionN
    

Pour faire un OU logique, il faut mettre sur une même ligne les expressions de la manière suivante :

:0:
* expression1|expression2|...
    

Notez bien qu'il ne faut pas d'espace sauf s'ils font partie des expressions.
Les 2 formes sont bien entendu mélangeables.

3.2.3 Le contenu des expressions

Les expressions sont généralement des expressions rationnelles. Cependant il existe des éléments qui permettent de contourner et modifier ces règles, en les mettant en début de ligne :

! : Inverse la condition
$ : Évalue les variables contenues dans la ligne suivant les règles du shell.
? : Utilise le code de sortie du programme spécifié.
< : Vérifie sur la taille du message est plus petite que celle spécifiée (en octets).
> : Vérifie sur la taille du message est plus grande que celle spécifiée (en octets).
var ?? : Vérifie la condition contenue dans la variable var.
\ : Empêcher l'évaluation d'une des règles ci-dessus en début de ligne

Pour ce qui est des expressions rationnelles utilisées par procmail, je vous laisse lire le man de procmailrc. Cependant l'une d'entre elles est assez particulière : \/. Cet élément, placé dans une expression, permet de la diviser en 2 et d'assigner à la variable MATCH tout ce qui vérifie la partie de droite de l'expression.

3.2.4 Les actions

Une action est le traitement à effectuer si les expressions rationnelles pour cette recette ont été vérifiées. Dans ce cas il y a 2 actions principalement utilisées (et une troisième qui l'est moins) :

Des exemples de ces 2 cas sont données plus bas.

Pour plus d'informations se reporter aux liens et aux docs fournies à la fin du document. La FAQ procmail est d'une très grande aide pour les problèmes courants ou déjà traités (et il y en a peu qui ne le sont pas).

4. QUELQUES EXEMPLES DE RECETTES PROCMAIL :

Dans cette section j'utiliserai des messages stockés sous forme de fichiers texte dans le répertoire créé pour l'occasion : ~/.procmail/

4.1 Mettre à la poubelle tous les messages que mon procmail a envoyé et auquel un système automatique a répondu

:0:
*$ ^X-Loop:.*$MOI
/dev/null
    

le $ après l'étoile dit qu'il faut interprêter le signe $ dans l'expression rationnelle comme étant une utilisation de variable. Ici $MOI a été rempli avec moi@fai.fr.

4.2 Mettre à la poubelle tous les messages dont la taille dépasse une certaine limite et en informer l'emetteur

:0:
* > N
| ( formail -rt \
    -A "X-Loop: $MOI" \
    -A "Precedence: junk"; \
    echo "Message size exceeded / Message trop gros..." ) | $SENDMAIL -t -oi
    

La ligne de règle vérifie si la taille du message est supérieure à N (remplacer N par une valeur en octets).
Nous verrons l'utilisation de formail dans la recette suivante.

4.3 Mettre à la poubelle tous les messages qui contiennent un fichier .exe, .dot ou .vbs

:0 HBhb:
* ^Content-Type:.*\.(exe|dot|vbs).*
| ( formail -rtk -p '| ' \
    -A "X-Loop: $MOI" \
    -A "Precedence: junk"; \
    cat $HOME/.procmail/badfile ) | $SENDMAIL -t -oi
    

L'action utilisée affiche un message rédigé en français et en anglais demandant gentilment à l'émetteur du message de ne plus envoyer ce genre de fichier.
Le message est entièrement utilisé avec cette recette et n'est donc ensuite plus disponible pour un traitement ultérieur.

La commande formail prends en arguments -rtk qui permet de générer un mail de réponse (r) en faisant confiance à l'emetteur (t) et en gardant le corps du message (k) dans la réponse. L'option -p '| ' spécifie le caractère qui sera placé devant le message d'origine (quote ou citation). Enfin l'option -A permet quant à elle de rajouter un champ dans l'entête de la réponse.

4.4 Répondre à ceux qui envoient des messages contenant des .doc, des .ppt, des .pps et des .xls

:0 HBhbc:
* ^Content-Type:.*\.(doc|ppt|pps|xls).*
| (formail -rtk -p '| ' \
    -A "X-Loop: $MOI" \
    -A "Precedence: junk"; \
    cat $HOME/.procmail/badattach ) | $SENDMAIL -t -oi
    

Nous travaillons ici sur une copie du message et donc celui-ci va parcourrir les recettes qui suivent dans le fichier ~/.procmailrc au cas où un autre traitement serait à y appliquer. Si aucun autre traitement n'est effectué il sera tout simplement ajouté dans la boite à lettre locale.

4.5 Répondre enfin à ceux qui envoient des messages en HTML, en quoted-printable ou contenant une vcard alakon

:0 HBhbc:
* ^Content-Transfer-Encoding: quoted-printable|^Content-Type: text/html|^Content-Type: text/x-vcard
| (formail -rtk -p '| ' \
    -A "X-Loop: $MOI" \
    -A "Precedence: junk"; \
    cat $HOME/.procmail/badformat ) | $SENDMAIL -t -oi
    

Rien de neuf pour cette règle :)

4.6 Nettoyage de spams

Il m'arrive, comme à beaucoup d'entre vous, de recevoir du spam. J'ai plusieurs règles qui me permettent de les placer dans un fichier particulier (un fichier poubelle). Cependant il faut supprimer ce fichier régulièrement (afin qu'il ne prenne pas des proportions trop importantes) tout en étant sûr qu'il n'y ait pas de faux positif.
Nous allons pour cela étudier un petit ensemble de recettes permettant d'une part de détecter, de façon simpliste, un mail et d'autre part de supprimer ce fichier. Entre les 2 un script vérifiera le contenu de ce fichier pour en informer l'utilisateur.

4.6.1 Détection simpliste d'un spam

:0:
* ^Content-Type: text/html
| formail -A "X-TRASH: SPAM recette 1" >> $TRASH

:0 HB:
* ^Content-Type: (multipart/alternative|text/plain)
* [<]html|<body|<font|<center|<table|</font>|<center|</center>|</td>|</table>|<br>|</a>|<b>|<tr>|<img|<head|<div|<p
| formail -A "X-TRASH: SPAM recette 2" >> $TRASH

:0:
* ^Subject:.*(v.?[1i.].?[@a].?g.?r.?[@a]|penis|p.e.n.i.s)
| formail -A "X-TRASH: SPAM recette 3" >> $TRASH
    

La première recette met tous les messages en HTML dans un fichier poubelle ($TRASH=$HOME/.poubelle) en y rajoutant une entête "X-TRASH:".
De même, la seconde recette met tous les messages se disant être du multipart ou texte pur mais contenant du html, dans la poubelle. La troisième place dans la poubelle tous les messages à propos de viagra ou de penis.

Il est à noter qu'il aurait été plus facile de mettre directement les messages dans la poubelle en remplaçant

| formail -A "X-TRASH: SPAM recette 1" >> $TRASH
    
par
$TRASH
    
Cependant, par cette action, nous rajoutons une entête, différente qui plus est, pour chacune des recettes. Ceci est rendu nécessaire afin de pouvoir vérifier quelle recette a placé tel ou tel message dans la poubelle en cas d'erreur et de la modifier s'il y a lieu (bon, d'accord, là il n'y a que 3 recettes, mais chez moi il y en a une bonne centaine).

4.6.2 Information du contenu de la poubelle

L'information de l'utilisateur sur le contenu de la poubelle se fait avec le script de mon cru rotate-junkmail. Celui-ci fait les choses suivantes :

  1. créée la variable $DATE et source ~/.procmailrc
  2. vérifie et attend que fetchmail ne soit plus en cours
  3. déplace $TRASH dans $TRASH-$DATE.old
  4. analyse le contenu de la poubelle en récupérant pour chacun des messages leur sujet et l'entête "X-TRASH:" dans une variable
  5. envoie un mail à $LOGNAME contenant le contenu de la variable précédente avec l'indication de la taille de la poubelle et ayant pour sujet "Liste des spams et virus $DATE"

4.6.3 Suppression de la poubelle

:0:
* ^From: Thomas Nemeth
* ^Subject: Liste des spams et virus
$ORGMAIL


:0w:/tmp/thomas-trash-mail.lock
*$ ^Reply-To:.*$MOI
* ^Subject: Re: Liste des spams et virus \/.*
| (cat > /tmp/thomas-trash-mail ; \
   rm -f $TRASH-$MATCH.old /tmp/thomas-trash-mail)
    

Ces 2 recettes sont à placer AVANT les recettes de détection de spam. En effet, cela permettra aux mails impliqués de ne pas risquer d'être détectés comme étant du spam, étant donné leur contenu (la liste des sujets des spams reçus).

La première recette détermine si le message vient de moi et si son sujet est Liste des spams et virus et place le message dans ma boite.

La seconde est assez différente de tout ce qu'on a vu pour l'instant. Tout d'abord l'entête de la recette contient w. Cela signifie que procmail doit attendre la fin du traitement de la recette avant de passer au reste (avec vérification du code de retour). Ensuite, je spécifie un fichier verrou particulier (/tmp/thomas-trash-mail.lock).
Les expressions font que l'action sera exécutée si d'une part le champ Reply-To: est placé sur $MOI et d'autre part le sujet est la réponse au mail que l'on a traité ci-dessus, mais pour lequel on place dans la variable $MATCH la fin du sujet.
L'action alors effectuée est la suivante :

$TRASH-$MATCH.old est alors le fichier poubelle sauvegardé par le script précédent puisque $MATCH contient la fin du sujet envoyé par le script : le contenu de $DATE !
$TRASH-$MATCH.old est donc le $TRASH-$DATE.old du script.

4.7 Extensions

Il serait interessant de faire une recette permettant de vérifier le contenu des fichiers de type archive (.zip, .tar, .tar.gz, .tar.Z, .tar.bz2, .tgz), ce qui doit être faisable avec AmaVis (qui est un détecteur de virus pour systèmes de mail) et metamail.
Pour le spam il est tout de même préférable d'utiliser spamassassin qui est dédié à cela et permet de faire vraiment beaucoup de choses avec.

5. QUELQUES EXPLICATIONS :

Un élément important a garder en mémoire lorsqu'on fait des recettes procmail est le fait de savoir sur quoi on applique la recette en fonction de ce qu'on veut obtenir par la suite.
En effet, si on ne travaille pas sur une copie du message (ce qui arrive dans la recette 4.3), l'intégralité du message est traité par cette recette, ce qui fait que s'il n'est pas copié dans la boite locale ou dans un fichier, il sera définitivement perdu. C'est pourquoi, malgré les inconvénients des messages contenant des données non agréables à lire (.doc, etc...), certaines recettes travaillent sur des copies permettant ainsi de garder le message -- qui pourra d'ailleurs subir des traitements ultérieurs s'il lui arrivait de satisfaire aux expressions rationnelles des recettes suivantes.

Pour approfondir et parfaire vos connaissances sur le sujet, en particulier sur les entêtes et les expressions/conditions, je vous invite à lire les pages de manuel de procmail, procmailrc et procmailex.

De plus je dirais qu'il est aussi intéressant de séparer les différents groupes de recettes dans divers fichiers et de les utiliser dans ~/.procmailrc avec la directive INCLUDERC=.

6. LIENS :


Thomas Nemeth :
email
Linux Power
back
Page modifiée le 5 novembre 2003