自建邮局排查指南

自建邮局能发不能收,是很常见的坑。发信和收信走的是两条完全不同的链路:发信靠出站 SMTP,收信则依赖 MX 记录、入站 25 端口、本地域名配置,以及客户端通过 IMAP / POP3 取信的能力——任何一环出问题都会导致收信失败。

不管你是"别人发给我的邮件根本收不到",还是"服务器上明明有邮件,客户端却看不到",都可以按本文的顺序逐层排查,比一上来就翻配置文件更高效。

先判断故障发生在哪一层

在动手之前,先把问题分成下面三类:

  1. 外部发件人根本投递不进来 重点检查 MXA/AAAA、公网 25 端口、反向解析和服务器是否真的在监听。
  2. 服务器已经收到了邮件,但客户端读不到 重点检查 IMAP / POP3 监听、TLS 证书、账号认证、邮箱配额和客户端配置。
  3. 手动配置能用,但自动配置失败 重点检查自动发现接口、SRV 记录,以及客户端的自动发现机制。

如果你不确定属于哪一类,最简单的办法是同时做两件事:

  • 用外部邮箱(如 Gmail、Outlook)给你的域名发一封测试邮件。
  • 立即查看服务器日志,确认这封邮件有没有到达。

只要日志里完全没有新的入站记录,问题大概率还停留在 DNS、网络或 25 端口这一层。

1. 先检查 DNS 解析

收信链路里,DNS 是第一关。MX 错了,后面的配置再正确也没用。

I. 检查 MX 记录

dig example.com MX

需要确认两点:

  • MX 记录确实存在。
  • MX 指向的是一个域名,而不是 IP 地址。

例如下面这种写法才是正常的:

example.com.  300  IN  MX  10 mail.example.com.

II. 检查 MX 指向的 A/AAAA 记录

dig mail.example.com A
dig mail.example.com AAAA

MX 指向的主机名必须能继续解析到可访问的公网地址。

这里有一个很常见的坑:AAAA 记录存在,但服务器其实没有正确配置 IPv6。这样一来,部分发件方会优先走 IPv6 投递,结果表现为“有些邮件能收到,有些收不到”。如果你暂时不打算支持 IPv6,宁可先去掉错误的 AAAA 记录,也不要让它半通不通。

III. 检查 PTR 反向解析

dig -x <服务器公网IP>

虽然 PTR 错误不一定会导致完全无法收信,但它会显著影响投递质量,某些服务商也会更严格地对待这类主机。理想情况是:

  • 公网 IP 的 PTR 指回你的邮件主机名,例如 mail.example.com
  • 这个主机名再正向解析回同一个 IP

IV. 注意 DNS 生效延迟和本地缓存

如果你刚改过记录,别忘了考虑两件事:

  • 解析未完全传播,外部仍在命中旧记录
  • 本地机器或路由器缓存了旧结果

可以额外做一次查询验证:

dig +short example.com MX
dig +short mail.example.com A
dig +short mail.example.com AAAA

2. 确认入站端口是否真的可达

“发信正常”经常会让人误以为网络没问题,但这只能说明出站路径大致可用,并不能证明别人可以从公网连到你的服务器。

I. 优先测试 SMTP 25 端口

如果外部邮件根本投递不进来,最应该先查的是 25 端口:

nc -zv -w 3 mail.example.com 25

如果你还要顺手检查客户端收信相关端口,可以一起测:

nc -zv -w 3 mail.example.com 143
nc -zv -w 3 mail.example.com 993
nc -zv -w 3 mail.example.com 110
nc -zv -w 3 mail.example.com 995
nc -zv -w 3 mail.example.com 465
nc -zv -w 3 mail.example.com 587

II. 常见邮件端口对照

服务 端口 用途 加密方式
SMTP 25 服务器间收发信 无/STARTTLS
SMTP 587 客户端提交发信 STARTTLS
SMTPS 465 客户端提交发信 SSL/TLS
IMAP 143 客户端收信 STARTTLS
IMAPS 993 客户端收信 SSL/TLS
POP3 110 客户端收信 STARTTLS
POP3S 995 客户端收信 SSL/TLS

III. 不要只看服务器防火墙

端口不通时,问题可能出在下面任意一层:

  • 服务器本机防火墙没有放行
  • 云厂商安全组或网络 ACL 没开
  • 路由器或 NAT 没有做端口转发
  • 宿主机到容器的端口映射不正确
  • 上游运营商或机房对邮件端口有限制

如果你部署在家宽或某些云平台上,25 端口尤其值得重点确认。有些环境不是“服务没启动”,而是上游直接不让你接这类连接。

IV. 其他检测方式

nmap -p 25,110,143,465,587,993,995 mail.example.com
curl -v --connect-timeout 3 telnet://mail.example.com:25

如果你希望完全不依赖外部工具,也可以用 Bash 自带的 TCP 探测:

(echo >/dev/tcp/mail.example.com/25) && echo "开放" || echo "关闭"

3. 检查 TLS 和证书

如果问题表现为“服务器能收到邮件,但客户端连 IMAP/POP3 总是报证书错误、握手失败或一直转圈”,那下一步就该看 TLS。

I. 测试隐式 TLS 端口

openssl s_client -connect mail.example.com:993 -servername mail.example.com
openssl s_client -connect mail.example.com:465 -servername mail.example.com
openssl s_client -connect mail.example.com:995 -servername mail.example.com

II. 测试 STARTTLS 端口

openssl s_client -connect mail.example.com:143 -servername mail.example.com -starttls imap
openssl s_client -connect mail.example.com:587 -servername mail.example.com -starttls smtp
openssl s_client -connect mail.example.com:110 -servername mail.example.com -starttls pop3

注意openssl s_client -starttls 的协议协商并不总是可靠的——有些服务器在 STARTTLS 之前要求先完成认证或特定交互,openssl 做不到这些,就会导致测试失败,但服务器本身其实没问题。如果隐式 TLS 端口(993/465/995)全部通过,而 STARTTLS 端口全部失败,大概率是测试工具的局限,而不是服务器配置有误。大多数客户端默认使用隐式 TLS 连接,所以只要隐式 TLS 正常,收信一般不受影响。

III. 快速提取证书信息

openssl s_client -connect mail.example.com:993 -servername mail.example.com 2>/dev/null | openssl x509 -noout -subject -issuer -dates

IV. 常见证书问题

最常见的几类问题通常是:

  • 证书是自签的,客户端默认不信任
  • 证书上的域名与客户端连接用的域名不一致
  • 证书已经过期
  • 服务端口根本没有正确启用 TLS,输出里会看到 no peer certificate available

要注意一点:SMTP 25 端口缺少 TLS 并不一定会让收信完全失败,但 IMAP / POP3 端口的 TLS 配置错误,往往会直接表现为“明明有邮件,但客户端就是登录不了”。

4. 检查邮件服务本身

如果 DNS 和端口都没问题,接下来就该确认邮件服务本身有没有正确对外提供“收信”和“取信”能力。

I. 确认服务监听在公网地址

先看相关端口到底监听在什么地址上:

ss -tlnp | rg ':(25|110|143|465|587|993|995)\\b'

正常情况下,至少应该看到服务监听在 0.0.0.0[::] 或你的公网可达地址上。 如果只监听在 127.0.0.1::1,那外部客户端当然连不上。

II. 确认服务器愿意接收你的域名

这是另一个非常常见的配置问题:服务启动了,端口也通,但服务器根本没把 example.com 当作本地域名处理。

不同邮件服务器的叫法不完全一样,但你需要检查的本质都是同一件事:

  • 你的域名是否被列入本地投递域名
  • 该域名下的邮箱账号或别名是否真实存在
  • 邮件到达后是否有正确的投递目标

如果这一层配置有误,常见表现是:

  • 外部会收到 relay access denied
  • 服务器把发给你自己的邮件当成要继续转发的外部邮件
  • 日志里能看到邮件进来,但最终被拒收或落到了错误的位置

III. 检查账号、配额和本地存储

如果外部投递已经成功,但客户端看不到邮件,还要继续排查:

  • 该账号是否真的存在
  • 邮箱是否已满
  • 邮件是否被投递到了意料之外的文件夹
  • 是否有过滤规则把邮件转移、归档或删除了

IV. 留意封禁和限速策略

很多人排查时只盯着主配置,却忘了还有额外的访问控制层,例如:

  • fail2ban 或类似封禁工具
  • 服务自身的 IP 黑名单或灰名单
  • 登录失败后的限速或临时封锁

这类问题特别像“偶发故障”:同一套配置,在一台设备上能连,在另一台设备上又不行。

V. 直接看日志

日志通常比猜配置更快。无论你是系统服务、容器还是面板部署,都应该优先找到最近几十行日志:

journalctl -u <你的邮件服务> --no-pager -n 100
docker logs <你的邮件容器> --tail 100

重点关注这些关键词:

  • connect
  • reject
  • relay
  • tls
  • certificate
  • authentication failed
  • timeout
  • rate limit
  • mailbox full

如果你在外部发出测试邮件的同时盯着日志,往往几分钟内就能判断问题是在“进不来”还是“进来了但处理失败”。

5. 检查客户端自动发现

如果手动填服务器地址和端口可以正常收发,但 Thunderbird、Outlook 或手机系统的自动配置失败,那问题通常不在收信本身,而在“自动发现”这层。

I. 常见自动发现方式

不同客户端会使用不同机制,常见的有:

  • Autoconfig 例如 https://autoconfig.example.com/mail/config-v1.1.xml
  • Autodiscover 例如 https://autodiscover.example.com/autodiscover/autodiscover.xml
  • DNS SRV 记录 例如 _imaps._tcp_submission._tcp
  • 猜测常见主机名 例如 mail.example.comimap.example.comsmtp.example.com

II. 可以先直接验证相关地址

curl -v "https://autoconfig.example.com/mail/config-v1.1.xml"
curl -v "https://autodiscover.example.com/autodiscover/autodiscover.xml"

如果这些地址根本打不开、证书不对,或者返回内容不是客户端期望的格式,那么自动配置自然会失败。

III. 常见 SRV 记录示例

记录类型 主机记录 记录值
SRV _imaps._tcp 0 1 993 mail.example.com.
SRV _imap._tcp 0 1 143 mail.example.com.
SRV _submissions._tcp 0 1 465 mail.example.com.
SRV _submission._tcp 0 1 587 mail.example.com.
SRV _pop3s._tcp 0 1 995 mail.example.com.

IV. 手动配置往往是最快的验证方式

如果你只想先确认服务本身是否可用,直接手动配置通常更高效:

项目 服务器 端口 安全
收信 IMAP mail.example.com 993 SSL/TLS
发信 SMTP mail.example.com 465 SSL/TLS

只要手动配置能通,就说明“邮件服务”本身大概率没问题,剩下只是自动发现资料没补齐。

6. 排除本地网络和缓存干扰

有些“收信异常”其实不是服务器坏了,而是你当前网络环境在捣乱。

I. 先换一个网络再试

如果出现下面这些现象,很值得怀疑本地网络或运营商干扰:

  • nc 能连上,但 TLS 握手异常中断
  • 同一账号在手机热点下正常,在公司或家里网络下异常
  • 只有个别设备、个别网络环境出问题

最简单的验证方式是:

  • 用手机热点再试一次
  • 开 VPN 再试一次
  • 换另一台设备再试一次

II. 必要时抓包看连接有没有到服务器

如果你有服务器权限,可以直接在服务端抓包确认客户端流量是否到达:

sudo tcpdump -i any -n 'port 25 or port 993'

观察思路很简单:

  • 客户端连接根本没到服务器,优先查 DNS、路由、端口映射
  • 连接到了服务器,但服务没有回应,优先查服务状态和 TLS
  • 连接到了服务器,服务器立刻拒绝,优先查认证、封禁和访问策略

III. 清理本地缓存

改过 DNS 或证书后,还可以顺手排查一下本地缓存:

sudo resolvectl flush-caches
resolvectl query mail.example.com
grep example /etc/hosts

如果 hosts 里残留了旧记录,或者系统还在使用旧解析结果,排查方向很容易被带偏。

7. 用命令行做一次最小化验证

图形客户端的信息往往不够直接。怀疑客户端本身有问题时,可以用命令行做一次最小验证。

I. 测试 IMAP 登录

curl -v --url "imaps://mail.example.com/INBOX" --user "[email protected]:密码"

只要这一步能成功列出或访问邮箱内容,说明至少下面几层已经基本打通:

  • 域名解析
  • 993 端口连通
  • TLS 握手正常
  • 用户名和密码正确
  • IMAP 服务可用

II. 手动与 IMAP 服务交互

openssl s_client -connect mail.example.com:993 -servername mail.example.com -quiet

连接后可以手工输入:

a1 LOGIN [email protected] 密码
a2 LIST "" "*"
a3 SELECT INBOX
a4 LOGOUT

这种方式虽然原始,但在排查“到底是客户端问题,还是服务器问题”时非常直接。