[Mutt]用msmtp替代esmtp作发信代理

刚开始使用mutt的时候,由于也没有什么经验,在MDA选择方面抓了一个esmtp就用上了。说实话,esmtp也一直工作的很好,就是发信的时候需要傻傻等着(参见muttrc的sendmail_wait参数),如果不等待也可以,发送失败你就不知道了。虽然失败的情况比较少,一般都是邮件比较大或者网络不太好的情况才会发生,但我们外发的邮件往往都是比较重要的,真想有一种能够自动重试的发信代理,于是就查到了msmtp。

[msmtp](http://msmtp.sourceforge.net/)和[esmtp](http://esmtp.sourceforge.net/)两个软件作者都不多,但msmtp确实更新频繁一些,而esmtp作者说[现在已经不需要怎么添加功能了,只是维护bug](http://esmtp.sourceforge.net/roadmap.html)。在多账户配置方面,好像msmtp的配置方法要“聪明”一些,账号规则有一些”继承”的小把戏。在发信队列方面,esmtp在Features中明显声明不支持,而msmtp有一个msmtpqueue,国内用的人非常少,只看到[cu blog](http://blog.chinaunix.net/u1/37261/showart_288583.html)上提到了一点,smtpqueue能够把要外发的邮件集中在一起,单独发送,但没有说失败处理的事情;再到msmtp在sf.net上的cvs中查[msmtpqueue的README文件](http://msmtp.cvs.sourceforge.net/msmtp/msmtpqueue/README?revision=1.2&view=markup),终于搞清楚了,和我的需要比较吻合。

msmtpqueue会”冒充”成一个MDA,当mutt发信时,它接收外发邮件并返回成功信息,而实际上只是把信件保存在QUEUEDIR里了,当调用msmtp-runqueue.sh的时候,再进行实际的发送处理。发送成功一封信,就会从QUEUEDIR中删除,发送失败就继续保持不动,下次再调用msmtp-runqueue.sh的时候自然又会处理(相当于重发)了。比起mutt中的邮件失败重发还会多生成一个邮件副本(我设定了发信的同时record在当前目录)应该是好多了。

Mails sent successfully will be deleted from the queue directory.
Mails whose delivery failed will be left untouched; you may want to edit
them, delete them by hand or simply run msmtp-runqueue.sh at a later time.

工作开始,首先通过apt安装msmtp,很小的,加上TLS/SSL所需的libgsasl7,一共才182k。然后配置账号文件~/.msmtprc,格式和~/.esmtprc比较类似:

# Default value for all following accounts
defaults
#      tls on
    tls_trust_file /etc/ssl/certs/ca-certificates.crt
#   keepbcc on
    logfile ~/log/msmtp.log

# Gmail
account gmail
    host smtp.gmail.com
    port 587
    auth on
    tls on

account mailbox@gmail.com : gmail
    from mailbox@gmail.com
    user "mailbox@gmail.com"
    password "secret"

# Another mail service
account another_mailbox@domain.com
    host smtp.domain.com
    auth on
    from another_mailbox@domain.com
    user "another_mailbox"
    password "another_secret"

# Default account
account default : mailbox@gmail.com

Copy自[官方文档](http://msmtp.sourceforge.net/doc/msmtp.html#A-user-configuration-file),语法很简单,最开始的defaults是默认设置,然后的account就是各个账号的设置了,账号名称最好和邮件中的From:对应,这样msmtp就能知道调用哪个账号了。最有意思的是,account可以用冒号:来”继承”其它已定义账号的设置,使用这个机制,就为所有gmail邮箱指定了host、port、auth、tls四个属性,然后在具体的账号设置中,只要再设定from、user、password就可以了,很方便,”继承”多个账号的话用逗号隔开。最后默认发信账号(匹配寻找account失败时使用)default可以直接”继承”某个账号的设置过来。

然后设置~/.muttrc,用msmtp来发信:

set sendmail="/path/to/msmtp"
set use_from=yes
set from="Fwolf <mailbox@domain.com>"
set envelope_from=yes
set sendmail_wait=0

测试一下,发信正常,现在可以让msmtpqueue出场了。由于msmtpqueue只是在”转达”msmtp发信的命令,所以需要先把msmtp调试好以后再配置。

msmtpqueue已经随msmtp安装上了,放在/usr/share/doc/msmtp/examples下,按照这里README文件的说明,把msmtp-enqueue.shmsmtp-runqueue.sh两个文件加上执行属性,然后ln到$HOME/.mutt下,再在这里创建一个新目录msmtpqueue,ln成~/.msmtpqueue(两个脚本默认的QUEUEDIR),最后修改muttrc中的sendmail:

set sendmail = "~/.mutt/msmtp-enqueue.sh"

好了,现在再来发信,是不是瞬间就完成了?再看~/.mutt/msmtpqueue目录下,也多了两个文件,分别以.mail.msmtp结尾,他们分别包含了刚才所发信件的信件内容和发送命令。现在运行msmtp-runqueue.sh

~/.mutt$ ./msmtp-runqueue.sh 
*** Sending 2008-01-12-23.03.52.mail...
2008-01-12-23.03.52.mail sent successfully

邮件就这样顺利的发出去了。

工作到这里基本就都完成了,发信时按y嗖一下就完成的感觉真不错,为了更方便的发送邮件,还可以在mutt中定义启动邮件发送程序的快捷键:

macro generic S "!~/.mutt/msmtp-runqueue.sh\n"

ubuntu的包里没有,但[svn上](http://msmtp.cvs.sourceforge.net/msmtp/msmtpqueue/)还有一个msmtp-listqueue.sh脚本,列出当前QUEUEDIR中信件的From/To/主题,凑合能用,但用RFC2047编码方式的中文标题自然是不能正常显示的了。

Update @ 2009-03-27

知道gmail的两个端口,465和587有区别么?还真不完全一样,我用msmtp试出来的结果是这样的:

  • 如果使用465端口,则置tls_starttls off
  • 如果使用587端口,则置tls_starttls on

否则不是连不上就是无回馈数据。是看了[标题: 我翻译的 msmtp 的手册页](http://www.linuxsir.org/bbs/thread301660.html)后受启发发现的。

4 thoughts on “[Mutt]用msmtp替代esmtp作发信代理”

  1. I follow up your instructions, but where can I get the ca-certificates.crt file? Is it in the libgsasl7.deb?

  2. 你好,我也正在使用Mutt+msmtp收发邮件,但是无法使用TLS加密功能 我指定了相同的证书,却提示:TLS certificate verification failed: the certificate hasn’t got a known issuer 对于这种情况,你知道怎么处理吗,谢谢:)

    1. /etc/ssl/certs/ca-certificates.crt 应该是信任的证书信息,在我的机器上这个文件的大小为 221357,建议你检查一下你机器上这个文件的信息?看错误信息好像是说证书没有颁发者。

Leave a Reply

Your email address will not be published. Required fields are marked *