带有 GUI 的 Linux 可以直接使用集成的邮件客户端,比如 Thunderbird。但在服务器上,发送邮件需要一些配置,踩一些坑。
邮件系统由三个部分组成:
- Mail User Agent (MUA),发送和接收邮件。
- Mail Transfer Agent (MTA),在计算机之间传输邮件。
- Mail Delivery Agent (MDA),将收到的邮件投递到用户收件箱。
MUA 我使用的是 GNU Mailutils,MTA/MDA 使用的是 Exim4。
下面以网易 163 邮箱为例, 说明怎么在 Debian 上配置 Exim4。
脑瘫的网易把我服务器 IP 屏蔽了,发邮件就报 553 错误:
<= fuck.netease@163.com U=root P=local S=459
H=smtp163.mail.ntes53.netease.com [103.129.252.45] TLS error on connection (recv): The TLS connection was non-properly terminated.
** ?@hotmail.com R=smarthost T=remote_smtp_smarthost H=smtp163.mail.ntes53.netease.com [103.129.252.45] X=TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM:256 CV=yes DN="C=CN,ST=zhejiang,L=hangzhou,O=NetEase (Hangzhou) Network Co.\, Ltd,CN=*.163.com": SMTP error from remote mail server after pipelined MAIL FROM:<fuck.netease@163.com>: 553 authentication is required,163 zwqz-smtp-mta-g5-0,_____wD3_4Uba9BlKz4cCQ--.10347S2 1708157724
<= <> R=1rbFr0-005yuc-14 U=Debian-exim P=local S=2232
Completed
H=smtp163.mail.ntes53.netease.com [103.129.252.45] TLS error on connection (recv): The TLS connection was non-properly terminated.
** fuck.netease@163.com R=smarthost T=remote_smtp_smarthost H=smtp163.mail.ntes53.netease.com [103.129.252.45] X=TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM:256 CV=yes DN="C=CN,ST=zhejiang,L=hangzhou,O=NetEase (Hangzhou) Network Co.\, Ltd,CN=*.163.com": SMTP error from remote mail server after pipelined MAIL FROM:<>: 553 NULL sender is not allowed,163 zwqz-smtp-mta-g5-3,_____wD3_7kda9Bly_Y5Aw--.8516S2 1708157726
Frozen (delivery error message)
换 QQ 邮箱了, 苟曰的腾讯也把我屏蔽了,改 Gmail1 了,但是教程对网易和 QQ 也适用,前提是你的 IP 没被屏蔽。
先安装:
apt install exim4 mailutils
SMTP 端口号
25
25 端口最初作为明文传输的 SMTP 端口,现在经常被 ISP 和云服务器提供商屏蔽。
使用 telnet 检测端口是否可用:
telnet smtp.163.com 25
个人测试发现,家用电信宽带、Vultr 可用,AWS 不可用。
465
465 是非标准的 SMTPS 端口,SMTPS 实际上就是 SMTP + TLS,类似 HTTPS 和 HTTP 的关系。虽然不是标准端口,但确实有一些邮件提供商支持。
587
587 是现在比较通用的标准端口,使用 STARTTLS 加密通信。
从上面我们可以知道,规范的 SMTP 端口为 25,TLS 版本为 465,STARTTLS 版本为 587。
后两者支持加密通信,不过只要服务端有支持,25 端口也可以加密通信,各邮件提供商有不同的实现。
我们可以在 https://esmtp.email/tools/tls/ 检测各端口的加密支持情况。
这个网站的服务出现错误。可以通过下面的 openssl 方式检测。
如果以下命令有 TLS 握手并输出证书,说明支持 TLS:
openssl s_client -connect smtp.gmail.com:465 </dev/null
如果以下命令输出证书,说明支持 STARTTLS:
openssl s_client -connect smtp.gmail.com:587 -starttls smtp </dev/null
Gmail
Gmail 使用标准的 STARTTLS 587 端口,和非标准的 SMTPS 465 端口。
QQ 邮箱
和 Gmail 一样,即 465 支持 SMTPS,587 支持 STARTTLS。
网易邮箱
网易比较坑爹,它确实支持 25、465、587 三个端口,但只有 25 支持 STARTTLS,后两者都是 SMTPS,而它显然没有在官网进行相关说明。
配置 Exim4
以 root 运行:
dpkg-reconfigure exim4-config
这会打开一个 TUI 配置向导。
依次设置:
mail sent by smarthost; received via SMTP or fetchmail
System mail name
保持localhost
IP-addresses to listen on for incoming SMTP connections
保持默认的环回地址Other destinations for which mail is accepted
留空Machines to relay mail for
留空IP address or host name of the outgoing smarthost
填入smtp.gmail.com::587
,注意两个半角冒号,这里使用 STARTTLS,配置比 SMTPS 简单。如果用 QQ 邮箱,就用
smtp.qq.com::587
。如果用网易 163,就用
smtp.163.com::465
,这里的 465 是网易支持的 SMTPS 端口,587 也可以,因为网易这逗比俩端口都是 SMTPS,效果完全一样。Hide local mail name in outgoing mail
如果选择NO
,那么本地发件人不会隐藏(例如 root@localhost 之类),YES
则会改为邮箱地址。
其余选项按喜好配置即可。
需要注意的是,出于安全原因,root 用户不能接收邮件,因此通常设置别名转发到常规用户。
这需要设置 /etc/aliases
,此外还可以设置当常规用户收到邮件时,将邮件投递到某个互联网邮箱,例如:
root: admin
admin: admin@example.com
运行 newaliases
使其生效。当系统收到邮件时(例如 root 用户的 Cron 定时任务),admin@example.com
就可以收到邮件提醒了。
接着在 /etc/exim4/passwd.client
中配置邮箱和密码:
# QQ
smtp.qq.com:username@qq.com:password
# 163
smtp.163.com:username@163.com:password
# Gmail
*.gmail.com:username@gmail.com:password
对于 QQ 和网易,这里的密码都要用授权码,登录 https://mail.qq.com https://mail.163.com 获取。
Gmail 可以使用类似的专用密码 https://support.google.com/accounts/answer/185833。
*.gmail.com
是 Gmail SMTP 服务器包含通配符的域名,如果以下查询有类似的别名(CNAME),要改成匹配的,例如
gmail*.google.com
:
$ host smtp.gmail.com
smtp.gmail.com is an alias for gmail-smtp-msa.l.google.com.
gmail-smtp-msa.l.google.com has address 74.125.127.109
gmail-smtp-msa.l.google.com has address 74.125.127.108
接着配置本地用户与发件邮箱的映射关系。
先在 /etc/hostname
和 /etc/hosts
中查看主机名和 FQDN,或者分别通过 hostname
和 hostname -f
获取。FQDN 常见于机房服务器,家用的一般没有配置,此时 FQDN 与主机名相同。
下面以主机名 myhostname
、FQDN myhostname.mylocaldomain
为例,编辑
/etc/email-addresses
:
root: username@gmail.com
root@localhost: username@gmail.com
root@myhostname: username@gmail.com
root@myhostname.mylocaldomain: username@gmail.com
admin: username@gmail.com
admin@localhost: username@gmail.com
admin@myhostname: username@gmail.com
admin@myhostname.mylocaldomain: username@gmail.com
这一步对于 Gmail 可能不是必须的,因为 Gmail 会自动重写发件人。但是其他邮件就不一定了。
如果在之前 Hide local mail name in outgoing mail
的设置中选择了 YES
,这一步或许可以省略。
首先声明我不是邮件专家。有段时间,Cron 任务发送的邮件如果不设置
MAILFROM
为邮件地址就无法发送,网易和 QQ 都出现过。在一次更新 exim4 后,又把MAILFROM
去掉,结果又可以了。不确定到底是网易或 QQ 的问题还是 exim4 的问题,又或者是别的什么问题。毕竟就像我说的,我不是邮件专家。
***真有邮件专家吗?为什么有这么蛋疼的配置?
更新配置并重启服务:
update-exim4.conf
service exim4 restart
发个邮件试试:
echo "邮件内容" | mail -s "邮件标题" admin@example.com
日志位于 /var/log/exim4/mainlog
。
如果你是 STARTTLS,那应该已经发送成功了。但我的日志里有莫名其妙的报错:
H=smtp.gmail.com [2607:f8b0:400e:c01::6c] TLS error on connection (recv): The TLS connection was non-properly terminated.
原因不明,而且网易、QQ 都有,但确实发送成功了。
SMTPS 还需要接下来的一些配置。
SMTPS 配置2
STARTTLS 请忽略此步骤。
创建 /etc/exim4/exim4.conf.localmacros
:
MAIN_TLS_ENABLE = 1
REMOTE_SMTP_SMARTHOST_HOSTS_REQUIRE_TLS = *
TLS_ON_CONNECT_PORTS = 465
REQUIRE_PROTOCOL = smtps
注意端口 465 与上面一致。
编辑 /etc/exim4/exim4.conf.template
,在
.ifdef REMOTE_SMTP_SMARTHOST_HOSTS_REQUIRE_TLS ... .endif
后(注意 .endif
)添加:
.ifdef REQUIRE_PROTOCOL
protocol = REQUIRE_PROTOCOL
.endif
在 .ifdef MAIN_TLS_ENABLE
后添加:
.ifdef TLS_ON_CONNECT_PORTS
tls_on_connect_ports = TLS_ON_CONNECT_PORTS
.endif
更新配置并重启服务:
update-exim4.conf
service exim4 restart
运行 exim4 -qff
强制发送之前发送失败而暂存的邮件。
这下终于可以了。