我有一个客户,他使用外部邮件服务器记录和过滤他们的入站电子邮件,然后将其传递到他们的主要邮件系统(即 Office365)。外部服务器正在运行 Sendmail,以前在 Debian 上运行,现在在 Ubuntu(亚马逊版本)上运行。
操作系统(和托管)的变更也导致 Sendmail 版本升级,从旧服务器(确实很老旧)上的 8.14.4 升级到新服务器上的 8.15.2。不幸的是,这也导致行为略有变化,我很难确定这是由标志还是其他配置设置控制的。
外部服务器会对垃圾邮件和其他垃圾进行一些过滤,在更换服务器之前,所有剩余的邮件都已成功发送到 O365。(其中一些邮件在那里被标记为垃圾邮件,但至少都到达了他们的服务器。)现在情况已经不同了。大多数被扣留而未送达的邮件都是从他们的邮件中退回的邮件,但他们确实需要查看这些邮件来清理他们的列表。
似乎未送达的邮件是邮件标头中名称不完全合格的邮件。它们不是来自到达外部服务器的跃点(例如,我们会在该阶段拒绝不存在的域),而是来自邮件旅程的早期。因此,我们可能会看到类似这样的标头
Received: from EXTERNAL.com (EXTERNAL.com [NN.NN.NN.NN])
by OUR.SERVER (8.15.2/8.15.2/Debian-10) with ESMTP id xELIDED
for <[email protected]>; Sat, 11 May 2019 10:49:17 GMT
Received: from EXTERNAL.com.local (EXTERNAL.com [NN.NN.NN.NN])
by EXTERNAL.com (8.16.0.22/8.16.0.22) with ESMTPS id xELIDED
(version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT)
for <[email protected]>; Sat, 11 May 2019 18:49:15 +0800
-- 是 .local 标头导致了问题。但是我们在邮件到达在服务器上,只有当它树叶服务器转向 Office365。此时,我们看到
EXTERNAL.com.local: Name server timeout
交易结束时
timeout writing message to OURDOMAIN-com.mail.protection.outlook.com.
<[email protected]>... Deferred: Name server: OURDOMAIN-com.mail.protection.outlook.com.: host name lookup failure
Closing connection to OURDOMAIN-com.mail.protection.outlook.com.
即最终的失败消息表明无法连接到 O365。事实并非如此,因为连接已成功启动,与 O365 服务器的其他连接也已成功连接(这是一个中等流量的服务器)。
Sendmail 日志和 tcpdump 显示 SMTP 连接的初始部分运行良好。在 DATA 部分,传输标头,然后由于无法查找与连接不直接相关的主机名而终止连接(它从未传输过电子邮件的任何正文)。
除了标头中存在无法解析的主机名的情况外,我还看到过这种情况发生在电子邮件中,其中回复被设置为不存在的域,因此无法解析。(很可能是垃圾邮件,但这不是真正的问题。)
我查看了 Sendmail 相关版本的更改日志,没有发现任何明显相关的内容;我还花了一点时间研究源代码。tcpdump 的日志显示,连接在我们这边被终止,而不是微软的——他们那边的一名工程师试图帮助我们,但是,由于这些邮件从未成功连接,他们很难发现发生了什么。其他所有东西的 DNS 查找似乎都运行正常。
如果有人知道在哪里可以找到“不要尝试查找不相关的主机名”的配置,我洗耳恭听。这些不是我们的配置错误!
提前致谢。
编辑添加一些 strace 日志:
connect(9, {sa_family=AF_UNIX, sun_path="/dev/log"}, 110) = 0
sendto(9, "<22>May 15 09:52:20 sendmail[135"..., 176, MSG_NOSIGNAL, NULL, 0) = 176
>>> EHLO our.server.name
250-VE1EUR02FT009.mail.protection.outlook.com Hello [NN.NN.NN.NN]
250-SIZE 157286400
250-PIPELINING
250-DSN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250-BINARYMIME
250-CHUNKING
250 SMTPUTF8
>>> MAIL From:<> SIZE=23108
250 2.1.0 Sender OK
>>> RCPT To:<[email protected]>
>>> DATA
250 2.1.5 Recipient OK
354 Start mail input; end with <CRLF>.<CRLF>
socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 12
connect(12, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.53")}, 16) = 0
sendto(12, "R>\1\0\0\1\0\0\0\0\0\1\2the\4dodgy\3com\5local\0\0"..., 46, MSG_NOSIGNAL, NULL, 0) = 46
recvfrom(12, "R>\201\202\0\1\0\0\0\0\0\1\the\4dodgy\3com\5local\0\0"..., 8192, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.53")}, [28->16]) = 46
[repeats six more times]
the.dodgy.com.local: Name server timeout
timeout writing message to OURDOMAIN-com.mail.protection.outlook.com.
sendto(9, "<18>May 15 09:52:20 sendmail[135"..., 130, MSG_NOSIGNAL, NULL, 0) = 130
<[email protected]>... Deferred: Name server: OURDOMAIN-com.mail.protection.outlook.com.: host name lookup failure
sendto(9, "<22>May 15 09:52:20 sendmail[135"..., 296, MSG_NOSIGNAL, NULL, 0) = 296
Closing connection to OURDOMAIN-com.mail.protection.outlook.com.
+++ exited with 70 +++
因此查找失败是打开的那个the.dodgy.com.local
(在之前的清理日志中提到EXTERNAL.com.local
,但我想在这里保留函数调用的结构),但 Sendmail 报告的那个是当时连接到的服务器上的查找失败。它不是正在做查找确实发生了,它就不会失败。
编辑(2):更改 DNS 解析器没有帮助。
答案1
我看到了一个链接为什么 sendmail 会在 To: 标头中为非收件人的域调用 dns_getcanonname?在侧边栏中,结果发现它确实有解决方案。我们需要添加FEATURE(nocanonify', canonify_hosts')
sendmail.mc,这似乎已经停止了额外的查找;之前无法投递的邮件现在已经投递了。