1---
2title: "A perfect email setup (for me)"
3author: ["Amolith"]
4cover: ./cover.png
5lastmod: 2023-01-27T13:00:36-05:00
6tags: ["Email", "Workflow"]
7categories: ["Technology"]
8draft: true
9---
10
11I've never been satisfied with any of the email clients most people use. I've
12tried [Thunderbird,](https://www.thunderbird.net/en-GB/)
13[Evolution,](https://wiki.gnome.org/Apps/Evolution)
14[Mailspring,](https://getmailspring.com/)
15[Mail.app,](https://support.apple.com/mail) [Roundcube,](https://roundcube.net/)
16[SOGo,](https://sogo.nu/) [Geary,](https://wiki.gnome.org/Apps/Geary) and _many_
17more. _None_ of them handle multiple accounts particularly well because all of
18the emails associated with that account are bound within it. Sure, you can make
19a new folder somewhere called `TODO` and move all of your actionable emails to
20that folder but, when you go to move actionable emails from _another_ account
21into that folder, you'll likely find that the client simply doesn't let you. If
22it does, when you reply, it will likely be sent from the wrong account. This is
23a limitation of the IMAP protocol; everything is _managed_ locally but changes
24are pushed to the remote server and mixing things the way I want leads to broken
25setups.
26
27Before I go any further, these are a few characteristics of my ideal email tool.
28
29- Support for multiple accounts (obviously)
30- _Native desktop application_ (**not**
31 [Electron](https://github.com/electron/electron))
32- Has stellar keyboard shortcuts
33- Doesn't require internet connectivity (other than downloading and sending of
34 course)
35- Organisation can be done with tags
36
37## Why tags? {#why-tags}
38
39Because they're better. Hierarchies are useful for prose and code but not for
40files, emails, notes, or anything where an item may fit within multiple
41categories. Imagine you get an email from your Computer Science professor that
42includes test dates, homework, and information about another assignment. In that
43same email, he asks every student to reply with something they learned from the
44previous class as a form of attendance. In a hierarchy, the best place for this
45might just be a `TODO` folder _even though_ it would also fit under `School`,
46`CS`, `Dates`, `To read`, and `Homework`. Maybe you have a few minutes and want
47to clear out some emails that don't require any interaction. In a tag-based
48workflow, this would be a good time to open `To read`, get that email out of the
49way, and remove the `To read` tag. It would still show up under the other tags
50so you can find it later and take the time to fully answer the professor's
51question, add those dates to your calendar, and add the homework assignments to
52your `TODO` list. Hierarchies can be quite cumbersome to work with, especially
53when one folder ends up getting all the data. Tags ensure that you only see what
54you want when you want it. Tags are more efficient and they will remain my
55organisation system of choice.
56
57## The tools {#the-tools}
58
59In short, the tools we will be using are...
60
61- [`mbsync`](https://isync.sourceforge.io/mbsync.html) to download our emails
62- [`notmuch`,](https://notmuchmail.org/) the primary way emails will be
63 organised
64- [`afew`](https://afew.readthedocs.io/en/latest/) to apply initial `notmuch`
65 tags based on subject, sender, recipient, etc.
66- [NeoMutt](https://neomutt.org/) to interact with those emails, reply,
67 compose, add/remove tags, etc.
68- [`msmtp`](https://marlam.de/msmtp/) for relaying our replies and
69 compositions to our mail provider
70
71Yes, it's a lot. Yes, it's time-consuming to set up. Yes, it's worth it (in my
72opinion).
73
74## `mbsync` {#mbsync}
75
76As I said above, IMAP is limiting; we need to use some other method of
77downloading our emails. There's an awesome piece of software called
78[mbsync](https://isync.sourceforge.io/mbsync.html) which is built for exactly
79this purpose. Its configuration can be rather daunting if you have as many
80accounts as I do (19) but it's not _terrible_.
81
82The following sections are named **Near**, **Far**, and **Sync**. Near and Far
83are terms mbsync uses to profile _how_ your emails are stored, _where_ they're
84stored, and how to interact with them. In this guide, Far will our mail
85provider's IMAP server and Near will be our local Maildir.
86
87### Far {#far}
88
89```text
90IMAPAccount amo_ema
91Host imap.nixnet.email
92CertificateFile /etc/ssl/certs/ca-certificates.crt
93SSLType STARTTLS
94User amolith@nixnet.email
95PassCmd "secret-tool lookup Title amolith@nixnet.email"
96
97IMAPStore amo_ema-remote
98Account amo_ema
99```
100
101### Near {#near}
102
103```text
104MaildirStore amo_ema-local
105SubFolders Verbatim
106Path ~/new-mail/amo_ema/
107Inbox ~/new-mail/amo_ema/INBOX/
108```
109
110In the first block, `localrepository` and `remoterepository` tell OfflineIMAP
111where to look for your emails. `use_exa-local` is an arbitrary naming scheme I
112use to differentiate between the various local and remote accounts. It can
113easily be swapped with something else.
114
115### Sync {#sync}
116
117```text
118Channel amo_ema
119Far :amo_ema-remote:
120Near :amo_ema-local:
121SyncState *
122Patterns *
123Create Both
124```
125
126The repository sections describe how the emails are stored or retrieved. In the
127`local` block, you'll notice that the type is `Maildir`. In this format, each
128email is given a unique filename and stored in a hierarchy of folders within
129your account. This is often how your emails are stored on your provider's mail
130server.
131
132`pythonfile` is used here to authenticate with the remote server. This can be
133complicated and depends _entirely_ on how you manage your passwords. I use
134[KeePassXC](https://keepassxc.org/) and love it. When I set OfflineIMAP up,
135however, it didn't have `libsecret` compatibility. This would have made setup
136significantly easier but, as it already just works™, I don't really see a reason
137to change it.
138
139This new feature allows `libresecret`-based applications to query KeePassXC for
140your passwords or store them there on your behalf. CLI/TUI applications that
141need a secure mechanism for background authentication can use `secret-tool
142lookup Title "TITLE_OF_PASSWORD"` as the password command. See [the pull
143request](https://github.com/keepassxreboot/keepassxc/pull/2726) for more
144details. Because this wasn't a feature when I first set it up, I put my
145passwords in plaintext files and encrypted them with the GPG key stored on my
146YubiKey. As long as my key is plugged in, OfflineIMAP can authenticate and
147download all my emails just fine. The process for using a GPG key _not_ stored
148on a hardware token is pretty much the same and I'll talk about that process
149instead.
150
151These are the contents of my `~/.offlineimap.py`.
152
153```python
154 #! /usr/bin/env python2
155 from subprocess import check_output
156 def get_pass(account):
157 return check_output(["gpg", "-dq", f" ~/.mail_pass/{account}.gpg"]).strip("\n")
158```
159
160This runs `gpg -dq ~/.mail_pass/use_exa.gpg` then strips the newline character
161before returning it to OfflineIMAP. `-d` tells GPG that you're passing it a file
162you want decrypted and `-q` tells it not to give any output other than the
163file's contents. For a setup that works with this Python script, put your
164passwords in plaintext files with the account name as the file name (e.g.
165`use_exa`). You'll then encrypt it with `gpg -er <YOUR_KEY_ID> use_exa`. Running
166`gpg -dq use_exa.gpg` should display your password. Repeat for every account and
167store the resulting files in `~/.mail_pass/`.
168
169The other option, `sync_deletes`, is whether or not to delete remote emails that
170have been deleted locally. I enabled that because I want to have easy control
171over how much remote storage is used.
172
173Here's the next block again so you don't have to scroll up:
174
175```text
176[Repository use_exa-remote]
177type = IMAP
178remotehost = imap.example.com
179starttls = yes
180ssl = no
181remoteport = 143
182remoteuser = user@example.com
183remotepasseval = get_pass("use_exa")
184auth_mechanisms = GSSAPI, XOAUTH2, CRAM-MD5, PLAIN, LOGIN
185maxconnections = 1
186createfolders = True
187sync_deletes = yes
188```
189
190This one's pretty self-explanatory. `type`, `remotehost`, `starttls`, `ssl`, and
191`remoteport` should all be somewhere in your provider's documentation.
192`remoteuser` is your email address and `remotepasseval` is the function that
193will return your password and allow OfflineIMAP to authenticate. You'll want
194enter the name of your password file without the `.gpg` extension; the script
195takes care of adding that. Leave `auth_mechanisms` alone and the same for
196`maxconnections` unless you know your provider won't rate limit you or something
197for opening multiple connections. `sync_deletes` is the same as in the previous
198block.
199
200Copy those three blocks for as many accounts as you want emails downloaded from.
201I have 510 lines just for `Account` and `Repository` blocks due to the number of
202address I'm keeping track of.
203
204## `notmuch` {#notmuch}
205
206[`notmuch`](https://notmuchmail.org/) is _a fast, global-search, and tag-based
207email system_. This what does all of our organisation as well as what provides
208the "virtual" mailboxes NeoMutt will display later on. Configuration is
209incredibly simple. This file goes in `~/.notmuch-config`.
210
211```text
212 [database]
213 path=/home/user/mail/
214
215 [user]
216 name=Amolith
217 primary_email=user@example.com
218
219 [new]
220 tags=unread;new;
221 ignore=Trash;
222
223 [search]
224 exclude_tags=deleted;spam;
225
226 [maildir]
227 synchronize_flags=true
228```
229
230First section is the path to where all of your archives are, the `[user]`
231section is where you list all of your accounts, `[new]` adds `tags` to mail
232notmuch hasn't indexed yet and ignores indexing the `Trash` folder, and
233`[search]` ignores mail tagged with `deleted` or `spam`. The final section tells
234`notmuch` to add maildir flags which correspond with `notmuch` tags. These flags
235will be synced to the remote server the next time OfflineIMAP runs and things
236will be somewhat organised in your webmail interface.
237
238After creating the configuration file, run `notmuch new` and wait for all of
239your mail to be indexed. This could take a short amount of time or it could take
240minutes up to an hour, depending on how many emails you have. After it's
241finished, you'll be able to run queries and see matching emails:
242
243```text
244 $ notmuch search from:user@example.com
245 thread:0000000000002e9d December 28 [1/1] Example User; Random subject that means nothing
246```
247
248This is not terribly useful in and of itself because you can't read it or reply
249to it or anything. That's where the Mail User Agent (MUA) comes in.
250
251## `afew` {#afew}
252
253[`afew`](https://afew.readthedocs.io/en/latest/) is _an initial tagging script
254for notmuch_. After calling `notmuch new`, `afew` will add tags based on headers
255such as `From:`, `To:`, `Subject:`, etc. as well as handle killed threads and
256spam. The official [quickstart
257guide](https://afew.readthedocs.io/en/latest/quickstart.html) is probably the
258best resource on getting started but I'll include a few tips here as well.
259
260## NeoMutt {#neomutt}
261
262## `msmtp` {#msmtp}
263
264`msmtp` is what's known as a _Mail Transfer Agent_ (MTA). You throw it an email
265and it will relay that to your mail provider's SMTP server so it can have the
266proper headers attached for authentication, it can be sent from the proper
267domain, etc. All the necessary security measures can be applied that prevent
268your email from going directly to spam or from being rejected outright.
269
270`msmtp`'s configuration is also fairly simple if a bit long, just like
271OfflineIMAP's.
272
273```text
274 # Set default values for all following accounts.
275 defaults
276
277 # Use the mail submission port 587 instead of the SMTP port 25.
278 port 587
279
280 # Always use TLS.
281 tls on
282```
283
284This section just sets the defaults. It uses port 587 (STARTTLS) for all SMTP
285servers unless otherwise specified and enables TLS.
286
287```text
288 account user@example.com
289 host smtp.example.com
290 from user@example.com
291 auth on
292 user user@example.com
293 passwordeval secret-tool lookup Title "user@example.com"
294```
295
296This section is where things get tedious. When passing an email to `msmtp`, it
297looks at the `From:` header and searches for a block with a matching `from`
298line. If it finds one, it will use those configuration options to relay the
299email. `host` is simply the SMTP server of your mail provider, sometimes this is
300`mail.example.com`, `smtp.example.com`, etc. I've already explained `from`,
301`auth` simply says that a username and password will have to be provided, `user`
302is that username, and `passwordeval` is a method to obtain the password.
303
304When I got to configuring `msmtp`, [KeePassXC](https://keepassxc.org/) had just
305released their `libsecret` integration and I wanted to try it. `secret-tool` is
306a command line tool used to store and retrieve passwords from whatever keyring
307you're using. I think KDE has `kwallet` and GNOME has `gnome-keyring` if you
308already have those set up and want to use them; the process should be quite
309similar regardless.
310
311As mentioned above `secret-tool` stores and retrieves passwords. For retrieval,
312it expects the command to look like this.
313
314```text
315secret-tool lookup {attribute} {value} ...
316```
317
318I don't know what `kwallet` and `gnome-keyring`'s attributes are but this can be
319used with KeePassXC by specifying the `Title` attribute. If the password to your
320email account is stored in KeePassXC with the address as the entry title, you
321can retrieve it by simply running...
322
323```text
324secret-tool lookup Title "user@example.com"
325```
326
327If you have a different naming system, you'll have to experiment and try
328different things; I don't know what KeePassXC's other attributes are so I can't
329give other examples.
330
331```text
332passwordeval gpg -dq ~/.mail_pass/use_exa.gpg
333```
334
335Now that the whole block is assembled, copy/paste/edit for as many accounts as
336you want to send email from.
337
338## Summary {#summary}
339
340## <span class="org-todo todo TODO">TODO</span> Pong fluffy when finished {#pong-fluffy-when-finished}