💾 Archived View for lyk.so › systems › e-mail captured on 2023-09-08 at 15:58:38. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2023-01-29)
-=-=-=-=-=-=-
Updated 2021-09-13
I use mblaze, isync/mbsync, msmtp, and some custom scripts for handling e-mail.
mblaze is a suite of utilities for managing maildir mailboxes, in the Unix spirit of simple, combinable tools.
mbsync synchronizes IMAP4 and maildir mailboxes.
msmtp is a simplified sendmail alternative.
I also secure the passwords for my e-mail using two hardware devices: a physical password manager (the Mooltipass) and a PGP-capable crypto fob (the Ledger Nano S), which I also use for managing my SSH keys.
In short, I:
1. Set up trezor-agent and created a GPG key for encrypting the passwords file on the hard disk.
2. Used my gpgkv script to create an encrypted TSV file with my e-mail addresses and their passwords at ~/.mbsync-passwords.
3. Created a dedicated "mbsync" user.
4. Set up /etc/sudoers to allow my user to run mbsync and msmtp as mbsync without a password.
5. Ran my load-mbsync-secrets script, which decrypts .mbsync-passwords using my Ledger and loads them into mbsync's kernel keyring. (I have to run this after every reboot as well.)
6. Set up .msmtprc and .mbsyncrc files in /home/mbsync with password commands allowing them to load the passwords from the user's keyring.
7. Set up my mblaze configuration in ~/.mblaze/profile.
8. Made my own user a member of the mbsync group, gave full, recursive permissions to the group on /home/mbsync/mail, and symlinked ~/mail to that directory.
9. Created a cronjob to run my check-mail script every ten minutes.
10. Wrote some extra scripts to make my daily e-mailing life easier.
My e-mail account passwords are auto-generated and stored on a hardware device that can act as a keyboard. This is about as secure as passwords get, as far as I can tell. This is not practical for checking e-mail periodically in the background, however.
The Ledger allows me to generate cryptographic keys deterministically on the device itself based on a randomly-generated string of 24 words. The algorithm is open-source, so as long as I can keep track of my 24 words, all the keys I've ever generated with it should be recoverable. I use trezor-agent to integrate the device with GPG and SSH. This allows me to keep my e-mail passwords encrypted on disk, decrypting them only to put them into a dedicated user account's kernel keyring once per boot.
Setting up trezor-agent for use with the Ledger and GPG is outside the scope of this document, but the process is described in that project's source code repository under the docs folder. Once set up, I used the following AGPL-3 licensed script (with the -p flag set) to create a store of e-mail address keys to password values at ~/.mbsync-passwords:
#!/usr/bin/env bash # <AGPL-3 license omitted here for brevity> # Has no way to handle tabs in keys or values, so don't try it! set -e set -o pipefail # This is the one line that keeps this a bash script. [ ! -e "$HOME/.gpgkvrc" ] || . "$HOME/.gpgkvrc" export GPGBIN="${GPGBIN:-gpg2 -q}" export GPGKV_IDENT="${GPGKV_IDENT:-$USER}" export GPGKV_STORE="${GPGKV_STORE:-$HOME/.gpgkv-store}" case "$1" in add) if [ "$2" = "-p" ]; then valopt="-s" valprompt="Password" shift else valprompt="Value" fi key="$2" val="$3" [ "$key" ] || { echo -n "Key: " && read key; } [ "$val" ] || { echo -n "$valprompt: " && read $valopt val; } if [ ! -e "$GPGKV_STORE" ]; then printf "%s\t%s\n" "$key" "$val" \ | $GPGBIN --armour --encrypt -r "$GPGKV_IDENT" \ | tee "$GPGKV_STORE" >/dev/null else echo "$($GPGBIN --decrypt "$GPGKV_STORE" \ | xargs -0 printf "%s\t%s\n%s" "$key" "$val" \ | $GPGBIN --armour --encrypt -r "$GPGKV_IDENT")" \ > "$GPGKV_STORE" fi echo # in case it used a password prompt ;; get) $GPGBIN --decrypt "$GPGKV_STORE" \ | grep -o "^$2\t" \ | cut -f2 ;; del) $GPGBIN --decrypt "$GPGKV_STORE" \ | grep -v "^$2\t" \ | $GPGBIN --armour --encrypt -r "$GPGKV_IDENT" \ | tee "$GPGKV_STORE" >/dev/null ;; dump) $GPGBIN --decrypt "$GPGKV_STORE" ;; *) echo "Usage: $0 <command> [args]" echo "Commands:" echo " add [-p] [<key> <value>]" echo " get <key>" echo " del <key>" echo " dump" esac
To write to ~/.mbsync-passwords instead of the default ~/.gpgkv-store, set the GPGKV_STORE variable when invoking gpgkv. E.g., "GPGKV_STORE='~/.mbsync-passwords' gpgkv ..."
Creating a dedicated user for the purpose of running msmtp and mbsync and keeping the passwords in their kernel keyring seemed to me like the easiest, safest way to keep the passwords in memory. In order to avoid having to type my user password during the normal execution of this user's duties, I made these entries in my sudoers file:
lykso ALL=(mbsync) NOPASSWD: /bin/keyctl padd user *@* @u lykso ALL=(mbsync) NOPASSWD: /bin/keyctl link @us @s lykso ALL=(mbsync) NOPASSWD: /usr/bin/mbsync -a lykso ALL=(mbsync) NOPASSWD: /usr/bin/msmtp lykso ALL=(mbsync) NOPASSWD: /bin/chmod -R g=u /home/mbsync/mail/*@*
If you copy this, be sure to verify the locations of keyctl, mbsync, msmtp, and chmod. I moved this to another distribution of Linux recently and had some trouble when, e.g., mbsync moved from /bin/mbsync to /usr/bin/mbsync.
To load the passwords, I wrote a simple script that iterates over every entry in ~/.mbsync-passwords and puts it in mbsync's keyring:
#!/usr/bin/env bash # Opens the .mbsync-passwords file with gpgkv and loads each key/value pair into # the kernel's keystore for the mbsync user. set -e set -o pipefail export GPGKV_STORE="$HOME/.mbsync-passwords" # Make sure the session and user session keyrings are linked. # User keys cannot be found otherwise. # Some distributions do this by default, but others don't. sudo -u mbsync keyctl link @us @s gpgkv dump | while read line; do # Doing it this way to keep the credentials out of the process list. IFS=