Hi all,
  I'm new to Org, but I fell in love with it quite quickly :-) As my
mail user agent has nothing to do with Emacs---it is Mutt---I was envy
to integrate it with Org, and I've actually done that.

With this mail, I'm wondering whether there were past/alternative
success stories about Mutt <-> Org integration (I've found nothing on
the Web).

Also, if you like the proposed way to integration, I'm looking forward
for advices on where to document it so that other people can take
inspiration (and avoid reinventing wheels, as I might have done).

Mutt <-> Org integration
------------------------

The link between Mutt and Org is the Message-ID of emails that I store
in a set of recursive Maildirs.

Those mails are indexed by mu (http://code.google.com/p/mu0/), an
alternative to mairix and nmzmail that I find more convenient. Just in
case you wonder, mail indexes are updated regularly with the following
cron entry (which takes just a few seconds, usually):

  31  */2 *  *   *     on_ac_power && mu-index -q

The attached script mutt-open is able to fire up Mutt on a message
specified by Message-ID (or path, FWIW) by looking it up via
mu-find. After finding the path, the script basically guesses the
corresponding Maildir, run mutt on it, and by sending some keys (via the
"push" command) open the given mail.

>From Org-mode, I can then follow "mutt:" links by using the following in
my Emacs conf:

  ;; add support for "mutt:ID" links
  (org-add-link-type "mutt" 'open-mail-in-mutt)

  (defun open-mail-in-mutt (message)
    "Open a mail message in Mutt, inside a terminal.
  
  Message can be specified either by a path pointing inside a
  Maildir, or by Message-ID."
    (interactive "MPath or Message-ID: ")
    (shell-command
     (concat
      (format "x-terminal-emulator -e \"%s %s\""
            (substitute-in-file-name "$HOME/bin/mutt-open") message))))

Finally, I've a macro to remember in Org a mail that I'm reading in
mutt:

  macro index \eR "|~/bin/remember-mail\n"

The corresponding script remember-mail is in attachment. It just
extracts from the piped mail the needed info to invoke Org protocol
appropriately via emacsclient. The corresponding remember template is
trivially as follows:

  ("Mail" ?m "* %?\n\n  Source: %u, %c\n  %i" nil "Note (mail)")


Any comment is welcome!

-- 
Stefano Zacchiroli -o- PhD in Computer Science \ PostDoc @ Univ. Paris 7
z...@{upsilon.cc,pps.jussieu.fr,debian.org} -<>- http://upsilon.cc/zack/
Dietro un grande uomo c'è ..|  .  |. Et ne m'en veux pas si je te tutoie
sempre uno zaino ...........| ..: |.... Je dis tu à tous ceux que j'aime
#!/bin/bash
#
# Fire up mutt on a given mail, located in some Maildir
# Mail can be specified either by path or by Messsage-ID; in the latter case
# file lookup is performed using some mail indexing tool.
#
# Copyright: © 2009 Stefano Zacchiroli <z...@upsilon.cc> 
# License: GNU General Public License (GPL), version 3 or above

MUTT=mutt
MUTT_FLAGS="-R"
HIDE_SIDEBAR_CMD="B"    # set to empty string if sidebar is not used

# Sample output of 'mu-find -f P i:MESSAGE-ID', which gets passed to mutt-open
#  
/home/zack/Maildir/INBOX/cur/1256673179_0.8700.usha,U=37420,FMD5=7e33429f656f1e6e9d79b29c3f82c57e:2,S

die_usage () {
    echo "Usage: mutt-open FILE" 1>&2
    echo "       mutt-open MESSAGE-ID" 1>&2
    echo 'E.g.:  mutt-open `mu-find -f P m:MESSAGE-ID`' 1>&2
    echo '       mutt-open 20091030112543.ga4...@usha.takhisis.invalid' 1>&2
    exit 3
}

# Lookup: Message-ID -> mail path. Store results in global $fname
lookup_msgid () {
    fname=$(mu-find --format P m:"$1" | head -n 1)
}

dump_info () {
    echo "fname: $fname"
    echo "msgid: $msgid"
}

if [ -z "$1" -o "$1" = "-h" -o "$1" = "-help" -o "$1" = "--help" ] ; then
    die_usage
fi
if (echo "$1" | grep -q /) && test -f "$1" ; then       # arg is a file
    fname="$1"
    msgid=$(egrep -i '^message-id:' "$fname" | cut -f 2 -d':' | sed 's/[ 
<>]//g')
elif ! (echo "$1" | grep -q /) ; then   # arg is a Message-ID
    msgid="$1"
    lookup_msgid "$msgid"       # side-effect: set $fname
fi
# dump_info ; exit 3
if ! dirname "$fname" | egrep -q '/(cur|new|tmp)$' ; then
    echo "Path not pointing inside a maildir: $fname" 1>&2
    exit 2
fi
maildir=$(dirname $(dirname "$fname"))

if ! [ -d "$maildir" ] ; then
    echo "Not a (mail)dir: $maildir" 1>&1
    exit 2
fi

# UGLY HACK: without sleep, push keys do not reach mutt, I _guess_ that there
# might be some terminal-related issue here, since also waiting for an input
# with "read" similarly "solves" the problem
sleep 0.1
mutt_keys="$HIDE_SIDEBAR_CMD/~i$msgid\n\n"
exec $MUTT $MUTT_FLAGS -f "$maildir/" -e "push $mutt_keys"
#!/usr/bin/perl -w
#
# Helper for mutt to remember mails in Emacs' Org mode
#
# Copyright: © 2009 Stefano Zacchiroli <z...@upsilon.cc> 
# License: GNU General Public License (GPL), version 3 or above
#
# Example of mutt macro to invoke this hitting ESC-R (to be put in ~/.muttrc):
#  macro index \eR "|~/bin/remember-mail\n"

use strict;
use Mail::Internet;
use URI::Escape;

my $msg = Mail::Internet->new(\*STDIN);
$msg->head->get('message-id') =~ /^<(.*)>$/;
my $mid = $1;
my $subject = $msg->head->get('subject') || "";
my $from = $msg->head->get('from') || "";
chomp ($subject, $from);
my $note_body = uri_escape("  Subject: $subject\n    From: $from");

exec("emacsclient -c org-protocol:/remember:/m/mutt:$mid/mail/$note_body");
_______________________________________________
Emacs-orgmode mailing list
Remember: use `Reply All' to send replies to the list.
Emacs-orgmode@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-orgmode

Reply via email to