remember Mutt's mail in Org-mode and jump back to them
As already
anticipated, I've been implementing my own Getting
Things Done work flow. This post documents one of its main
bricks: the integration between Mutt and Org-mode.
As a geek, my main incoming stream of TODO items and information
in general is email. As emails hit my INBOX, I either deal with
them immediately (reply, archive, delete) or I need to store them
elsewhere, possibly adding extra information such as a deadline, a
personal note, the associated next action, the context in which it
is actionable, etc. This need of adding extra information is what
defeats the usage of my mail client (Mutt) as a list manager (in
the GTD sense), and that's where I plugged Org-mode in. My main
goals are:
-
create Org-mode notes from Mutt, referencing
the current email, and possibly inlining some of its metadata (e.g.
subject, sender)
-
quickly retrieve referenced emails from Org-mode
notes; ideally that should happen in my usual email
environment (i.e. Mutt), so that I can process the retrieved mail
as usual (e.g. to inform the sender that I did something about
it)
In fact, both would be straightforward to achieve if I
were using some Emacs-based mail client such as Gnus, but I resist the
Emacs operating system syndrome, and therefore I
insist in using my beloved Mutt.
Let's see how the two parts of the interaction between Mutt and
Org-mode work.
(1) Mutt → Org-mode (there
...)
The interaction from Mutt to Org-mode happens via org-protocol.
Using it external applications can feed content to Org-mode note
templates, which are then interactively edited (via emacsclient), and
finally filed away.
The Mutt glue macro from my ~/.muttrc is as
follow:
macro index \eR "|~/bin/remember-mail\n"
The remember-mail script is
trivial: it parses the fed mail from STDIN (using a couple of
legacy Perl modules) and then invokes org-protocol.
The relevant configuration from my ~/.emacs is
reported below; the comments explain the various parts:
;; standard org <-> remember stuff, RTFM
(org-remember-insinuate)
(setq org-default-notes-file "~/org/gtd.org")
(setq org-remember-templates ;; mail-specific note template, identified by "m"
'(("Mail" ?m "* %?\n\n Source: %u, %c\n %i" nil)))
;; ensure that emacsclient will show just the note to be edited when invoked
;; from Mutt, and that it will shut down emacsclient once finished;
;; fallback to legacy behavior when not invoked via org-protocol.
(add-hook 'org-remember-mode-hook 'delete-other-windows)
(setq my-org-protocol-flag nil)
(defadvice org-remember-finalize (after delete-frame-at-end activate)
"Delete frame at remember finalization"
(progn (if my-org-protocol-flag (delete-frame))
(setq my-org-protocol-flag nil)))
(defadvice org-remember-kill (after delete-frame-at-end activate)
"Delete frame at remember abort"
(progn (if my-org-protocol-flag (delete-frame))
(setq my-org-protocol-flag nil)))
(defadvice org-protocol-remember (before set-org-protocol-flag activate)
(setq my-org-protocol-flag t))
The result is that when you hit ESC-R in Mutt,
emacsclient will be fired up in place presenting a note template
that already contains relevant mail information (date, subject,
from) and lets you add extra information before going away.
Additionally, the email message-id will be hidden in the note as a
mutt: hyperlink with anchor text "mail".
(2) Org-mode → Mutt (... and back
again)
Going back means that clicking on a "mail" hyperlink within an
Org-mode note should bring up a Mutt instance showing the original
message, in its context (e.g. its own mailbox). Achieving that
consists of 2 separate steps:
- looking up a specific message by
Message-ID
- firing up Mutt on the looked up message
For the first part I use maildir-utils
(AKA mu): a
Xapian-based mail indexing tool, which nicely integrates with Mutt;
check out my
previous blog post on the subject for a sample setup. Using mu,
Message-ID lookups are as simple as:
zack@usha:~$ mu find -f p m:E1NbJad-0007x9-B7@ries.debian.org
/home/zack/Maildir/Debian.project/cur/1264883664_0.9472.usha,U=6320,FMD5=2284e927bb93d8a2ec434f5614dc04ba:2,S
Note: I'm relying upon maildir-utils version 0.6
or greater, for all presented scripts.
For the second part I use the mutt-open script which fires upon a Mutt instance
on the maildir containing a specific message, and then "hits" the
appropriate keys to open the message and shutdown the sidebar (if
desired). It is a nicely reusable script, which I've being using
elsewhere too.
The needed glue on the emacs side is just a function to invoke
mutt-open in a brand new terminal, and its declaration
as the handler for mutt: URLs.
(defun open-mail-in-mutt (message)
"Open a mail message in Mutt, using an external terminal.
Message can be specified either by a path pointing inside a
Maildir, or by Message-ID."
(interactive "MPath or Message-ID: ")
(shell-command
(format "gnome-terminal -e \"%s %s\""
(substitute-in-file-name "$HOME/bin/mutt-open") message)))
;; add support for "mutt:ID" links
(org-add-link-type "mutt" 'open-mail-in-mutt)
Voilà!
Download
Summary of scripts and configuration snippets discussed
above:
|
thanks for your post [0]. Since I was reluctant to leave mutt (running in an M-x ansi-term anyway) for a pure elisp based solution (they all seemed overly complex to set up and unbearably slow with my HUGE imaps mailboxes) it helped me a great deal to get org integration working.
I left out the mu part entirely though and since I use sth. like (with-current-buffer "inbox" (term-send-raw-string (concat "/~i" message "\n\n")))) in my .emacs no shell script is needed.[1]
thanks again,
take care,
x
[0] http://upsilon.cc/~zack/blog/posts/2010/02/integratingMuttwith_Org-mode/ [1] this has the obvious disadvantage that I need to have the right mailbox open, but I am fine with that so far.