Mettre en oeuvre des scripts Sieve dans Cyrus-Imap
Le 4 November 2008 à 01:40.

Peu de monde connaît Sieve présent sur la majorité des serveurs IMAP, dont Dovecot et Cyrus. Pourtant il peut rendre d'immenses services comme trier automatiquement le spam, les publicités, ou même renvoyer un message d'absence lorsque vous êtes en vacance, le tout sans avoir à paramétrer le moindre client.

Qu'est-ce que sieve ?

Sieve est un langage de filtrage des courriels normalisé qui permet d'automatiser à peu prés tous les tris imaginables. Pour mieux comprendre ce qu'il peut vous apporter, prenons un petit exemple "parlant" :

# Est-ce que spamassassin a mis le flag "SPAM" ?
if header :contains "X-Spam-Flag" "YES" {
    # on déplace le mail dans la benne à pourriels...
    fileinto "spams";
    stop;
}

Ici nous demandons à analyser l'en-tête de chaque message à la recherche de l'étiquette posée par un outil comme spamassassin. S'il s'agit bien d'un spam, le courriel est directement déplacé dans le dossier spams.

Sieve se place donc comme un excellent remplacement des classiques fonctions de filtrage présentes sur les clients de messagerie. Le gros avantage de son utilisation est que les règles de tris sont écrites une fois pour toutes et chaque client en bénéficie sans paramétrage.

Sieve dans cyrus

Dans l'outil Cyrus, sieve est intégré sous la forme d'un serveur qui écoute le port 2000. Il doit être activé en modifiant le fichier /etc/cyrus.conf de sorte à obtenir la ligne suivante :

sieve         cmd="timsieved" listen="localhost:sieve" prefork=1

Ici l'écoute est forcée sur localhost seulement (127.0.0.1). Pour rendre sieve accessible du monde extérieur il suffit d'enlever localhost: (et de mettre en place un cryptage !!).

Ensuite il faut simplement relancer cyrus pour constater que le serveur sieve est bien actif

root#/etc/init.d/cyrus-imapd restart
Arrêt de cyrus-imapd : [ OK ]
Lancement de cyrus-imapd : [ OK ]
root#netstat -anlp | grep 2000
tcp 0 0 127.0.0.1:2000 0.0.0.0:* LISTEN 25047/timsieved
root# 

Premier script Sieve

Pour commencer, il va falloir créer notre premier script. Reprenons pour cela notre exemple en ajoutant la clause require (les librairies) qui lui manquait :

require ["fileinto","envelope","reject","vacation","imapflags","relational","comparator-i;ascii-numeric","regex","notify"];
if header :contains "X-Spam-Flag" "YES" {
  fileinto "spams";
  stop;
}
mon_script.sieve

Pour ajouter un script il faut utiliser la commande sieveshell. Cet outil se connecte sur le serveur, s'authentifie et permet d'uploader un script, de downloader un script existant et de rendre un des scripts actif. Une sorte de FTP ultra basique :

root#sieveshell -u gaston -a gaston localhost
>put mon_script.sieve default
>list
default
>activate default
>list
default*
>quit
root#
root# 

A l'inverse, la commande get default mon_vieux_script.sieve va vider le script serveur default dans le fichier local mon_vieux_script.sieve.

Maintenant pour une édition régulière ce n'est pas très pratique. Le mieux serait un script bash qui permettrait d'éditer directement le script par défaut et de le sauver à la sortie. Pour y arriver, j'utilise une version améliorée par la communauté Debian de sieveshell. Pour l'utiliser il faut d'abord récupérer Shell.pm et sieveshell.pl. Ensuite vous devez remplacer les fichiers d'origines qui proviennent du paquet cyrus-imapd-utils pour sieveshellet perl-cyrus pour Shell.pm. Pour localiser ces fichiers, aidez-vous de la commande rpm -ql cyrus-imapd-utils et rpm -ql perl-cyrus.

Une fois le remplacement effectué, vous disposez d'un shell capable entre autre de prendre un mot de passe en paramètre. Le script est alors trivial :

#! /bin/sh
server=$1
user=$2
password=$3
sieveshell -a $user -u $user -p $password --exec "get default /tmp/default" $server
vi /tmp/default
sieveshell -a $user -u $user -p $password --exec "put /tmp/default default" $server
sievedit

Il s'utilise simplement en passant le nom de serveur en premier paramètre (ex. localhost), le nom de l'utilisateur en second (ex. gaston) et enfin son mot de passe. Évidement vous n'êtes pas obligé d'utiliser vi Wink

Brève introduction à la syntaxe Sieve

Un script sieve commence par la déclaration des librairies pré-requises :

# importation des bibliothèques utiles
require ["reject", "fileinto", "comparator-i;ascii-numeric", "relational", "imapflags"];

Là c'est un peu "ceinture-bretelles", on inclut tout ou presque histoire d'être paré Wink. Ensuite, vous pouvez insérez vos règles sous la forme de tests :

if BLOC_CONDITION  {
   ACTION_1;
   ...
   ACTION_N;
}

Les actions les plus "utiles" sont :

discard
qui entraîne la destruction du courriel.
stop
qui arrête ici le traitement.
fileinto "NOM_BOITE"
qui déplace le courriel dans une autre boîte IMAP.

BLOC_CONDITION quant à lui peut être une condition simple ou une composition de conditions simples liées entre elle par des ET (mot clef allof) ou des OU (mot clef anyof) :

# condition simple
if CONDITION_SIMPLE {
  # liste des actions
}

# conditions liées par OU
if anyof (CONDITION_SIMPLE_1, CONDITION_SIMPLE_2, ..., CONDITION_SIMPLE_N) {
  # liste des actions
}

# conditions liées par ET
if allof (CONDITION_SIMPLE_1, CONDITION_SIMPLE_2, ..., CONDITION_SIMPLE_N) {
  # liste des actions
}

Une condition simple se compose d'un objet sur lequel porte la condition, d'un type de condition et de paramètres. La syntaxe globale d'une condition simple est donc (notez bien le : et le not optionnel) :

[not] OBJET_CONDITION :TYPE_CONDITION PARAMÈTRE_CONDITION_1 ... PARAMÈTRE_CONDITION_N  

Les objets souvent utilisés sont :

header
Il s'agit des champs de l'en-tête du message (Received, Subject, etc...)
size
La taille du message

Les paramètres des conditions dépendent quant à eux beaucoup du type de condition. Cela peut être une chaîne (ex. "CHAINE"), une taille (ex. 1M pour 1mo), un tableau de chaînes (ex. ["CHAINE_1","CHAINE_2",...,"CHAINE_N"]), etc...

Enfin les grand types de condition sont :

objet contains P V
qui vérifie que l'objet à au moins une valeur V dans sa partie P. P et V pouvant être des chaînes ou des tableaux.
objet matches P V
Comme contains mis à part que V peut contenir des chaînes avec des "jockers" (ex. "*@karma-lab.net")
objet over V
Qui vérifie que la valeur de l'objet est "supérieur à" V

Quelques exemples

Pour que tout cela passe mieux, voyons quelques exemple classiques :

if header :contains ["List-Id"] ["xorg.lists.freedesktop.org"] {
  fileinto "Mailling-Listes.xorg";
  stop;
}

On vérifie ici que la courriel est membre d'une mailling-liste donnée (champ List-Id du header) et on le déplace dans un dossier spécifique si tel est le cas.

if header :contains ["From"] ["mon_client.com"] {
  fileinto "mon client";
  stop;
}

Si le courriel vient d'une adresse donnée, on le place dans un dossier spécial.

if header :contains ["To"] [""] {
  fileinto "Publicites";
  stop;
}

Si le courriel est destiné à quelqu'un en particulier.

if header :contains ["Received"] ["12.34.56.78"]  {
  fileinto "Societe Betadure";
  stop;
}

Si le courriel a été reçu via un serveur SMTP (relais) particulier.

if size :over 1M {
  fileinto "gros courriels";
  stop;
}

Si le message est très gros, on le place dans un dossier particulier...

Les dossiers

Si vos messages ne sont pas filtrer et donc qu'une des règles semble échouer, il faut aller voir du côté des logs de votre serveur IMAP. Il se peut que vous ayez simplement un problème dans le nommage du dossier pour la commande fileinto du genre Invalid mailbox name ou mailbox doesn't exists. Les différentes pistes sont les suivantes :

  • L'encodage des accents. Certains serveur demande à ce que répondeur soit écrit deux.r&AOk-pondeur (ce n'est pas le cas de cyrus).
  • Le séparateur de dossiers. Selon les versions de cyrus, le séparateur doit être un . ou un /.
  • Racine de la boîte. Dans certaines version de cyrus les dossiers doivent commencer par la racine INBOX.
  • Racine des dossiers partagés. Selon le paramétrage de cyrus, la racine des dossiers partagée est la même que les dossiers standards ou doit être Shared Folders.

Conclusion

Voilà, fin du petit tour du petit langage sieve qui rend finalement de bien grands services.

Commentaires

Jean-François, le 10 septembre, 2007 - 18:48

Je suis en train de mettre en place un serveur smtp Postfix couplé à un serveur imap Cyrus. Autant dire que je suis heureux de lire cet article. Chapeau.

Une question : les filtres Sieve sont-ils forcément propres à UN utilisateur ? J'aimerais avoir un filtre qui classe certains messages arrivant dans une boîte, dans un dossier d'une autre boîte. Possible ?

Ulhume, le 10 septembre, 2007 - 23:45

Ravis que cela puisse servir (vu le peu de commentaires, dés fois j'ai des doutes Wink

Pour un script global, pour autant que je m'en souvienne, il suffit d'utiliser sieveshell avec l'utilisateur cyrus. Le script sera alors exécuté à l'échelle globale.

Dit moi si cela fonctionne !

Jean-François, le 11 septembre, 2007 - 11:27

Ben non justement ça marche pas pour un script global, c'est ce que j'avais essayé mais ça marche pas Frown

Autre chose qui serait de grande utilité : un tuto pour une installation complète Postfix / MySQL / cyrus-sasl / cyrus-imapd / Clamav / DSPAM / sieve le tout gérant des domaines virtuels. J'en trouve plein avec courier-imap mais cyrus-imap : désert. Ou alors sans le cas des domaines virtuels... avec un LDAP à la place de MySQL ça irait aussi... comme quoi je suis pas si difficile que ça !

Ulhume, le 11 septembre, 2007 - 12:09

C'est plus un tuto mais un livre qu'il faudrait là Smiling

Sur le site en cherchant tu devrais trouver "postfix/spamd", "postfix/cyrus/ssl", et "Cyrus/Sieve". Si tu ne trouves pas, dis-le moi, je te chercherais les pointeurs.

Pour ce qui est de postfix, j'avais le projet d'en écrire un mais c'est un monde à part entière ce soft. J'ai jamais eu le courage Smiling Et en plus cela demanderais une maîtrise du bignou que je suis bien loin d'avoir... Sinon, j'ai pas vraiment exploité les domaines virtuels, juste une attaque à la sauvage postfix/virtual.cf. Donc rien de bien serieux.

Pour MySql je ne sais pas, j'utilise pas.

Lone Wolf, le 4 novembre, 2008 - 07:16

Salut,

je connais Sieve depuis longtemps, et c'est vraiment un outil super pratique. J'aimerai ajouter à ton article que Horde (http://www.horde.org/) possède un outil d'édition des règles Sieve. C'est très pratique pour les utilisateurs normaux qui peuvent ainsi profiter des avantages de cet outil.

Et en bonus, un lien vers mon guide d'installation (facile ?) de Horde:

http://howto.landure.fr/lone-wolf-scripts/gnu-linux/debian-4-0-etch/inst...

Bonne continuation.

Ulhume, le 4 novembre, 2008 - 10:03
@Lone pas de soucis :) Au passage il existe aussi un plugin de ce genre pour SquirrelMail.
Yves Agostini, le 4 novembre, 2008 - 15:02

Pour ceux que ça intéresse, j'ai diffusé mes modules sur CPAN pour manipuler les filtres
http://search.cpan.org/dist/Net-Sieve/
ou leur contenu
http://search.cpan.org/dist/Net-Sieve-Script/

ils son également dispo sur debian lenny et ubuntu Intrepid

apt-get install libnet-sieve-perl libnet-sieve-script-perl
freeflyer, le 4 novembre, 2008 - 17:20

Sinon pour ceux qui utilisent Thunderbird, y'a un module "sieve" qui existe..
https://addons.mozilla.org/fr/thunderbird/addon/2548

Dup, le 5 novembre, 2008 - 00:29

Aller juste un mot pour ajouter que dovecot gère aussi les règles sieve Sticking out tongue

Quand à thunderbird j'ai pas bien pigé comment il marchait le module Glad

Ulhume, le 5 novembre, 2008 - 00:39

@Dup mais je l'ai mis, et en intro en plus !!! Smiling

Perso pour l'édition des scripts, après moultes essais de moultes modules qui m'ont systématiquement flingué ou au mieux crypté les sources des règles, je ne crois plus qu'en mon script basé sur vi. Lui au moins ne m'a jamais planté.

Dup, le 5 novembre, 2008 - 09:07

Erf j'ai commencé à lire à partir de Qu'est ce c'est Sieve inconsciemment lol

Ca va tu es pardonné Sticking out tongue

Ulhume, le 5 novembre, 2008 - 17:22

Ah bé vala, je vais plus faire d'intro moi, ça sert à rien Smiling

J'en profite, mais tu utilises dovcot de manière intensive ?

Dup, le 6 novembre, 2008 - 02:03

Intensive pas vraiment, mais il s'agit de mon serveur imap pour mon accès webmail & distant(thunderbird) en ssl.

Donc je suis en gros tout seul dessus mais je l'utilise combiné à postfix car il me paraissait plus simple à mettre en place que cyrus et on active les protocoles(pop3,pop3s,imap,imaps) que l'on désire dans le fichier de config.

Ulhume, le 6 novembre, 2008 - 02:08

@Dup en fait je me posais deux questions qui me feraient basculer direct :
1/ Est-ce qu'il y a un back-end postgresql
2/ Est-ce que les dossiers partagés sont enfin correctement supportés (autrement que par une immonde glute à base de ln -s)

Dup, le 6 novembre, 2008 - 02:54

1/ Bon en regardant vite fait la doc fourni avec le package dovecot j'ai pu y lire :

Currently supported user databases are:
* [AuthDatabase.SQL.txt]: SQL database (PostgreSQL, MySQL, SQLite)

Et idem pour l'authentification sur bdd.

2/ Dossier partagé, j'ai pu lire ca dans le dovecot.conf :
# You can have private, shared and public namespaces. The only difference
# between them is how Dovecot announces them to client via NAMESPACE
# extension. Shared namespaces are meant for user-owned mailboxes which are
# shared to other users, while public namespaces are for more globally
# accessible mailboxes.

J'ai pas testé si ca marchait bien, surtout a cette heure jme bats avec pam_ldap la, encore que je vais pas tarder à me coucher.

Ulhume, le 6 novembre, 2008 - 08:58

@Dup merci des infos ! Je vais sûrement tester cela rapidement.

Daniel, le 8 novembre, 2008 - 14:59

Juste qq infos pour ceux qui voudraient utiliser sieve avec dovecot.

Dans dovecot.conf, décommenter la ligne

protocol lda {
  ...
  mail_plugins = cmusieve
  # facultatif, un script sieve de filtrage par défaut, pour ceux qui n'auraient pas de filtres perso
  global_script_path = /path/qcq/globalsieverc
  ...
}

et ensuite, mettre ses règles sieve dans <racine du compte imap concerné>/.dovecot.sieve

Cf http://wiki.dovecot.org/LDA/Sieve pour qq exemple (répondeur, regex, colorier ses mails dans thunderbird) et http://casys.crevetor.org/index.php/Filtres_c%C3%B4t%C3%A9_serveur pour installer pysieved (je n'en ai jamais éprouvé le besoin car je trouve aussi pratique d'éditer mon fichier de filtres directement sur le serveur imap, mais ça peut servir).

Poster un nouveau commentaire

Si vous avez détecté une erreur, coquille ou bêtises du même ordre, merci de plutôt passer par le formulaire de contact
Pour vous abonner au flux des commentaires sur cet article, clickez ici.
Pour répondre à quelqu'un, utilisez plutôt le lien répondre qui se trouve en haut (ou en bas) à gauche de son commentaire.
Le contenu de ce champ sera maintenu privé et ne sera pas affiché publiquement. Si vous avez un compte gravatar, l'utilisez pour afficher votre avatar.
  • To highlight piece of code, just surround them with <code type="language"> Your code &tl;/code>>. Language can be java,c++,bash,etc... Everything Geshi support.
  • Tags HTML autorisés : <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <blockquote> <div> <p> <br>
  • Les lignes et les paragraphes vont à la ligne automatiquement.
  • Textual smileys will be replaced with graphical ones.
  • Les adresses de pages web et de messagerie électronique sont transformées en liens automatiquement.
  • Every instance of custom tags in the input text will be replaced with a specific tool shortcut.

Plus d'informations sur les options de formatage


Commentaires récents
Porte secrète