基于 mutt+offlineimap+notmuch+inotifywait 的个人邮件系统

收邮件

早先使用getmail + procmail。缺点是本地对邮件的操作无法在服务器上反映出来。

使用offlineimap可以利用Gmail的filter功能,把邮件分拣到本地的各个maildir子目录。

注意在Gmail上设置filter规则时,要选上Skip Inbox,以免一封邮件同时出现在分类子目录和INBOX中。请看下面这条示例规则:

Matches: list:"<tuna-general.googlegroups.com>"
Do this: Skip Inbox, Apply label "Tuna"

新邮件提醒功能

我大致想到这项功能可以在以下三个地方处理。

  • 在offlineimap配置文件中处理。草草看了下它的配置,postsynhookpresynchook不够用,因为无法知道邮件的标题和其他信息。
  • man notmuch-hooks没有满足需要的hook。postnewhook也无法知道是否添加了新邮件。
  • mutt中配置。Mutt配置太复杂,难以集成。
  • 求助于inotifywait

最终选择了最后一个方案,编写了这样一个常驻的脚本。

1
2
3
4
5
6
7
##!/bin/bash
inotifywait -mrqe create ~/Maildir | while read; do
if ! [[ "$reply" =~ notmuch ]] && notmuch new | grep -q ^Added; then
msg=$(notmuch search --sort=newest-first --limit=1 --output=summary '*' | cut -d';' -f2-)
notify-send -i ~/Icons/gmail.png -c mail -t 5 -- 'New mail' "$msg"
fi
done

大意是递归监控~/Maildir目录下文件的创建事件,如果创建的文件不是notmuch建立的,那么就执行notmuch new把这个新邮件添加到notmuch数据库中,调用notify-send提示最新的邮件。

在mutt中集成邮件搜索功能

使用notmuch作为邮件检索系统。

在某个$PATH路径下建立脚本,比如~/bin/mutt-notmuch

1
2
3
4
5
6
7
8
9
##!/bin/bash
tmpdir=/tmp/.notmuch
rm -rf $tmpdir/{cur,new}
mkdir -p $tmpdir/{cur,new,tmp}
echo 'notmuch search terms:'
read
notmuch search --output=files "$REPLY" . |
awk 'NR<=50;NR==50{system("notify-send -i ~/Icons/gmail.png Mail
\"Too many results\"")}' | xargs -r ln -sft $tmpdir/cur

这个脚本的作用是读入一行,用notmuch search检索匹配的邮件,把它们的软链接放到/tmp/.notmuch这个maildir中。

然后在~/.mutt/muttrc中添加

macro index ,s \
  "<enter-command>unset wait_key<enter><shell-escape>mutt-notmuch --output \
  /tmp/.notmuch --prompt search<enter><change-folder-readonly>/tmp/.notmuch<enter>" \
  "search mail (using notmuch)"

这样在Mutt中按,s会调用之前的脚本,并且检查/tmp/.notmuch这个搜索结果形成的maildir。