Sieve est un langage de script de manipulation d'emails côté serveur. On peut classer des emails dans un dossier, écrire un répondeur, ignorer des spams, évaluer le retour d'un antivirus, chiffrer les emails entrants (avec un plugin, pas juste du Sieve), etc. RFC 5228. Beaucoup d'extensions : RFC 5233 pour travailler plus simplement sur des sous-adresses (étiquettes), RFC 5232 pour manipuler les drapeaux IMAP, RFC 5230 pour un répondeur, RFC 5235 pour évaluer simplement le résultat d'un antivirus / antispam, etc.
Les utilisateurs peuvent envoyer leurs scripts à leur serveur emails avec le protocole ManageSieve (je ne le fais pas, je passe par SSH).
Comme toujours, il y a la norme technique et les implémentations. Pour ma part, j'utilise Pigeonhole, l'implémentation de Sieve de Dovecot (qui, en sus d'être un serveur IMAP / POP peut aussi être un MDA, un agent local de livraison des emails, qui s'occupe des derniers kilomètres, comme un facteur humain, nommé dovecot-lda
). Documentation. Exemples. Autres exemples.
Un script Sieve est compilé (en une représentation binaire) afin d'accélérer son exécution. Dovecot y procède si le binaire n'existe pas (et on peut utiliser la commande sievec
pour le faire nous même), c'est le fichier ~/.dovecot.svbin
(qu'on peut lire avec sieve-dump
).
Ci-dessous, je note les quelques syntaxes que j'utilise.
[]
: liste de chaînes de caractères. On peut bosser sur plusieurs entêtes et/ou plusieurs valeurs en une expression.
require
: charger des extensions. Ex. : require ["fileinto", "envelope", "subaddress", "imap4flags", "body"];
if
/ elsif
/ else
if not
if anyof (condition_1, condition_2)
: OR (« ou » logique), une seule condition suffit
if allof (condition_1, condition_2)
: AND (« et » logique), il faut remplir toutes les conditions
Quelques commandes de test (en sus de not
, anyof
et allof
qui figurent déjà ci-dessus :
envelope
(nécessite le chargement de l'extension du même nom) : travailler sur l'enveloppe (MAIL FROM
, RCPT TO
, etc.)header
: travailler sur un ou plusieurs entête de l'emailaddress
: sous-ensemble de header
, portant uniquement les adresses (expéditeur, destinataire, copie, etc.)body
: travailler sur le corps de l'emailexists
(un entête existe), size
, etc.if header :is "Subject" "Check out my profile on LinkedIn"
: si le sujet est « Check out my profile on LinkedIn »
if header :contains "Subject" "Check out my profile on LinkedIn"
: si le sujet contient, entre autres la chaîne « Check out my profile on LinkedIn »
La comparaison entre un entête ou le corps de l'email et une chaîne de caractère n'est pas sensible à la case (parce que la norme du format des emails l'impose). Y compris les adresses emails (dont la partie locale est sensible à la case, pour rappel). Pour avoir une sensibilité à la case : if header :comparator "i;octet" :contains "Subject" "LoLmDr"
/ if address :comparator "i;octet" :localpart :is "From" "ToTo"
.
if address :is "From" "invitations@linkedin.com"
if address :contains "From" "@newsletter.voyages-sncf.com"
/ if address :domain :is "From" "newsletter.voyages-sncf.com"
: comparer uniquement le domaine (inversement, il existe :localpart
)
if header :contains "From" "quelquechose"
: chercher plus librement dans tout le From (ou dans le To ou…), pas juste dans l'adresse. J'y ai déjà eu recours quand address
ne matchait pas sur le domaine d'une adresse pour une raison qui m'échappait.
if address :is "To" "toto@example.com"
/ if header :is "To" "toto@example.com"
if envelope :is "To" "toto@example.com"
/ if header :is "Delivered-To" "toto@example.com"
: quand l'adresse de destination ne figure pas dans les entêtes (copie cachée, alias, liste, etc.)
if header :contains "List-Id" "nomliste.lists.example.com"
: quand l'email provient d'une liste de diffusion précise
if exists "List-ID"
: l'email provient d'une liste de diffusion (sans chercher laquelle)
if address :contains "To" "+test"
/ if address :detail :is "To" "test"
/ if envelope :contains "To" "+test"
/ if envelope :detail :is "To" "test"
: travailler sur une étiquette / sous-adresse (« test » dans « toto+test@example.com »). (Les 2e et 4e syntaxes nécessitent l'extension subaddress
. La 4e nécessite de configurer Postfix pour transmettre l'adresse complète à Dovecot-lda, « toto+test@example.com » au lieu de « toto@example.com » en laquelle Postfix l'aura résolu.)
if body :contains "blablabla"
(nécessite l'extension du même nom)
Il existe également l'extension regex
.
L'ordre des paramètres d'une commande n'est pas important : if address :is :domain :comparator "i;octet" "From" "example.com"
= if address :comparator "i;octet" :domain :is "From" "example.com"
, alors que seule la 2e respecte strictement le RFC. Évidemment, il ne faut pas inverser l'entête sur laquelle on travaille et sa valeur (ex. de truc foireux : if header :is "example.org" "From"
), car le compilateur ne les détecte pas tous (comme l'exemple donné ici), et c'est logique. Le type de comparaison (exacte avec :is
, sous-chaîne avec :contains
, ou métacaractères / joker avec :matches
) est optionnel et vaut :is
par défaut, mais je trouve que ne pas l'indiquer rend la règle illisible.
Toutes les actions doivent être suivies d'un point-virgule.
discard
: ignorer un email (il disparaît)
fileinto "dossier"
(nécessite l'extension fileinto) : déplacer l'email dans le dossier nommé « dossier »
setflag "\\Seen"
(nécessite l'extension imap4flags
) : marquer l'email comme lu. Il doit être positionné avant un fileinto. / fileinto :flags "\\Seen" "dossier"
stop
: ne pas poursuivre l'exécution du script car on a fait tout ce qu'on voulait
Il existe aussi redirect
, vacation
(répondeur, cf. ci-dessous), etc.
Pour tester un script (aussi bien sa syntaxe que son effectivité), Dovecot propose la commande sieve-test <chemin/vers/script/sieve> <email_à_tester>
. (Évidemment, le script sera compilé, donc analysé en entier, donc toute erreur de syntaxe sera remontée, même si l'email ne déclenche qu'un sous-ensemble.) Si l'on veut juste tester la syntaxe, on peut uniquement compiler le script : sievec .dovecot.sieve
.
Pour appliquer un script Sieve sur des emails déjà réceptionnés : sieve-filter
(attention : le manuel exige d'être très prudent, bugs, tout ça).
Aeris avait mis à disposition le script Sieve suivant qui envoie un email à toute personne le contactant avec une adresse email hébergée par un GAFAM. Je le recopie ci-dessous. Dovecot n'envoie pas l'email en réponse à une liste de diffusion et autres messages de masse (source).
if anyof (
address :is :domain "From" "gmail.com",
address :is :domain "From" "live.com",
address :is :domain "From" "msn.com",
address :is :domain "From" "hotmail.com",
address :is :domain "From" "hotmail.fr",
address :is :domain "From" "yahoo.com",
address :is :domain "From" "yahoo.fr"
) {
vacation :days 1 :subject "Protection de la vie privée" text:
### Message automatique ###
Bonjour,
Vous m’écrivez depuis une adresse mail dont le fournisseur ne respecte pas ma
vie privée et dont je n’ai aucunement approuvé les conditions générales
d’utilisation liberticides.
Je vous saurai donc gré de cesser d’utiliser cette adresse pour me joindre, et
de vous tourner vers des fournisseurs de mail respectueux de ma vie privée (à
défaut de la vôtre).
Votre mail ne recevra donc probablement aucune réponse de ma part, afin de ne
pas continuer à fournir mes données privées à votre fournisseur.
https://imirhil.fr/et-puis-merde-à-la-vie-privée.html
--
Aeris
Protégez votre vie privée, chiffrez vos communications
GPG : EFB74277 ECE4E222
OTR : 5769616D 2D3DAC72
https://café-vie-privée.fr/
.
;
}