blog post on integrating Mutt and Org-mode
[homepage.git] / blog / posts / 2010 / 02 / integrating_Mutt_with_Org-mode.mdwn
1 # remember Mutt's mail in Org-mode and jump back to them
2
3 As [[already anticipated|2009/10/mail_indexing_for_mutt]], I've been
4 implementing my own [[!wikipedia Getting_Things_Done]] work flow. This post
5 documents one of its main bricks: the **integration between
6 [Mutt](http://www.mutt.org/) and [Org-mode](http://orgmode.org)**.
7
8 As a geek, my main incoming stream of TODO items and information in general is
9 email. As emails hit my INBOX, I either deal with them immediately (reply,
10 archive, delete) or I need to store them elsewhere, possibly adding extra
11 information such as a deadline, a personal note, the associated next action,
12 the context in which it is actionable, etc. This need of adding extra
13 information is what defeats the usage of my mail client (Mutt) as a list
14 manager (in the GTD sense), and that's where I plugged Org-mode in. My main
15 goals are:
16
17 1. **create Org-mode notes from Mutt**, referencing the current email, and
18    possibly inlining some of its metadata (e.g. subject, sender)
19
20 2. quickly **retrieve referenced emails from Org-mode notes**; ideally that
21    should happen in my usual email environment (i.e. Mutt), so that I can
22    process the retrieved mail as usual (e.g. to inform the sender that I did
23    something about it)
24
25 <small> In fact, both would be straightforward to achieve if I were using some
26 Emacs-based mail client such as [Gnus](http://www.gnus.org/), but
27 [[I resist the *Emacs operating system syndrome*|2008/11/from_Vim_to_Emacs_-_part_2]],
28 and therefore I insist in using my beloved Mutt. </small>
29
30 Let's see how the two parts of the interaction between Mutt and Org-mode work.
31
32 ## <small>(1)</small> Mutt &rarr; Org-mode <small><em>(there ...)</em></small>
33
34 The interaction from Mutt to Org-mode happens via
35 [org-protocol](http://orgmode.org/worg/org-contrib/org-protocol.php). Using it
36 external applications can feed content to Org-mode note templates, which are
37 then interactively edited (via
38 [emacsclient](http://www.emacswiki.org/emacs/EmacsClient)), and finally filed
39 away.
40
41 The Mutt glue macro from my `~/.muttrc` is as follow:
42
43         macro index \eR "|~/bin/remember-mail\n"
44
45 The [[remember-mail]] script is trivial: it parses the fed mail from STDIN
46 (using a couple of legacy Perl modules) and then invokes org-protocol.
47
48 The relevant configuration from my `~/.emacs` is reported below; the comments
49 explain the various parts:
50
51         ;; standard org <-> remember stuff, RTFM
52         (org-remember-insinuate)
53         (setq org-default-notes-file "~/org/gtd.org")
54         (setq org-remember-templates  ;; mail-specific note template, identified by "m"
55               '(("Mail" ?m "* %?\n\n  Source: %u, %c\n  %i" nil)))
56
57         ;; ensure that emacsclient will show just the note to be edited when invoked
58         ;; from Mutt, and that it will shut down emacsclient once finished;
59         ;; fallback to legacy behavior when not invoked via org-protocol.
60         (add-hook 'org-remember-mode-hook 'delete-other-windows)
61         (setq my-org-protocol-flag nil)
62         (defadvice org-remember-finalize (after delete-frame-at-end activate)
63           "Delete frame at remember finalization"
64           (progn (if my-org-protocol-flag (delete-frame))
65                  (setq my-org-protocol-flag nil)))
66         (defadvice org-remember-kill (after delete-frame-at-end activate)
67           "Delete frame at remember abort"
68           (progn (if my-org-protocol-flag (delete-frame))
69                  (setq my-org-protocol-flag nil)))
70         (defadvice org-protocol-remember (before set-org-protocol-flag activate)
71           (setq my-org-protocol-flag t))
72
73 The result is that when you hit `ESC-R` in Mutt, emacsclient will be fired up
74 in place presenting a note template that already contains relevant mail
75 information (date, subject, from) and lets you add extra information before
76 going away. Additionally, the email message-id will be hidden in the note as a
77 `mutt:` hyperlink with anchor text "mail".
78
79 ## <small>(2)</small> Org-mode &rarr; Mutt <small><em>(... and back again)</em></small>
80
81 Going back means that clicking on a "mail" hyperlink within an Org-mode note
82 should bring up a Mutt instance showing the original message, in its context
83 (e.g. its own mailbox). Achieving that consists of 2 separate steps:
84
85 1. looking up a specific message by `Message-ID`
86 2. firing up Mutt on the looked up message
87
88 For the first part I use [[!debpkgsid maildir-utils]] (AKA
89 [mu](http://code.google.com/p/mu0/)): a Xapian-based mail indexing tool, which
90 nicely integrates with Mutt; check out
91 [[my previous blog post on the subject|2009/10/mail_indexing_for_mutt/]] for a
92 sample setup. Using mu, `Message-ID` lookups are as simple as:
93
94         zack@usha:~$ mu find -f p m:E1NbJad-0007x9-B7@ries.debian.org
95         /home/zack/Maildir/Debian.project/cur/1264883664_0.9472.usha,U=6320,FMD5=2284e927bb93d8a2ec434f5614dc04ba:2,S
96
97 <small> Note: I'm relying upon *maildir-utils version 0.6* or greater, for all
98 presented scripts. </small>
99
100 For the second part I use the [[mutt-open]] script which fires upon a Mutt
101 instance on the maildir containing a specific message, and then "hits" the
102 appropriate keys to open the message and shutdown
103 [the sidebar](http://packages.debian.org/lenny/mutt-patched) (if desired). It
104 is a nicely reusable script, which I've being using elsewhere too.
105
106 The needed glue on the emacs side is just a function to invoke `mutt-open` in a
107 brand new terminal, and its declaration as the handler for `mutt:` URLs.
108
109         (defun open-mail-in-mutt (message)
110           "Open a mail message in Mutt, using an external terminal.
111
112         Message can be specified either by a path pointing inside a
113         Maildir, or by Message-ID."
114           (interactive "MPath or Message-ID: ")
115           (shell-command
116            (format "gnome-terminal -e \"%s %s\""
117                    (substitute-in-file-name "$HOME/bin/mutt-open") message)))
118
119         ;; add support for "mutt:ID" links
120         (org-add-link-type "mutt" 'open-mail-in-mutt)
121
122 VoilĂ !
123
124 ## Download
125
126 Summary of scripts and configuration snippets discussed above:
127
128 * [[remember-mail]] - store in Org-mode a note back-referencing an email
129 * [[mutt-open]] - open Mutt on an email having a specific `Message-ID`
130 * [[Emacs configuration|emacs-conf]]
131 * [[Mutt configuration|mutt-conf]]
132
133 [[!tag lang/english planet-debian orgmode mutt gtd hack]]