mailx 是一个邮件用户代理(MUA)工具,通俗的说就是邮件客户端。可以通过它来操作邮件传输代理(MTA),比如 Postfix、Sendmail、QQ 邮箱、163 邮箱等,进行收发邮件。不同于我们常见的 Outlook 或者 Spark 这种具有图形界面的邮件客户端,mailx 在 Linux 上以命令方式运行,可以很方便的与脚本或其它命令结合,将脚本或命令输出的信息通过邮件发送出去。与其类似的还有 mutt。

一、安装

注意:如果系统中预置了 mailx,由于依赖可能有所不同并因此会导致无法使用,所以需要先将系统预置 mailx卸载。然后再安装:

  • CentOS
$ sudo yum -y install mailx
  • Ubuntu & Debian
$ sudo apt-get install heirloom-mailx

heirloom-mailx 和 CentOS 7下的 mailx,除了配置文件不同外,实际是同一个程序。heirloom-mailx 的配置文件为 /etc/nail.rcmailx 的配置文件为 /etc/mail.rc。在 Ubuntu 和 Debian 系统下,与 heirloom-mailx 功能相似的程序还有 bsd-mailx,但 bsd-mailx 不能使用外部的 MTA。

安装完成后会生成 2 个新命令 mailmailx,可以发现 mail 命令是 mailx 命令的别名,也就意味着这两个命令效果完全一样。

二、配置

假设要使用 163 的邮箱发送邮件,并且通过 SSL 协议进行登录。通过 163 邮箱的设置页面可知,用来发信的服务器地址为 smtp.163.com,SSL 端口为 465。开启 smtp服务并获取授权码(也就是专门用于 MUA 认证用的密码)。

由于 mailx 默认连接的是本地的 MTA,如 Sendmail、Postfix 等,所以不需要使用 SSL 连接。而我们需要连接的是外部的 SMTP 服务器,所以使用 SSL/TLS 协议进行通信是最好的选择。但这就需要我们自行配置根证书数据库(mailx 默认未配置证书数据库)。mailx 先获取到外部 SMTP 服务器的证书链,然后通过 NSS 来检测证书链是否真的是由其声称的根证书签发的,检测所需就是我们配置的证书数据库中的根证书。

2.1 获取邮箱服务器的根证书

先来查看 163 邮箱服务器证书链的信息:

$ openssl s_client -connect smtp.163.com:465 -showcerts 2>&1 </dev/null | grep depth

输出内容如下:

depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA
depth=1 C = US, O = GeoTrust Inc., CN = GeoTrust SSL CA - G3
depth=0 C = CN, ST = ZheJiang, L = HangZhou, O = "NetEase (Hangzhou) Network Co., Ltd", CN = *.163.com

输出结果最上面的 GeoTrust Global CA 即是其根证书名(注意:根证书可能会变化,以你看到的为准),于是到 GeoTrust 官网的根证书下载页面找到对应名称的根证书下载地址进行下载:

$ wget https://www.geotrust.com/resources/root_certificates/certificates/GeoTrust_Global_CA.pem

如果是 QQ 邮箱,则访问 DigiCert 的根证书下载页面

2.2 将根证书导入证书数据库

先找个地方创建一个存放证书数据库的目录:

$ sudo mkdir /path/to/mailx_nssdb

将证书导入数据库:

$ sudo certutil -A -n "GeoTrust Global CA" -t "C,C,C" -d /path/to/mailx_nssdb -i GeoTrust_Global_CA.pem

上面的命令中,-A 选项表示将一个证书导入进证书数据库,如果数据库不存在,则初始化一个数据库。-n 选项指定证书的存放名称,如果名称已存在,会报错。-t 选项指定证书的信任级别(C 代表受信任的根证书,用逗号区分范围,查看这篇文档了解 NSS 对证书信任级别的分类)。-d 选项指定存放证书数据库的目录,这个目录必须提前创建好。-i 选项指定需要导入的证书,不区分证书格式。关于 certutil 命令的更多信息可以查看这篇文档:NSS 工具 certutil

导入后,可以在 mailx_nssdb 目录下看到 cert8.dbkey3.dbsecmod.db 这三个数据库文件。

可以用下面的命令查看数据库内的证书情况:

$ sudo certutil -L -d /path/to/mailx_nssdb/

输出:

Certificate Nickname                                         Trust Attributes
                                                             SSL,S/MIME,JAR/XPI

GeoTrust Global CA                                           C,C,C

可见根证书已被导入进去。把根证书导入到数据库之后就可以删除下载的根证书文件了。

$ rm ~/GeoTrust_Global_CA.pem

2.3 编辑 mailx 配置文件

打开 mailx 的配置文件

$ sudo vi /etc/mail.rc

在最后添加如下内容:

# 设置证书数据库所在目录
set nss-config-dir=/path/to/mailx_nssdb

# 设置邮件服务器地址
set smtp=smtps://smtp.163.com:465
# 设置用户名
set smtp-auth-user=example@163.com
# 设置密码,也就是授权码
set smtp-auth-password=mypassword
# 设置邮件发信地址
set from=example@163.com

参数解析:

  • nss-config-dir: mailx 使用的是 NSS 密码学工具库,而不是 Openssl,所以需要指定 NSS 的证书库。
  • smtp:这一项设置之后,mailx 将不再连接本地 MTA,转而连接这一项参数配置的 MTA 服务器地址。如果指定以 smtps:// 的方式连接,mailx 会检查 nss-config-dir 这一样是否被正确设置。
  • smtp-auth-usersmtp-auth-passwordfrom 这三个参数可以在 mailx 命令中以参数的形式设置,以避免邮箱账户信息被服务器的其他用户看到。
  • smtp-auth 参数指定认证方式。在上面的配置文件中并没有添加这一项,是因为当 smtp-auth-user 被设置后,mailx 的默认认证方式就是 login。其它可选值为 cram-md5plain。如果 smtp-authsmtp-auth-user 都没有被设置,则不会进行 STMP 认证。
  • ssl-verify 参数指定在验证服务器证书有效性时发生了错误该怎么处理。可设置的值为:1、strict,判定为失败时立即关闭连接。2、ask,用交互式方法询问是否继续。3、warn,打印一个警告并继续。4、ignore,不执行验证。默认值是 ask。由于我们在上面已经配置好了证书数据库,所以在调试的时候可以以默认值运行,调试成功后可以配置为 strict

三、使用

3.1 交互式

这种方式主要用于测试,更人性化一些:

$ mail example@qq.com    # 首先输入你的目标邮箱,然后回车
Subject: 这是一封测试邮件   # 然后mailx会问询你的邮件主题,输入后回车
this is a test.          # 然后你就可以输入正文了
Bye!
.                        # 正文输入完成后在新的一行输入英文句号表示结束,回车后发送
EOT

3.2 管道

mailx 可以从标准输入(stdin)中读取内容作为邮件内容。使用这种方式可以很好的和脚本或其他命令结合:

$ echo "你好,世界!" | mail -s "hello world" example@qq.com

上面命令中的 -s 选项指定的是邮件主题。

3.3 输入重定向

利用输入重定向可以将文件内容作为邮件内容发送:

$ mail -s this is a test" example@qq.com < /path/to/file

3.4 多个收件人

多个收件人之间使用逗号分隔:

$ echo "你好,世界!" | mail -s "hello world" example1@qq.com,example2@qq.com

3.5 抄送和密送

使用 -c 选项添加 CC 地址,使用 -b 选项添加 BCC 地址:

$ echo "你好,世界!" | mail -s "hello world" -c ccaddress@qq.com -b bccaddress@qq.com example@qq.com

3.6 指定发件人地址和姓名

使用 -r 选项来指定发件人地址和姓名,发件人名字在前,发件人地址使用尖括号括起来:

$ echo "你好,世界!" | mail -s "hello world" -r "Foo<bar@qq.com>" example@qq.com

3.7 添加附件

使用 -a 选项来指定要添加的附件:

$ echo "你好,世界!" | mail -s "hello world" -a /path/to/file example@qq.com

3.8 在命令中设定参数

在前面,我们已经在 /etc/mail.rc 这个配置文件中设定了一些参数,这些参数可以通过 -S (大写)选项进行覆盖,格式是:-S "参数名=参数值"。通过这个选项,我们就可以在命令中动态的设置 STMP 服务器配置信息:

$ echo "你好,世界!" | mail -s "hello world" \
> -S "smtp=smtps://smtp.163.com:465" \
> -S "smtp-auth-user=example@163.com" \
> -S "smtp-auth-password=mypassword" \
> -S "from=example@163.com" \
> example@qq.com

3.9 查看与 STMP 服务器的通信过程

通过 -v 选项,可以在终端打印出与 STMP 服务器的通信过程。

$ echo "你好,世界!" | mail -v -s "hello world" example@qq.com

四、更多

有关mailx的更多详细信息可以通过 Linux 自带的手册查看:

$ man 1 mailx

有兴趣的话,可以看一下我的另一篇文章:通过 mailx 发送 Cron 输出

五、参考文章

9 mail/mailx command examples to send emails from command line on Linux

(完)