Alternative email handling with mmh and mblaze

Sun, Jun 23, 2019 | tags: email unix mmh mblaze

Email and its underlying technologies have fascinated me for a while. In my opinion, email is one of the few federated, standardized, reliable and relatively easy communication methods on the internet that work well in practice.

I have been using mutt as a MUA for the past few years. In my mutt email setup, mail is first handled by either the Google servers (for my gmail account) or by the Kolabnow (for my sillymon.ch mail domain) ones. I use isync to synchronize my maildir folders on my local machine and then use mutt to read and reply to incoming mail.

While a lot of people consider mutt to be rather minimal, I have been intrigued by more Unix-like approaches to email handling. The first information source that kicked off this interest was mmh. Mmh is a cleaned-up version of the nmh mail handler written as part of a master thesis (which makes for an interesting reading by itself!).

Like nmh, mmh is a collection of command line tools which are supposed to be used together to form an exhaustive tool box for email handling. In that sense, mmh conforms closer to the Unix software design philosophy of writing simple tools that do one thing well and that work together in harmony.

It was around September last year that I decided to try out mmh for my daily email handling. What led to that decision was that I wanted to finally try out a more Unix-y way of dealing with email. Two drawbacks of my usage of mutt also contributed. The first one is the start-up speed of mutt when reading the local mail box for the first time. With around 170K emails in my inbox, the first start of mutt takes up to 10 seconds to read all the files in my mail dir into the page cache. This does not feel snappy at all. Mutt also seems to not apply flag changes on email immediately, i.e. if you read a newly arrived email, its Unread-flag on the file system will only be cleared once you close mutt. This implementation decision can lead to some frustrating loss of state if you have read the first 50 new emails in your inbox but mutt crashes on showing you the 51st …

My mmh setup (used from September 2018 until about March 2019)

Mmh doesn’t use the maildir format but the nh-mail format. So in order to get email from my mail accounts I used the following .fetchmailrc.

poll imap.gmail.com protocol imap auth password:
     username "yourgmailaddress@gmail.com" password "yourpasswordhere" mda "/usr/bin/rcvstore";
     ssl, sslproto tls1, sslcertck, keep

# useful for debugging
#set syslog set logfile "fetchmail.log"

In order for /usr/bin/rcvstore to know where to put your mail, you have to configure it correctly. The following is a relevant excerpt of my mmh profile.

Path: /home/silvan/.mmh/mail
Inbox: gmail
Editor: /usr/local/bin/vis
Aliasfile: /home/silvan/.mmh/aliases
Pager: mmhpager
Alternate-Mailboxes: me@sillymon.ch
mhshow-show-image: sxiv %f
mhshow-show-application/pdf: zathura %f
mhshow-show-text/html: /usr/lib/plan9/bin/htmlfmt -a -c utf-8

Note that this profile also specifies the editor to use as well as how to handle mail attachments.

To save on typing, I would recommend to add some shell aliases. Below you can find a few that I found to be useful.

# mmh aliases
alias n='next'
alias p='prev'
alias sc='scan -form /usr/etc/scan.meillo'
alias un='unseen'
alias uc='sc +cyon u'
alias ug='sc +gmail u'
alias fu='show u:1'
alias s='show'
alias replac='repl -group -nocc me -form /home/silvan/.mmh/replgroupcompsc'
alias replag='repl -group -nocc me -form /home/silvan/.mmh/replgroupcompsg'
alias replc='repl -form /home/silvan/.mmh/replcompsc'
alias replg='repl -form /home/silvan/.mmh/replcompsg'

There are a few aliases that differ only by the last character (e. g. replac vs. replag). These aliases are mail account specific. The ones ending on ‘g’ are used for mail arriving at my gmail account while the ones ending on ‘c’ are used for my sillymon.ch address.

I have used this mmh setup daily for about six months. The biggest advantage is that all of the tools used in the mmh email handling suite are small and there is no startup time at all since they operate only on a subset of your emails at a time (typically). The one exception to this was the remove mail command (rmm). It seems like this tool reads your mail folder by default which adds about 150ms on each invocation. This feels very sluggish and means that it was a pain to delete emails one-by-one. Instead I tried to make lists of all the mails I wanted to delete and then call rmm on that list. The frustration stemming from this drove me to try how mblaze dealt with deleting mail.

My mblaze setup (since about March 2019)

While searching for solutions for the perceived shortcomings of mmh, I found mblaze. Mblaze is a modernized Unix-y mail handler inspired by nmh. One of the biggest differences between the two is that mblaze operates on regular maildir mailboxes. That meant that I did not have to change my isync-based email setup that I used with mutt to try out mblaze.

My mblaze settings look as follows.

Local-Mailbox: "Silvan Jegen" <mygmailemailaddress@gmail.com>
Alternate-Mailboxes: "Silvan Jegen" <localpartofmyaddress@sillymon.ch>
FQDN: homearch.localdomain
Outbox: /home/silvan/.config/mblaze/outbox
Sendmail: /usr/bin/msmtp

Note that I am using msmtp directly to send my mail. As with mmh, I have a set of shell aliases that simplify my daily email workflow. My email alias file looks as follows.

# mblaze aliases
alias new='(mlist -s ~/.mutt/Mail/Inbox; mlist -s ~/.mutt/Mail/cyon/inbox)'
alias all='(mlist -s ~/.mutt/Mail/Inbox; mlist -s ~/.mutt/Mail/cyon/inbox) | mthread | mless'
alias mall='(mlist -s ~/.mutt/Mail/Inbox; mlist -s ~/.mutt/Mail/cyon/inbox) | mthread | mseq -S ; mseq -C 1'
alias mread='mseq | mflag -S'
alias s='mshow | less'
alias n='mshow .+1'
alias p='mshow .-1'
alias sc='mscan'
alias mrm='rm $(mseq .)'
alias mrepc='MBLAZE=~/.config/mblaze-cyon/ mrep $(mseq .)'
alias mcomc='MBLAZE=~/.config/mblaze-cyon/ mcom'
alias mgetallg='mlist ~/.mutt/Mail/Inbox | mthread  | mseq -S'
alias mgetallc='mlist ~/.mutt/Mail/cyon/inbox/ | mthread  | mseq -S'

The alias used to delete mail is set to mrm. You can see that it simply calls rm on the path of the current message/mail. This of course does not read the directory content, so its speed is not dependent on the mail count.

Thoughts

Since the end of March I have been using my mblaze setup for all my email needs. I would point out its non-existing start-up delay and fast operation in general as its biggest strength. Mail search over all your mail is not as fast as I would like it, however. Of course this could be improved quite easily by using something like notmuch.

Another big advantage of command line oriented email handling programs like mmh or mblaze is that they can be scripted to your heart’s content. That means if there is some processing that you want to do periodically on a subset of your mail, it should be straight-forward to script it. Until now I haven’t had the need for such processing though.

Mblaze’s mless tool already replicates a lot of mutt’s email rendering in a simple but more efficient way. What I am missing is a key shortcut to delete the current mail message. Other than that, there is only the email alias functionality of mmh that I am missing in mblaze. For now I am making due with running sed on my email’s “To:”, “CC:” and “BCC:”-headers to replace shorthands of email addresses. It would be nice if there would be a more elegant way to integrate this functionality into the mblaze suite.

Don’t hesitate to send comments and/or questions to my public-inbox (view).