Ted écrit des trucs

Sur des sujets en lien avec la vie privée, ou parfois pas.

Gérer ses mails en local : étape 3 bis, du rab' de mutt :D

— modifié le

Ce billet fait partie d'une série d'articles présentant la façon dont je gère mes mails en local. Si vous êtes arrivés là sans lire l'introduction, c'est probablement une bonne idée de commencer par le début.


Donc, au cas où je ne vous ai pas convaincu que mutt c'était le Bien™, que l'article précédent vous a laissé perplexes et que vous êtes en train de vous dire que c'est quand même beaucoup de travail pour avoir quelque chose de vraiment chouette à utiliser, je vais faire un second essai pour vous convaincre. Entre autres, je vais essayer de vous convaincre qu'on peut ajouter des fonctionnalités vraiment avancées et personnalisées si on a envie, tout comme on peut émuler à peu près n'importe quel avantage d'un client mail grand public.

Quelques macros pour commencer

Quand j'ai commencé à recevoir un nombre de mails par jour qui se comptait en dizaines et non plus en unités, il s'est vite posé le problème des mails importants qui se font enterrer sous des piles de messages qui le sont moins. Je me suis donc mis à utiliser la fonction « flag » (F comme raccourci, pour faire apparaître un message en surbrillance si on a un jeu de couleurs adapté) pour marquer tous les mails auxquels je devais répondre, ou qui contenaient quelque chose dont je devais m'occuper. Malheureusement, ça ne suffisait pas, une fois que le message en question était trop loin dans ma liste de mails pour apparaître, j'oubliais son existence.

J'ai trouvé une solution qui me convient en utilisant des macros qui listent les messages susceptibles d'être importants, et n'affichent que ceux-là. J'utilise des raccourcis commençant par une virgule, parce que c'est la touche qui fait office de <Leader> dans ma configuration de vim, du coup j'ai l'habitude de la combiner avec d'autres. Donc, les messages dont je suis susceptible de devoir m'occuper sont les messages marqués comme importants, ceux que je n'ai pas encore lus, ainsi que les récents auxquels je n'ai pas répondu alors qu'ils me sont adressés personnellement. Ça donne :

macro index ,r "l((~N|~O|~F)!~D!~P)|(~d<1w!~Q)\n"

ceux qui sont systématiquement dignes d'intérêt sont les messages non lus, ou ceux explicitement notés comme importants (avec la fonction de flag) :

macro index ,i "l((~N|~O|~F)!~D!~P)\n"

et on a besoin d'un raccourci facile pour revenir à la vue normale, où l'on voit tous les mails :

macro index ,, "l~A\n"

ce qui fait que cette astuce n'est pas juste un bout de config' dont je ne me sers pas, c'est qu'en fait, j'exécute la commande ,r (qui montre les messages potentiellement intéressants) à chaque fois que j'ouvre un dossier dans mutt :

folder-hook . push ',r=*'

et cette vue-là contient (en pratique) toujours les mails marqués comme importants, parce qu'elle cache tous les mails auxquels j'ai répondu ou ceux dont je ne suis pas le destinataire.

Gérer les pièces jointes et les mails en HTML

Dans un client mail graphique, on peut en général naviguer dans un menu pour indiquer au programme avec quoi on veut ouvrir les pièces jointes. Dans mutt, cette configuration se fait via le fichier indiqué dans la variable maicap_path du .muttrc. Dans le mien, il y a :

set mailcap_path = ~/.mutt/mailcap

et dans le fichier en question, on met une ligne par type de fichier. Par exemple, dans le mien, on trouve :

application/pdf; chromium %s
image/*; feh %s

pour dire d'ouvrir les PDFs avec Chromium (oui, c'est ce que j'utilise comme lecteur PDF, faute de mieux), et les fichiers de type « image » (jpg, png, etc.) avec feh.

Le fichier mailcap sert aussi à indiquer comment on veut lire les mails en HTML. Ces atrocités ne devraient pas exister et les auteurs des clients mails qui en envoient par défaut devraient mourir par le feu, mais dans la vraie vie, les mails en HTML existent, on les reçoit et il faut bien en faire quelque chose. J'utilisais une solution sale à base de w3m à une époque, et puis a3nm m'a soufflé la solution tout aussi crade mais un peu plus efficace suivante :

text/html; ~/.bin/mutt_bgrun firefox %s > /dev/null 2> /dev/null; nametemplate=%s.html
text/html; iconv -f %{charset} %s | elinks -dump %{charset} -dump -dump-color-mode 1 -dump-width 76 /dev/stdin 2>/dev/null | sed 's/ * $//' | sed 's/   //' ; copiousoutput

elle utilise links par défaut pour afficher le corps du message (ce qui donne en général un résultat, heu, pas très beau, mais si le contenu n'est pas trop bourré de CSS affreux, ça reste lisible, et ça permet d'afficher rapidement les liens présents dedans). Si ça ne suffit pas, alors je tape v pour ouvrir la liste des fichiers constituant le mail, et si je sélectionne celui en .html, c'est Firefox qui me l'ouvre dans un nouvel onglet. C'est assez sale parce qu'il faut un script supplémentaire (disponible ici, ce n'est pas moi qui l'ai écrit) et que l'appel à ELinks est prévue pour fonctionner avec une taille de fenêtre fixe (ici, 76 caractères de large).

Le contenu complet de mon fichier mailcap est disponible par ici.

Un script pour les étourdis dans mon genre

Ça va paraître absurde, mais une des choses qui m'a le plus manqué quand je suis passé de l'interface Web de GMail à mutt, c'est la fonctionnalité (ou peut-être est-ce une extension, je ne me souviens plus) « afficher un message de confirmation lorsqu'on essaie d'envoyer un message dont le contenu a l'air de sous-entendre qu'il faudrait qu'il y ait une pièce jointe, mais qu'il n'y en a pas ». Parce que les mails suivis immédiatement d'un second mail « Oups, j'ai oublié la pièce jointe, la voilà », ça ne fait pas très sérieux (surtout quand on oublie la pièce jointe dans le second mail (ne riez pas)).

Mais, magie des possibilités infinies de configuration de mutt, il suffit de faire un script qui fait ça. J'en ai trouvé un sur le wiki de mutt, que je me souviens d'avoir modifié à plusieurs reprises mais je ne me souviens plus pourquoi exactement. La version que j'utilise est disponible par là, et l'idée est de remplacer l'appel à msmtpq de la variable sendmail du .muttrc par un appel à ce script. Si on l'appelle avec des paramètres, il appellera msmtpq avec les mêmes paramètres, donc ça marche bien (et ça m'a évité d'être ridicule un nombre de fois ridiculeusement élevé). Il nécessite zenity pour afficher le message de confirmation.

t-prot, pour économiser de la place sur l'écran

Je n'ai rien contre les gens qui répondent aux mails en coupant le message original en morceaux, et en répondant entre les morceaux : lorsque le mail concerne plusieurs points distincts, c'est plutôt pratique et je fais moi-même comme ça de temps en temps. Le problème, c'est que les informations moins utiles (les anciens messages auxquels on répond, qui portent le joli nom de TOFU) peuvent parfois prendre une place démesurée sur l'écran, si on ne prend pas la peine de couper le passage cité et qu'il y a plusieurs réponses imbriquées. Sur certaines mailing-lists, c'est un vrai problème, parce que six pages successives pour un message où il n'y a qu'une vingtaine de lignes ajoutées par rapport aux messages précédents, c'est pas du tout pratique.

Et donc sans surprise, des gens ont écrit un script qui résout le problème, et qui tronque le TOFU pour faciliter la lecture du nouveau contenu. Ça s'appelle t-prot, c'est disponible par ici et l'installation consiste juste à le mettre quelque part dans son $PATH en le rendant exécutable. Puis, dans le .muttrc, il faut ajouter quelques lignes pour l'invoquer automatiquement…

set display_filter='t-prot -cemt --pgp-move-vrf --pgp-short --bigq=10,4 -Mmutt -S -s -w'

… quelques macros pour s'en servir aisément (ici, 0 pour voir le message original, et 1 pour réactiver le tronquage du TOFU)…

macro generic 0 ":unset display_filter\n" "Turn TOFU protection off"
macro generic 1 ":set display_filter='t-prot -cemt --bigq=10,4 -M=mutt -S -s -w'\n" "Turn TOFU protection on"
macro pager 0 ":unset display_filter; exec exit\n:exec display-message\n" "Turn TOFU protection off"
macro pager 1 ":set display_filter='t-prot -cemt --bigq=10,4 -M=mutt -S -s -w'; exec exit\n:exec display-message\n" "Turn TOFU protection on"

… et un peu de couleurs pour qu'on voie quand t-prot a fait disparaître quelque chose :

color body      brightmagenta   black   "^\\[---.*"
color body      green           black   "^#v[-+]"

si vous êtes inscrits sur des listes de diffusion, ce truc tout bête a le potentiel de vous changer la vie :-)

Indexation efficace avec notmuch

Une des choses qui a probablement fait le succès de GMail, c'est son outil de recherche de messages : rapide, efficace et facile à utiliser. Mutt a aussi un système de recherche utilisant des expressions régulières, et qui est donc très puissant et permet de faire des requêtes qui correspondent exactement à ce qu'on recherche. Le problème, c'est que lorsqu'on commence à vouloir rechercher un terme présent dans le corps d'un message parmi une boîte mail en contenant plusieurs milliers… Ça prend un temps linéaire en la taille de la boîte et donc c'est un peu long.

Mais joie, bonheur et allégresse : il existe un indexeur, Notmuch, qui permet de rendre le traitement de ce type de requête instantanée. Ça prend un peu de place sur le disque dur (j'ai 4 Go de mails, et les bases de données de notmuch nécessitent 700 Mo), mais vu le prix du Go de nos jours, c'est vraiment pas un problème. Donc, pour installer cette petite merveille, on passe par les paquets :

aptitude install notmuch

et on a un peu de configuration à faire une fois que c'est fait, mais il n'y a même pas besoin de modifier le moindre fichier de configuration. Il suffit en effet de lancer la commande :

notmuch setup

et de répondre gentiment aux questions permettant au programme de savoir quels sont les mails qui viennent de nous, où ils se trouvent sur le système, etc.

Une fois que c'est fait, on rajoute quelques macros dans mutt pour utiliser la recherche par notmuch de la façon la plus naturelle possible :

macro index S "<enter-command>unset wait_key<enter><shell-escape>notmuch-mutt --prompt search<enter><change-folder-readonly>~/.cache/notmuch/mutt/results<enter>" "search mail (using notmuch)"
macro index L "<enter-command>unset wait_key<enter><shell-escape>read -p 'notmuch query: ' x; echo \$x >~/.cache/mutt_terms<enter><limit>~i \"\`notmuch search --output=messages \$(cat ~/.cache/mutt_terms) | head -n 600 | perl -le '@a=<>;chomp@a;s/\^id:// for@a;$,=\"|\";print@a'\`\"<enter>" "show only messages matching a notmuch pattern"

ici, les touches S et L (respectivement « Search » et « Limit ») fonctionnent de la même façon que leurs homologues en minuscules par défaut dans mutt, sauf qu'ils utilisent le moteur de notmuch pour faire leur recherche. C'est aussi simple que ça !

On me signale dans l'oreillette que notmuch permet de faire des choses encore plus cool que ça, par exemple de l'étiquetage de messages, mais n'ayant jamais testé cette fonctionnalité, je ne peux pas vous en dire grand-chose.

Conclusion provisoire

Bon, cette fois, je ne crois pas avoir oublié grand-chose (mis à part l'utilisation intensive de PGP qui mérite un article à part). Il faudrait peut-être que je mentionne le réglage sendmail_wait de mutt, qui est un compromis relativement important entre le temps d'attente nécessaire pour mettre un mail envoyé dans la file de msmtpq, et le temps que je me laisse pour répondre « non » au script qui vérifie si je n'ai pas oublié une pièce jointe, mais du coup, je ne sais pas trop dans quelle section en parler. Je verrai ça plus tard.

Tout ce que je raconte ici sont mes opinions personnelles, pas celles de mon employeur.
Je suis toujours ravi de recevoir des réactions, critiques, questions, ou autres commentaires sur ce que j'écris. Envoyez-moi ce qui vous chante à se.niatnofsed@neimad.