配置Mutt二三事

与无数国人一样,我也是从王垠的《Mutt email 程序使用入门》入门的。很荣幸,当初我直接找到了这篇博文的原始地址,而不是满天飞的CSDN转载。我想要使用Mutt的初衷,不仅仅是觉得tui应用很酷,而且也有想要在自动化shell脚本里加入发送邮件的功能。后来,我把Mutt安装到每一台我所使用的服务器上,Mutt配置也在各台计算机之间传来传去,就像其他费时费力的配置脚本一样,例如.vimrc(笑)。再后来,我接触到NeoMutt。与Mutt一样,NeoMutt也是使用纯C语言实现的项目,并且使用与Mutt相同的图标:一只像素风格的小狗。“Teaching an Old Dog New Tricks.”,NoeMuttGithub主页信息栏里,似乎蕴含着Mutt的历史与未来。

一个完整的邮件客户端(Mail user agent, MUA)至少应该能够做两件事情: 1. 查看邮件 2. 发送邮件。接下来也将分成这两大部分介绍Mutt的使用方法。

查看邮件

协议

从服务器上获取邮件有两种协议,POP3IMAP。 粗略来理解,可以认为基于IMAP协议会把本地的操作(已读、删除)同步到云端;而POP3则不会。作为颇有类Unix组件化哲学的Mutt,在查看邮件方面也有广泛对接的程序,例如fetchmail,一个可以定期将邮件下载回本地的后台程序。当然,Mutt也保证自己是开箱即用的,不使用其他软件下载邮件也可以,Mutt支持直接查看服务器上邮件。不过,直接查看邮件有一个问题,IMAP/POP3协议支持查询邮件目录而不下载,如果在Mutt里配置显示邮件行数的话,那一列就全都是0了,除非打开一封邮件看看。

显示

控制台的资源总是很紧张,每一个字符都会占用一个显示位,不多也不少。因此合理安排显示的内容、每列的宽度与间隔就显得很重要。顺便一提MuttCJK字符宽度的计算是正确的,不会像某些愚蠢的软件一样出现对不齐的问题(说的就是你,snap,以及到底是谁给服务器安装中文版的Ubuntu的……)。

邮件渲染

现代大多数的邮件除了会发一份HTML格式的文件之外,也会照顾到老旧的MUA(Mutt:正是在下)而附带一份纯文本的“fallback”。但是,不是所有的邮件都是如此,至少Mutt写出这样一份有好几种预备方案的健壮的邮件是很困难的(Mutt何苦为难Mutt)。所以,当接收到仅有一份HTML内容的邮件时,用默认配置的Mutt就只能阅读HTML源码了。

如何解决这个问题呢?

正巧,之前我了解过一个著名的cli浏览器w3m,它可以实现一些浏览器的基本功能。那么,Mutt是否可以使用w3m渲染HTML邮件呢?

答案是肯定的。

省流总结如下:

  1. 创建一个~/.mutt/mailcap文件,
  2. 在上述文件里写入一行text/html; w3m -I %{charset} -T text/html; copiousoutput;
  3. 把原本的~/.muttrc文件移动到~/.mutt/muttrc

注意 顺便一提,w3m无法安装在WSL1里。

发送邮件

编辑器

写邮件或者回信的时候,Mutt允许你自定义编辑器,通过指定EDITOR的值。 EDITOR其实是常见的变量,例如crontab也需要这个值作为默认编辑器(没有则默认vi)。在我的shell初始化脚本里,EDITOR值为vim。当然,你可以指定其为emacsnano、甚至VSCode(code)。

命令行调用

shell里调用mutt/neomutt非常简单,令它接收管道的输出作为自己的输入就好了。一行代码就是,echo "something" | mutt -s "Subject" you@addr.com

有的时候,还可以添加一些类似于.muttrc文件里的选项的设置:

1
echo "mail content" | mutt  -e "set content_type = \"text/html\"" -s "Subject" you@addr.com

注意-e参数一定要在最前面。

cat、sed一样,Mutt是从管道里接收数据的软件,因此可以写类似以下形式的代码:

1
2
3
4
5
6
7
8
9
10
11
mutt -s "Are ya ready kids?" spongebob@pineapple.house <<MAIL
Who lives in a pineapple under the sea?
Spongebob squarepants!
Absorbant and yellow and porous is he?
Spongebob squarepants!
If nautical nonsense is something you wish?
Spongebob squarepants!
Then drop on the deck and flop like a fish!
Spongebob squarepants!
Ready?
MAIL

最后是一个小细节。 Mutt的指令是mutt,NeoMutt的指令是neomutt。其实就此与mutt诀别也没什么,但是我还是舍不得破坏~/.zsh_history里的指令统一性。(并没有这种东西)

一个简单的处理方法是在~/.bashrc或者~/.zshrc里添加一行alias mutt='neomutt'

MSMTP

MSMTP是一个SMTP客户端,配合mutt使用,可以实现更丰富的发信功能,比如,本地的日志记录,设置SOCKS代理等。 Ubuntu上大多数软件的配置流程都是轻松的,因为基本是开箱即用的。但那都是服务级应用,MSMTP这种用户级应用还是要踩不少坑的。

就比如说,我喜欢把所有的用户级日志放在~/logs目录下。而MSMTP,就经常报错:msmtp: cannot log to /home/julia/logs/msmtp.log: cannot open: No such file or directory。创建日志文件并将文件权限设置成777并不能解决这个问题。更神秘的是,这个bug时有时无,从Ubuntu 18.04Ubuntu 22.04,不论是物理机还是WSL兼容层,像一个u0,飘荡在Linux系统里。

这是为什么呢?

没想到,这样的小问题,居然困扰了我4年。从刚假设邮件服务器刚开始使用Mutt,一直到给邮箱服务器上SSL并使用NeoMutt作为客户端的刚刚。 或许,都怪我懒得修吧。

查阅资料可知,查看/etc/apparmor.d/usr.bin.msmtp可以看到msmtp被设定为对特定pattern的文件有写入权限:

1
2
3
4
5
6
owner @{HOME}/.msmtp*.log wk,
/var/log/msmtp wk,

...

owner @{HOME}/.cache/msmtp/*.log wk,

可以看到,我设置的日志文件/home/julia/logs/msmtp.log不满足任一pattern。但是我懒得改这个文件,所以我选择把日志文件设置为/home/julia/.msmtp-$(date +%Y-%m).log。问题顺利得到解决。

除了突然冒出来的apparmor。

apparmor是什么?

以前我从未听说。

Ubuntu居然默认安装着这种东西,以前完全没有注意到。

它甚至不是一个开机启动的守护进程,而仅仅是一系列传统Unix自主访问控制(discretionary access control, DAC)策略。

只有在追查这个bug的时候,我才发现了它,静悄悄地影响着几乎每一个后台运行的服务。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{21:35}~ ➭ aa-status
apparmor module is loaded.
You do not have enough privilege to read the profile set.
{21:36}~ ➭ sudo aa-status
[sudo] password for julia:
apparmor module is loaded.
34 profiles are loaded.
34 profiles are in enforce mode.

...

0 profiles are in complain mode.
6 processes have profiles defined.
6 processes are in enforce mode.

...

怪恐怖的。

Fin.

0条搜索结果。