在 Linux 上使用 Exim4 发送邮件

2023-05-12 • 更新于 2025-08-19

带有 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,或者分别通过 hostnamehostname -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 强制发送之前发送失败而暂存的邮件。

这下终于可以了。

Linux

本作品根据 署名-非商业性使用-相同方式共享 4.0 国际许可 进行授权。

视频相关的命令和脚本

Homebrew 使用中的一些问题