My mail client of choice is Mutt. It works. It works well. It works well over SSH, and will do just about anything I ask it to, as long as what I ask it to do is to manage my mail. Plus, it’s fast.
I also have been using David Allen’s system known as Getting Things Done, or GTD. Tonight I did a little Mutt configuration to automate some of the GTD-style email reading I’ve been doing.
The principle is to have every incoming mailbox completely empty by the time I’m done reading it. The messages get deleted or sorted into other boxes where they either wait for more information or generate actions for me to do when the time is right.
A little googling revealed that others have done something similar in recent years, but there were two problems. First, messages were tagged by adding an “X-Label:” header, which supposedly required a patch to Mutt’s source code. Possible, but a bit ugly. I vastly prefer custom configuration to custom software, when possible. Second, a number of the pages about using Mutt in a GTD way are no longer available.
But this one is available. Unfortunately, it also relies upon the “Add an X-Label header” patch to Mutt’s source code. But I had an inkling it could be done another way, without the patch. A few hours later, after a little Reading of The Fine Manual and some experimentation, I have the answer.
The goal is to provide simple keystrokes that will add an X-Label header or change an existing one right from the index listing or the pager. Then, folder hooks can change the index listing format when needed to include the X-Label header — or at least a few characters of it. That way, I can process messages when they come in, slap a label on them, and then save them into an appropriate folders for later review at the right time. When I browse those folders later, I’ll see my labels, and know what to do even before I read the messages. In addition, I can set up automated summaries of my GTD folders, including how many messages are there, and what their Labels say. The summaries might appear on my desktop, or wherever else I might want them.
I ended up doing most of what’s mentioned on the page linked above. The chief difference is that I haven’t patched Mutt. So instead of using the “edit-label” command (which doesn’t exist for me), I used the following somewhat long binding (inspired by this thread) in my muttrc:
macro index,pager Cl "<enter-command>set my_editor=$editor<enter>\
<enter-command>set editor='~/bin/mutt-setlabel.sh'<enter>\
<edit><enter-command>set editor=\$my_editor<enter>"
The magic keystroke is Cl, available in the index or the pager. Everything else is the macro this keystroke performs.
First, we save the value of the current Mutt editor variable to a custom variable, cryptically named my_editor.
Then, we set the Mutt editor to a shell script, which I’ll include below.
After that, we issue the Mutt
Finally, we restore the original value of the Mutt editor variable. The backslash is needed here because we want this variable to be expanded when the macro executes, rather than when it is defined.
The shell script is as follows:
#!/bin/bash
read -e -p"Enter an X-Label: " value
file=$1
formail -I "X-Label: $value" <$file >$file.tmp
sleep 1
mv $file.tmp $file
Ignore the first line. It’s how shell scripts work.
First, on line 2, we have Bash ask for a new label value. Since Mutt runs in a terminal, this is no problem at all.
The third line takes the filename parameter provided by Mutt and puts it into a nice, descriptive variable, just because.
The fourth line uses a command-line utility to do the heavy lifting, using the value we just obtained in line 2. Shell redirection is used for input and output.
The fifth line pauses for a second, because supposedly Mutt will assume the file is unchanged if the final timestamp is unchanged.
Finally, we move the modified message to the original filename for Mutt to pick up.
And that’s it. The rest is similar to the first link above. But now, it’s late. My next action is to get some rest.