使用mailx在控制台发送邮件

3,948 阅读8分钟

从Unix开始就可以使用mail命令发送邮件,经过多年的变迁,这个命令的使用方式和工具链已经发生了很多变化。我们从头说起,通过mail命令的历史了解它的现状。

mailx的历史

mail命令最早出现在1971年问世的第一版Unix上,当时只是用于向同一台计算机上的其他用户发送邮件。在后来的Unix版本中mail扩展了发送远程邮件的功能。

1978年在BSD Unix上(Unix的一个主要分支)出现了另一个邮件程序Berkeley Mail,它也使用mail命令,并在后来代替了原Unix的mail

在1987年发布的Unix版本上出现了Berkeley Mail的衍生版本mailx,该程序使用命令mailx

由于Unix长期处于闭源状态,Linux用户无法使用Unix的mailx程序,于是出现了基于Berkeley Mail的开源版本nail,后改名为Heirloom mailxHeirloom mailxBerkeley Mail一样使用mail命令,并扩展了很多功能,如内置的POP3、IMAP、SMTP支持。Heirloom mailx尽可能保持与mailx的使用体验一致,所以也添加了mailx命令,但它只是mail的符号链接。

以前各Linux发行版上的mailx软件包基本都是打包自Heirloom mailx

Heirloom mailx的更新后来逐渐停滞,又出现了Heirloom mailx的分支s-nail。目前各发行版已经用s-nail取代了Heirloom mailx,包名一般是s-nail,提供mailmailx命令,使用体验与Heirloom mailx基本一致。

s-nail将来的v15版本将做出不向后兼容的巨大改变,且s-nail欲更名为s-mailx

安装mailx

很多Linux发行版都会提供名为mailutils的软件包,但这不是我们需要的mailxGnu Mail的软件行为和我们介绍的mailx并不一致。

我们也不需要安装sendmail,因为我们只是提交邮件到外部邮件服务器(如QQ邮箱),而不是自己搭建邮件服务器。s-nail内置了SMTP功能。

Red Hat系

如果使用Fedora或者CentOS Stream,使用下面的命令:

sudo dnf install s-nail

如果使用CentOS,其软件包普遍比较老旧,如果没有s-nail,就安装名为mailx软件包:

sudo dnf install mailx

Debian系

使用下面的命令安装:

sudo apt install s-nail

Debian系的s-nail软件包可能不提供mailmailx命令,而是使用s-nail命令。可以通过下面的命令创建mail命令。

sudo ln -s s-nail /usr/bin/mail

Arch Linux系

使用下面的命令安装

sudo pacman -S s-nail

配置mailx

开启邮箱的SMTP服务

使用第三方客户端发送邮件需要开启邮箱的SMTP服务,很多邮箱还需要授权码。如果你的邮箱不支持SMTP服务,就无法通过第三方客户端发送邮件了。下面以QQ邮箱为例介绍如何开启SMTP服务并且获得有关信息。

在邮箱主页的左上角进入“设置页面”,并进入“账户”选项卡。

在下面找到POP3/IMAP/SMTP设置,把需要的服务打开,并且点击提示部分的“生成授权码”按照要求获取授权码。

点击帮助部分,即“什么是IMAP,它又是如何设置?”,进入帮助页,查看邮件服务器的地址以及支持的端口。

编辑mailx配置文件

不建议修改/etc/mail.rc文件,应该在用户目录建立自己的配置文件!!!

在用户根目录下创建".mailrc"文件

vim ~/.mailrc

添加SMTP配置

在“.mailrc”文件中加入以下配置信息,以QQ邮箱为例。

set smtp-auth=login
set smtp-use-starttls
set smtp='smtp://smtp.qq.com:587'
set smtp-auth-user='user@qq.com'
set smtp-auth-password='password'
  • set smtp-auth=login:使用登录验证的方式连接到SMTP服务器
  • set smtp-use-starttls:开启TLS加密,否则邮件使用明文提交
  • set smtp='smtp://smtp.qq.com:587':提供QQ邮箱的SMTP服务器和端口
  • set smtp-auth-user='user@qq.com':验证用户,一般为邮箱帐号
  • set smtp-auth-password='password':验证密码,一般为邮箱密码,但很多邮件服务器使用授权码

设置SMTP服务器还可以写为

set smtp='smtp.qq.com:587'

但不建议这么写。如果要使用端口465smtps,必须用第一种写法指定协议。

set smtp='smtps://smtp.qq.com:465'

如果省略smtp协议端口,默认使用端口25
如果使用端口465smtps,则默认开启TLS加密,不需要set smtp-use-starttls

建议使用端口587提交邮件。关于如何选择端口,请读我的这篇文章:邮件客户端如何选择SMTP端口


s-nail v15配置

s-nail的v15版本将弃用之前的SMTP配置格式。 如果在v14.9中使用旧版配置格式,将给出警告。v14.10将默认使用v15配置格式。

v15之前的版本中使用v15的配置格式,需要在配置文件中添加下面的申明:

set v15-compat

验证方式set smtp-auth=login和加密方式set smtp-use-starttls没有改变。

v15mta取代了smtp变量,并把用户名、密码和SMTP服务器放在了一个URL中,URL格式如下:

PROTOCOL://[USER[:PASSWORD]@]server[:port]

示例如下:

set mta='smtp://user:password@smtp.qq.com:587'

如果用户名或密码中有"@"字符,需要URL转义。

添加发件人

如果仔细看一封电子邮件,会发现标头有FromToSubject等字样。现在为我们的邮件添加From部分,即发件人

在“.mailrc”文件中加入下面的配置:

set from='user@domain'

除了邮箱地址,还可以添加发件人的名字:

set from='Name<user@domain>'

那么这里设置的发件人和上面设置的验证用户有什么区别和关系呢?

验证用户用于向邮件服务器验证身份,获得SMTP服务器的使用权,你输入的信息都由邮件服务器处理,不会发给收件人。而from变量设置的发件人信息会发给收件人,表明这封邮件是谁发的,可用于回复,或者投递失败退回。同时发件人信息除了邮箱地址还可以设置发件人名字。

邮件服务器一般要求验证用户和发件人信息必须一致,毕竟不能让你使用服务器上别人的邮箱发送邮件。但如果当前用户有多个邮箱别名,则发件人和验证用户信息可以不同。比如QQ邮箱提供数字邮箱和英文邮箱(两个名字指向同一个邮箱),这时发件人和验证用户可以分别填这两个。

添加别名

我们可以通过添加别名保存联系人信息,这样在填收件人信息的时候可以少敲几下键盘。

添加别名的方法如下:

alias Zhangsan 'zhangsan@qq.com'
alias Lisi 'lisi@163.com'

注意: 这里的邮箱地址不能写成'Name<user@domain>'这种形式,因为别名Zhangsan会默认当作收件人名字。别名不能用于发件人。

如果同一个别名对应多个邮箱地址,如:

alias Zhangsan 'zhangsan@qq.com'
alias Zhangsan 'zhangsan@163.com'
alias Zhangsan 'zhangsan@gmail.com'

那么在使用别名给他发邮件的时候,会同时发给这个别名对应的所有邮箱。


配置好的“.mailrc”文件大致如下:

# ~/.mailrc

set smtp-auth=login
set smtp-use-starttls

# Old format
set smtp='smtp://smtp.domain:587'
set smtp-auth-user='user@domain'
set smtp-auth-password='password'

# New format
#set v15-compat
#set mta='smtp://user:password@smtp.domain:587'

set from='Name<user@domain>'

# Contacts
alias Name 'user@domain'

使用mailx

添加收件人

首先执行mail命令,并传入收件人参数。

mail 'zhangsan@qq.com'

多个收件人用空格分开(即每个参数对应一个收件人)。收件人也可以添加名字,还可以用配置文件里的别名。

mail 'zhangsan@qq.com' 'Lisi<lisi@163.com>' Zhangsan

编写邮件

mailx默认从标准输入读取邮件。在终端输入mail命令并传入收件人参数后按回车,即可进入mail的交互界面。首先会提示输入邮件主题,直接按回车可跳过。接着会自动生成To一行,即收件人。然后就可以写正文。

正文写完后在新的一行按ctrl+D即可结束输入。此时会自动生成邮件标头,并询问是否发送邮件。输入yesy发送邮件,直接按回车重新编辑。

如果邮件发送失败,会在用户根目录生成“dead.letter”文件,包含邮件正文和日期。

[user@host]$ mail zhangsan@qq.com
Subject: Hello
To: zhangsan@qq.com
Hello, Zhangsan.
^D
-------
Envelope contains:
From: Lisi <lisi@qq.com>
To: zhangsan@qq.com
Subject: Hello
Send this message [yes/no, empty: recompose]?

使用管道或重定向

如果使用管道或者输入重定向,mail将不会进入交互页面,而是直接发送邮件。

mail lisi@qq.com < ~/letter
mail lisi@qq.com <<< Hello
echo "$PATH" | mail lisi@qq.com

添加标题

mail -s Hello zhangsan@qq.com

添加附件

mail -a ~/file lisi@qq.com

注意: 一定要把选项加在收件人的前面,否则会把选项解释为收件人。


常用选项解释
-v显示发件过程的详细信息
-a添加附件
-b添加密送
-c添加抄送
-s添加标题
-S作用与配置文件中的set相同
-h查看帮助

更多使用方法请查看mailman手册。

man mail