💾 Archived View for wilw.capsule.town › notes › aerc.gmi captured on 2024-12-17 at 09:47:11. Gemini links have been rewritten to link to archived content
-=-=-=-=-=-=-
This note documents my current setup for email.
It includes:
- aerc [1] as an email client
- vdirsyncer [2] for syncing contacts
- khard [3] for reading and searching locally-synced contacts
- mbsync [4] for syncing email to a local Maildir
- notmuch [5] for organising and searching locally-synced email
To securely store credentials for syncing, I use `pass` [6]. I recommend installing this for your system and setting it up with a GPG key.
One issue I had whilst using `pass` was that it would frequently timeout, and the GPG dialog would fail to work or would interfere with the running mail client. As such, I extended the TTLs of the agent by adding these lines to my `~/.gnupg/gpg-agent.conf`:
default-cache-ttl 34560000 max-cache-ttl 34560000
Once set-up, add the needed credentials for your various mail accounts to `pass`. For some services (e.g. Fastmail and Google) an app-specific password should be generated for this. E.g.:
pass insert Email/fastmail
I use `vdirsyncer` to sync contacts to a local directory. This allows `khard` to read and search contacts locally and surface them to `aerc`.
To install both of these, use Homebrew on a Mac: `brew install vdirsyncer khard`.
Once installed, create a new configuration file for vdirsyncer at `~/.config/vdirsyncer/config`:
[general] status_path = "~/.config/vdirsyncer/status/" # Personal Contacts [pair personal_addressbook] a = "personal_addressbook_local" b = "personal_addressbook_remote" collections = ["from a", "from b"] metadata = ["displayname"] [storage personal_addressbook_local] type = "filesystem" path = "~/.config/khard/personal/" fileext = ".vcf" [storage personal_addressbook_remote] type = "carddav" auth = "basic" url = "https://carddav.fastmail.com/dav/addressbooks/user/USERNAME@fastmail.com/Default" username = "USERNAME@fastmail.com" password.fetch = ["command", "pass", "Email/fastmail"]
This syncs my Fastmail (i.e. personal, non-work) contacts to `~/.config/khard/personal/`. The final three blocks of the config file (the `pair` and two `storage` blocks) can be repeated for each account you wish to sync contacts for.
I use it with both Fastmail and Google, and it works well. For Google contacts, the `url` I use is: `https://www.googleapis.com/carddav/v1/principals/USERNAME@DOMAIN.COM/lists`.
For `khard`, create a new config file at `~/.config/khard/khard.conf` with contents along the lines of the example on the website [7]. Specifically, for the `[addressbooks]` section, I use the `~/.config` dir primarily out of laziness, as this auto-syncs with my dotfiles.:
[addressbooks] [[personal]] path = ~/.config/khard/personal/Default [[work]] path = ~/.config/khard/work/default ...
In the latter example, the `default` is lowercase as this is how Google names its default address books.
To test this is all working, run a sync and then try searching for a contact:
vdirsyncer sync khard list john
If you have a contact named John, you should see them listed.
Although `aerc` can directly connect to IMAP servers, I prefer to have mail synced locally. This allows me to manage it using local tools (such as `notmuch`) but it also enables me to back things up more easily.
I use `mbsync` for syncing IMAP accounts to a local Maildir directory. It is part of a package called `isync` and can be installed with Homebrew: `brew install isync`.
To set it up, create a file at `~/.mbsyncrc`. I find the `mbscync` config file fiddly and unintuitive, but have set my personal Fastmail IMAP account up as follows. These blocks can be repeated for your other IMAP accounts (just ensure to use unique names for the accounts, stores, and channels).
IMAPAccount personal Host imap.fastmail.com Port 993 User USERNAME@fastmail.com PassCmd "pass Email/fastmail" TLSType IMAPS AuthMechs LOGIN IMAPStore personal-remote Account personal MaildirStore personal-local Path ~/Syncthing/Maildir/personal/ Inbox ~/Syncthing/Maildir/personal/INBOX SubFolders Verbatim Channel personal Far :personal-remote: Near :personal-local: Patterns * Expunge None CopyArrivalDate yes Sync All SyncState * Create Both
You may notice that I reference a Maildir in my Syncthing directory. This is to ensure my mail is backed-up to other machines.
To test this is working, run `mbsync -a` and check the Maildir directory for your account. You should see your mail syncing.
`notmuch` is a tool I use for parsing and searching email in a local Maildir. It's super fast and works well with `aerc`.
To install it, use Homebrew (on a Mac): `brew install notmuch`.
To set it up, run `notmuch`. This will prompt for a few bits of info and setup a database at the root of your Maildir and a configuration file at `~/.notmuch-config`.
The defaults for the config are pretty good, but for reference I add mine below:
[database] # Path to your Maildir path=/Users/will/Syncthing/Maildir [user] # I don't think this affects much unless you use notmuch for sending mail too primary_email=USER@DOMAIN.COM other_email=email1;email2; [new] # default tags for new messages tags=unread;inbox; ignore= [search] # how to manage searches (i.e. ignore deleted/spam mail) exclude_tags=deleted;spam; [maildir] # sync some notmuch tags with maildir flags (e.g. read/unread) synchronize_flags=true
I also ensure to add the following to `~/Syncthing/.stignore` to prevent Syncthing from syncing the `notmuch` database (which is huge, but can be rebuilt):
.notmuch/xapian
notmuch hooks [8] can be set up to run commands alongside `notmuch`. For example, to add/remove tags before or after mail is processed.
My approach is simple, and I just have a single `post-new` hook in `~/Syncthing/Maildir/.notmuch/hooks/post-new` to make my mail management a little easier:
#!/bin/bash # Reference Maildir folders for tagging notmuch tag +personal "folder:/personal/" notmuch tag +account2 "folder:/account2/" # Handle sent and spam mail by IMAP folders # e.g. if Gmail marks it as spam, tag it as spam notmuch tag +sent "folder:/Sent/" and not tag:sent notmuch tag +spam "folder:/Spam/" and not tag:spam # Handle customer specific tags notmuch tag +customer1 from:customer1.com notmuch tag +customer2 from:customer2.com and tag:personal # Remove the new tag from all new emails notmuch tag -new tag:new
(Note: after creating this file for the first time, be sure to ensure it's executable: `chmod +x ~/Syncthing/Maildir/.notmuch/hooks/post-new`)
Because our config file auto-applies the `unread` tag, we don't need to handle it here, but we could if we wanted to.
If you now run `notmuch new`, the Maildir will be processed according to the config and any hooks you've setup.
You can now try running a search to show how fast it runs:
notmuch search from:domain1.com notmuch search tag:personal
I now talk about installing and setting-up `aerc`, which will bring all of this together into one place.
Although it's installable from Homebrew, the distributed binary does not include `notmuch` support. As such, I compile `aerc` from source using the headers installed as part of the `notmuch` installation from earlier.
First, make sure to have `go` installed (according to the website [9]).
Clone the `aerc` repo and change into it:
git clone https://git.sr.ht/~rjarry/aerc cd aerc
Set some flags so the build process knows where to find the `notmuch` headers and so the linker can find the library. In my case (and versions), this was done using:
export CPATH=/opt/homebrew/Cellar/notmuch/0.38.3/include export LIBRARY_PATH=/opt/homebrew/Cellar/notmuch/0.38.3/lib
Now compile `aerc` with the `notmuch` tag:
gmake GOFLAGS=-tags=notmuch
To help automate some of the mail fetching and tagging tasks, I added a script (largely taken from the example on the aerc wiki [10]). This script will be invoked whenever `aerc` wants to fetch new mail (as we'll set up later):
#!/bin/sh MBSYNC=$(pgrep mbsync) NOTMUCH=$(pgrep notmuch) if [ -n "$MBSYNC" -o -n "$NOTMUCH" ]; then echo "Already running one instance of mbsync or notmuch. Exiting..." exit 0 fi # Actually delete the emails tagged as deleted notmuch search --format=text0 --output=files tag:deleted | xargs -0 --no-run-if-empty rm -v mbsync -a notmuch new
I save this in `~/.config/aerc/mail-sync`. As above, ensure this script is executable: `chmod +x ~/.config/aerc/mail-sync`.
The `aerc` accounts setup is highly flexible. The man page (like this Arch Wiki one) [11] is a good reference.
Below is a sample of mine (in `~/.config/aerc/accounts.conf`), which demonstrates `notmuch` and `khard` integration:
[Combined] source = notmuch://~/Syncthing/Maildir query-map = ~/.config/aerc/map.conf default = INBOX from = Will Webberley <USERNAME@DOMAIN.COM> check-mail-cmd = ~/.config/aerc/mail-sync check-mail = 2m check-mail-timeout = 30s [Personal] source = notmuch://~/Syncthing/Maildir outgoing = smtps://USERNAME%40fastmail.com@smtp.fastmail.com:465 maildir-store = ~/Syncthing/Maildir maildir-account-path = personal outgoing-cred-cmd = pass Email/fastmail check-mail-cmd = mbsync personal && notmuch new check-mail = 2m default = INBOX from = Will Webberley <USERNAME@DOMAIN.COM> cache-headers = true copy-to = Sent address-book-cmd = khard email -a personal --parsable --remove-first-line %s [Work1] source = notmuch://~/Syncthing/Maildir ... etc.
This setup includes a Combined account which is optional but I like it for having a single view across all my accounts. You can also see this account invoking the `mail-sync` script we created earlier.
The `khard` integration offers auto-complete suggestions as you type a name or email address into the mail composer.
The Combined account also makes use of a query map which maps "folders" onto `notmuch` queries. My `~/.config/aerc/map.conf` looks like this:
Inbox=tag:inbox Todo=tag:todo and not tag:archived and not tag:deleted All=not tag:archived and not tag:deleted and not tag:spam Sent=tag:sent Spam=tag:spam
I created a `~/.config/aerc/aerc.conf` file to set some general options. This file is also hugely configurable [12]. Mine is very basic by comparison:
[general] default-save-path=~/Downloads log-file=~/.aerc.log [ui] styleset-name=nord fuzzy-complete=true icon-new=✨ icon-attachment=📎 icon-old=🕰️ icon-replied=📝 icon-flagged=🚩 icon-deleted=🗑️ [statusline] [viewer] alternatives=text/plain,text/html header-layout=From,To,Cc,Bcc,Date,Subject [compose] header-layout=From,To,Cc,Subject reply-to-self=false empty-subject-warning=true no-attachment-warning=^[^>]*attach(ed|ment) [multipart-converters] text/html=pandoc -f markdown -t html --standalone [filters] text/html=pandoc -f html -t plain text/plain=colorize text/calendar=calendar message/delivery-status=colorize message/rfc822=colorize .headers=colorize [openers] [hooks] [templates]
An interesting part of this is the filter for HTML. By default `aerc` cannot display HTML emails. This makes emails impossible to view if there is no `text/plain` alternative. In my example I use `pandoc` to convert HTML to plain text, which works OK for me. Other solutions might involve `w3m` or other tools.
The `multipart-converters` section allows for specifying how non-plain parts of the email can be generated. Once an email is written (in `text/plain`) an HTML part can then be generated by running `:multipart text/html` when in review mode.
`aerc` can now be run: `/path/to/aerc -C ~/.config/aerc/aerc.conf -A ~/.config/aerc/accounts.conf`.
Run `:check-mail` in the Combined account to check that's working, try sending mail, check out the autocomplete of contacts via Khard, and try searching for emails.
For day-to-day use, I strongly recommend reading through the `aerc` wiki and man pages, and also experimenting with the setups published by other people.