Retour à l'accueil

Gestion des courriels avec Mutt et cie.

Programmer la manipulation des courriels

Il y a bien longtemps, je lisais mes courriels personnels à l’aide du logiciel Mozilla Thunderbird. Par la suite, j’ai découvert comme bien des gens la puissante interface Web GMail qui est impressionnante et bien faite. À l’automne 2019, j’ai voulu m’éloigner des produits GAFAM et en particulier de Google par principe. J’ai donc abandonné le service gratuit Gmail pour le service payant Protonmail basé en Suisse. De mon point de vue, ce service a l’avantage de joindre une signature GPG et de permettre d’envoyer des courriels cryptés. C’est ce que je n’arrivais pas à faire avec Gmail. Le seul défaut de Protonmail est qu’il n’a pas de serveur IMAP facile à configurer.

Tout ça, ça concerne mes courriels personnels. Par ailleurs, pour mes courriels professionnels, cela fait très longtemps que j’utilise Thunderbird. Je suis sous Linux pratiquement à 100 % depuis des années. C’est naturel de choisir Thunderbird qui est souvent installé par défaut sur la plupart des distributions Linux.

Mais Thunderbird ne me satisfaisait pas complètement. Je cherchais à automatiser (programmer) des tâches de manipulation des courriels. Thunderbird a la possibilité d’ajouter des modules (plugins), mais je n’ai pas trouvé de module assez impressionnant qui automatise la manipulation des courriels. Je me suis donc lancé dans la recherche d’un meilleur gestionnaire de courriels.

D’autres gestionnaires graphiques existent, mais rien ne me convenait.

J’ai donc regardé du côté des logiciels de gestion de courriels en mode texte comme Mutt, Pine et Sup. Un peu par hasard, je suis tombé sur Notmuch qui permet une recherche efficace des courriels. Ça m’a impressionné. C’est comparable à l’outil de recherche intégré de Gmail.

La recherche par Notmuch

L’outil de recherche d’un gestionnaire de courriels est important. Sous Thunderbird, j’utilisais un module complémentaire qui permettait des recherches plus précises et rapides (ce module n’existe plus sur les versions récentes de Thunderbird). Le logiciel Notmuch semblait me fournir la même puissance (ou plus).

Par contre, Notmuch n’est pas un gestionnaire de courriels à proprement dit. Il permet la recherche sans fournir la manipulation des courriels. J’ai donc fouillé un peu plus pour obtenir un outil en relation avec Notmuch.

Gestionnaire de courriels Mutt

Mutt est le gestionnaire de courriels le plus connu en relation avec Notmuch. Je me suis donc lancé dans la configuration de Mutt pour gérer mes courriels professonnels avec le plus d’aisance possible comme Thunderbird me l’offrait.

Passer de Thunderbird à Mutt

Mutt et Notmuch utilisent le format de courriel EML. Le format standard Thunderbird est MBOX. Une conversion est nécessaire pour transférer les courriels de Thunderbird vers Mutt.

Pour faire la conversion de mes courriels sous Thunderbird, j’ai utilisé le module Import-Export-NG dans Thunderbird.

Il y a plusieurs avantages au format EML sur le format MBOX. Les messages en format EML sont stockés dans des fichiers séparés contrairement à MBOX qui est un seul fichier qui regroupe tous les courriels. Avec le format EML, Notmuch peut se permettre facilement d’indexer tous les courriels (comme on peut indexer des fichiers) pour permettre une recherche rapide.

Configurer Mutt

Mutt offre beaucoup de fonctionnalités de configuration. Beaucoup sur le Web ont expliqué en détails tous les aspects de configuration possible, par exemple, ce qu’on retrouve dans ce guide https://wiki.archlinux.org/index.php/Mutt.

Je présente ici seulement quelques éléments de configuration (tout le code doit se retrouver dans le fichier ~/.mutt/.muttrc).

D’abord, l’édition des messages se fait par défaut avec Vim sous Mutt. J’ai gardé cet éditeur, mais j’y ai modifié un peu la configuration Vim comme suit:

set editor="vim -f -g -c 'set noautoindent filetype=mail wm=0 tw=0 norelativenumber list! nopaste formatoptions-=t'"

Dans la configuration Mutt, j’ai décidé que tous les courriels soient enregistrés dans un même dossier .imap. Comme bien des applications de type Unix, Mutt délègue la récupération des courriels à une application tierce. Dans ce cas, la récupération IMAP des courriels se fait par le programme tiers appelé offlineimap. Je vais y revenir un peu plus tard.

Voici la configuration Mutt pour le dossier en question:

set mbox_type=Maildir
set folder=~/.imap/
set spoolfile=~/.imap/INBOX
set record=~/.imap/Sent
set header_cache=~/.imap/hcache
mailboxes `find ~/.imap/ -type d -name cur -printf '%h '`

Pour l’envoi des courriels SMTP, voici une configuration partielle en exemple:

set hostname = "serveur-imap-du-travail"
set smtp_url = "smtp://demers@...:587/"
set ssl_force_tls = yes
set smtp_authenticators = "login"
set from = "demers@..."
set realname = "F.-Nicola Demers"

Pour éviter d’insérer le mot de passe SMTP dans le fichier de configuration, j’utilise le programme pass. Le mot de passe est récupéré par l’exécution de la commande pass. À la première exécution, la commande pass va demander le mot de passe de décryption GPG et s’en souvenir pour un certain temps pour les exécutions subséquentes.

set smtp_pass = `pass local/mutt`

Il est possible d’avoir accès à des alias. Voici la configuration pour ces alias:

set alias_file = "~/.mutt/aliases"
set sort_alias = alias
set reverse_alias = yes
source $alias_file

Une signature est possible d’être ajoutée automatiquement aux courriels à envoyer:

set signature="~/.mutt/signature.txt"

Le fichier mailcap est un fichier qui indique à Mutt comment convertir le contenu des courriels en format texte. Il faut se rappeler que Mutt est un gestionnaire en mode texte seulement. Tout ce qui est visuellement graphique doit être converti en format texte. Je reviendrai sur le contenu de ce fichier. Voici où se situe ce fichier:

set mailcap_path = "~/.mutt/mailcap"

Mutt est vraiment particulier et avantageux parce qu’il est capable de convertir tous les contenus en format texte. On peut spécifier l’ensemble des formats visibles qui seront considérés:

auto_view application/zip
auto_view application/x-gzip
auto_view application/x-gunzip
auto_view application/octet-stream
auto_view application/x-zip-compressed
auto_view application/x-tar-gz
auto_view application/msword
auto_view application/x-perl
auto_view application/x-sh
auto_view application/x-tcl
auto_view application/RTF
auto_view text/html
auto_view text/x-vcard
auto_view image/tiff
auto_view text/calendar
alternative_order text/plain text/enriched text/html text/calendar

Quand on consulte la liste des messages (l’index), il est intéressant de voir les messages qui contiennent des fichiers joints ou non. C’est visible par la lettre “A” vis-à-vis chaque courriel. Voici comment l’obtenir.

set index_format="%4C %Z %{%b %d} %?X?A&-? %{%y%m%d} %-12.12L %?M?(#%03M)&(%4c)? %?y?(%.20Y) ?%s"

Voici quelques configurations reliées à la langue française:

set rfc2047_parameters = yes
set config_charset = "utf-8"

set attribution = "Le %d, %n a écrit:"
set date_format = "%d/%m/%Y %H:%M"

Mutt offre une configuration assez sophistiquée du chiffrement des messages. Tous mes messages sont signés avec ma signature GPG. Voici mes paramètres:

set crypt_autoencrypt           = no
set crypt_autopgp               = yes
set crypt_autosign              = yes
set crypt_autosmime             = yes
set crypt_confirmhook           = yes
set crypt_opportunistic_encrypt = no
set crypt_replyencrypt          = yes
set crypt_replysign             = yes
set crypt_replysignencrypted    = yes
set crypt_timestamp             = yes
set crypt_use_gpgme             = no
set crypt_use_pka               = no
set crypt_verify_sig            = yes

set ssl_starttls     = yes
set ssl_use_sslv3    = no
set ssl_use_tlsv1    = yes
set ssl_use_tlsv1_1  = yes
set ssl_use_tlsv1_2  = yes
set ssl_verify_dates = yes
set ssl_verify_host  = yes

set pgp_autoinline      = no
set pgp_auto_decode     = yes
set pgp_check_exit      = yes
set pgp_entry_format    = "%4n %t%f %4l/0x%k %-4a %2c %u"
set pgp_good_sign       = "Good signature from"
set pgp_ignore_subkeys  = yes
set pgp_long_ids        = no # mutt uses full fingerprint internally
set pgp_mime_auto       = no
set pgp_replyinline     = no
set pgp_retainable_sigs = yes
set pgp_show_unusable   = no
set pgp_sign_as         = "0xXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
set pgp_sort_keys       = address
set pgp_strict_enc      = yes
set pgp_timeout         = 21600 # Remember PGP passphrase for 6 hours

# PGP Commands
set pgp_clearsign_command    = "gpg2 --batch --output - %?p?--passphrase-fd 0? --armor --textmode --clearsign %?a?-u %a? %f"
set pgp_decode_command       = "gpg2 --status-fd=2 %?p?--passphrase-fd 0? --quiet --batch --output - %f"
set pgp_decrypt_command      = "gpg2 --status-fd=2 %?p?--passphrase-fd 0? --quiet --batch --output - %f"
set pgp_encrypt_only_command = "/usr/lib/mutt/pgpewrap gpg2 --batch --quiet --output - --encrypt --textmode --armor --always-trust -- -r %r -- %f"
set pgp_encrypt_sign_command = "/usr/lib/mutt/pgpewrap gpg2 %?p?--passphrase-fd 0? --batch --quiet --textmode --output - --encrypt --sign %?a?-u %a? --armor --always-trust -- -r %r -- %f"
set pgp_encrypt_sign_command = "/usr/lib/mutt/pgpewrap gpg2 %?p?--passphrase-fd 0? --batch --quiet --textmode --output - --encrypt --sign %?a?-u %a? --armor --always-trust -- -r %r -- %f"
set pgp_export_command       = "gpg2 --export --armor %r"
set pgp_getkeys_command      = ""
set pgp_import_command       = "gpg2 --import -v %f"
set pgp_list_pubring_command = "gpg2 --with-colons --with-fingerprint --list-keys %r"
set pgp_list_secring_command = "gpg2 --with-colons --with-fingerprint --list-secret-keys %r"
set pgp_sign_command         = "gpg2 --comment 'I welcome encrypted mail.' --batch --output - %?p?--passphrase-fd 0? --armor --detach-sign --textmode %?a?-u %a? %f"
set pgp_verify_command       = "gpg2 --status-fd=2 --quiet --batch --output - --verify %s %f"
set pgp_verify_key_command   = "gpg2 --verbose --batch --fingerprint --check-sigs %r"

Configuration Mailcap

Mailcap est un fichier de configuration qui détermine les dépendances aux applications en ligne de commande. Mailcap délègue la conversion pour convertir les contenus en format texte. Le programme de conversion le plus utilisé est celui qui convertit le format HTML en format texte. Dans ce cas-ci, j’utilise l’application w3m. La conversion me semble la meilleure. La conversion des fichiers de format Word sont convertis avec antiword et docx2txt. Les fichiers PDF sont convertis par pdftotext. Les images pourraient être converties en format texte (cacaview). Mais pour simplifier, je fais exception et je rends visible les images par un visionneur graphique léger appelé Fim. D’ailleurs, Mutt n’empêche pas d’utiliser des visualiseurs graphiques si on le désire. Enfin, les fichiers compressés sont rendus visibles par Zip, Tar et 7zip.

Cette approche de (presque) tout convertir en format texte est avantageuse parce que, quand on lit nos courriels, on ne veut pas nécessairement enregistrer ou modifier les fichiers. On effectue souvent une première lecture rapide sans répondre nécessairement. On veut simplement visualiser le contenu rapidement. Mutt fait donc une conversion très rapide du contenu sans ouvrir l’application associée. Pensons surtout aux documents MS Office. Sous Linux, pour lire ces formats (doc, docx, xls, etc.), il faut utiliser l’application Libre Office qui est lourde et longue à démarrer; surtout quand on veut simplement consulter le contenu. La conversion en format texte est tellement plus rapide!

De plus, c’est très sécuritaire puisque aucun virus ne peut être exécuté du fait que les convertisseurs ne tiennent pas compte des virus ou codes cachés.

Même les liens URL ne sont pas visibles directement. Il faut utiliser une application tierce appelée Urlscan qui affiche les liens et offre de consulter les URLs dans un fureteur externe. J’utilise Luakit.

Mutt convertit en format texte, mais il est aussi possible de visualiser le contenu HTML en format HTML. J’utilise le fureteur léger Luakit.

Voici une partie de ce fichier de configuration Mailcap:

text/html; ~/bin/view_luakit.bash '%s' &; test=test -n "$DISPLAY"; needsterminal;
text/html; w3m -I %{charset} -T text/html -dump; copiousoutput;

application/gpg; gpg -d %s; copiousoutput

text/pdf; pdftotext -layout '%s' -; copiousoutput
application/pdf; pdftotext -layout '%s' -; copiousoutput
application/x-pdf; pdftotext -layout '%s' -; copiousoutput
application/x-bzpdf; pdftotext -layout '%s' -; copiousoutput
application/x-gzpdf; pdftotext -layout '%s' -; copiousoutput
image/*; fim %s ; copiousoutput

application/msword; antiword -w 96 '%s'; copiousoutput
application/vnd.openxmlformats-officedocument.wordprocessingml.document; docx2txt '%s' -; copiousoutput

application/vnd.oasis.opendocument.text; odt2txt --width=96 '%s'; copiousoutput
application/vnd.oasis.opendocument.text-master; odt2txt --width=96 '%s'; copiousoutput
application/vnd.oasis.opendocument.text-template; odt2txt --width=96 '%s'; copiousoutput
application/vnd.oasis.opendocument.text-web; odt2txt --width=96 '%s'; copiousoutput
application/vnd.oasis.opendocument.presentation; odt2txt --width=96 '%s'; copiousoutput
application/vnd.oasis.opendocument.presentation-template; odt2txt --width=96 '%s'; copiousoutput
application/vnd.sun.xml.writer; odt2txt --width=96 '%s'; copiousoutput
application/vnd.sun.xml.writer.template; odt2txt --width=96 '%s'; copiousoutput
application/vnd.sun.xml.writer.global; odt2txt --width=96 '%s'; copiousoutput
application/vnd.sun.xml.calc; odt2txt --width=96 '%s'; copiousoutput
application/vnd.sun.xml.calc.template; odt2txt --width=96 '%s'; copiousoutput
application/vnd.sun.xml.impress; odt2txt --width=96 '%s'; copiousoutput
application/vnd.sun.xml.impress.template; odt2txt --width=96 '%s'; copiousoutput

text/csv; less '%s'; copiousoutput
text/tab-separated-values; less '%s'; copiousoutput

application/x-bzip; tar --list '%s'; copiousoutput
application/x-bzip1; tar --list '%s'; copiousoutput
application/x-bzip-compressed-tar; tar --list '%s'; copiousoutput
application/x-bzip1-compressed-tar; tar --list '%s'; copiousoutput
application/x-tar; tar --list '%s'; copiousoutput
application/x-tarz; tar --list '%s'; copiousoutput
application/x-lzma; xz -l '%s'; copiousoutput
application/x-lzma-compressed-tar; xz -l '%s'; copiousoutput
application/x-xz; xz -l '%s'; copiousoutput
application/x-xz-compressed-tar; xz -l '%s'; copiousoutput
application/x-7z-compressed; 7z l '%s'; copiousoutput
application/x-7z-compressed-tar; tar --list '%s'; copiousoutput
application/x-zip; unzip -l '%s'; copiousoutput
application/x-zip-compressed; unzip -l '%s'; copiousoutput
application/zip; unzip -l '%s'; copiousoutput

text/calendar; vcalendar-filter; copiousoutput

Configuration OfflineMap

OfflineMap est une application qui permet de télécharger les courriels localement sous forme de tâche en lot. Quand on applique des changements sur les courriels localement, OfflineMap va synchroniser (faire les mises à jour sur le serveur en conséquence). Je l’utilise pour stocker mes courriels dans le dossier .imap. Le fichier de configuration est .offlineimaprc. Pour éviter de stocker le mot de passe du serveur, j’utilise un script Bash qui insère le mot de passe à la volée. Par la même occasion, je me sers de ce script pour supprimer les messages auxquels une étiquette deleted a été ajoutée. Pour ce faire, j’ai été inspiré par le billet suivant. Voici mon script Bash:

#!/bin/bash

notmuch search --output=files tag:deleted > /tmp/offlineimap_files.txt
mapfile -t liste_fichiers < /tmp/offlineimap_files.txt

for x in "${liste_fichiers[@]}"
do
    rm -f "$x"
done

MP=$(pass local/mutt)
sed "s/PASSWORD/$MP/g" ~/.offlineimaprc > /tmp/.offlineimaprc
offlineimap -l ~/.offlineimaplog -c /tmp/.offlineimaprc
rm -f /tmp/.offlineimaprc

Voici le contenu de mon fichier de configuration .offlineimaprc. Le texte PASSWORD est remplacé par le bon mot de passe du serveur IMAP.

[general]
accounts = Travail

[Account Travail]
localrepository = TravailLocal
remoterepository = TravailRemote
postsynchook = notmuch new

[Repository TravailRemote]
type = IMAP
remotehost = serveur-imap-du-travail
remoteuser = demers@...
remotepass = PASSWORD
ssl = yes
readonly = False
realdelete = yes
maxconnections = 1
cert_fingerprint = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

folderfilter = lambda folder: folder not in ['Calendar']


[Repository TravailLocal]
type = Maildir
localfolders = ~/.imap
restoreatime = no

Astroid

Astroid est une interface graphique qui présente les courriels qui ont été digérés par notmuch. Astroid n’est pas un gestionnaire de courriel à proprement dit comme Mutt. C’est plutôt un agent de recherche et de présentation des courriels. Astroid utilise notmuch pour effectuer ses recherches. Astroid peut servir de remplacement occasionnel de Mutt pour lire les courriels. Astroid offre aussi le moyen d’envoyer des courriels à l’aide de l’outil en ligne de commande msmtp. Astroid offre aussi le moyen d’effectuer des recherches rapides en utilisant notmuch.

Voici une partie de la configuration Astroid:

{
    "astroid": {
        "config": {
            "version": "11"
        },
        "notmuch_config": "\/home\/demers\/.notmuch-config",
        "debug": {
            "dryrun_sending": "false"
        },
        "hints": {
            "level": "0"
        },
        "log": {
            "syslog": "false",
            "stdout": "true",
            "level": "debug"
        }
    },
    "accounts": {
        "fnd": {
            "name": "F.-Nicola Demers",
            "email": "demers@...",
            "gpgkey": "0xXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
            "always_gpg_sign": "true",
            "sendmail": "msmtp -i -t",
            "default": "true",
            "save_sent": "false",
            "save_sent_to": "\/home\/demers\/.imap\/Sent\/cur\/",
            "additional_sent_tags": "",
            "save_drafts_to": "\/home\/demers\/.imap\/Drafts\/",
            "signature_separate": "true",
            "signature_file": "\/home\/demers\/.mutt/signature.txt",
            "signature_file_markdown": "",
            "signature_default_on": "true",
            "signature_attach": "false",
            "select_query": ""
        }
    },
    "startup": {
        "queries": {
            "inbox": "tag:inbox"
        }
    },
    "terminal": {
        "height": "10",
        "font_description": "default"
    },
    "thread_index": {
        "page_jump_rows": "6",
        "sort_order": "newest",
        "cell": {
            "font_description": "default",
            "line_spacing": "2",
            "date_length": "10",
            "message_count_length": "4",
            "authors_length": "20",
            "subject_color": "#807d74",
            "subject_color_selected": "#000000",
            "background_color_selected": "",
            "background_color_marked": "#fff584",
            "background_color_marked_selected": "#bcb559",
            "tags_length": "80",
            "tags_upper_color": "#e5e5e5",
            "tags_lower_color": "#333333",
            "tags_alpha": "0.5",
            "hidden_tags": "attachment,flagged,unread"
        }
    },
    "general": {
        "time": {
            "clock_format": "local",
            "same_year": "%b %-e",
            "diff_year": "%x"
        },
        "tagbar_move": "tag"
    },
    "editor": {
        "cmd": "gvim -geom 10x10 --servername %2 --socketid %3 -f -c 'set ft=mail' '+set fileencoding=utf-8' '+set ff=unix' '+set enc=utf-8' '+set fo+=w' '+set tw=0' '+set noautoindent' '+set norelativenumber' '+set list!' '+set nopaste' %1",
        "external_editor": "false",
        "charset": "utf-8",
        "save_draft_on_force_quit": "true",
        "attachment_words": "attach",
        "attachment_directory": "~",
        "markdown_processor": "cmark",
        "markdown_on": "false"
    },
    "mail": {
        "reply": {
            "quote_processor": "w3m -dump -T text\/html",
            "quote_line": "Extraits de %1 en date de %2:",
            "mailinglist_reply_to_sender": "true"
        },
        "forward": {
            "quote_line": "Forwarding %1's message of %2:",
            "disposition": "inline"
        },
        "sent_tags": "sent",
        "message_id_fqdn": "",
        "message_id_user": "",
        "user_agent": "default",
        "send_delay": "2",
        "close_on_success": "false",
        "format_flowed": "false"
    },
    "poll": {
        "interval": "0",
        "always_full_refresh": "false"
    },
    "attachment": {
        "external_open_cmd": "/home/demers/bin/qutebrowser.bash"
    },
    "thread_view": {
        "open_html_part_external": "true",
        "preferred_type": "plain",
        "preferred_html_only": "false",
        "allow_remote_when_encrypted": "false",
        "open_external_link": "/home/demers/bin/qutebrowser.bash",
        "default_save_directory": "~",
        "indent_messages": "false",
        "gravatar": {
            "enable": "true"
        },
        "mark_unread_delay": "0.5",
        "expand_flagged": "true"
    },
    "crypto": {
        "gpg": {
            "path": "gpg2",
            "always_trust": "true",
            "enabled": "true"
        }
    },
    "saved_searches": {
        "show_on_startup": "false",
        "save_history": "true",
        "history_lines_to_show": "15",
        "history_lines": "1000"
    }
}

Et enfin, voici la configuration de .msmtprc pour qu’Astroid puisse envoyer des courriels:

defaults

port 587

tls on
tls_starttls on

tls_trust_file /etc/ssl/certs/ca-certificates.crt

account travail

host serveur-imap-travail

from demers@...

auth on
user demers@...

domain serveur-entreprise-travail

passwordeval pass local/mutt; echo

account default : travail
syslog LOG_MAIL
logfile ~/.msmtp.log

Vous constatez que ces configurations ont la particularité d’utiliser beaucoup de commandes et d’applications interdépendantes pour lire, chercher et envoyer des courriels. Certaines personnes peuvent trouver cela décourageant. Il faut penser que cette approche fournit un environnement très efficace et très sécuritaire. La difficulté est la configuration. Par la suite, ça fonctionne bien et c’est stable. Il ne reste qu’à apprendre les raccourcis claviers disponibles.