环境是 Amazon EC2,运行 Amazon Linux(类似 Centos),带有 sendmail 8.14.4 和 Cyrus sasl 2.1.23。该机器有一个弹性 IP 地址,它是域名的目标,并且为其设置了反向 DNS。MX 记录指向外部服务器,因此该机器不处理任何传入的互联网电子邮件,只处理传出的电子邮件。对于所有传出的节点外电子邮件,我想使用 TLS 身份验证连接到 smtp.googlemail.com。
关于这种设置有很多教程和文章(本网站及其姊妹网站上有几篇),因为它似乎是处理云中电子邮件的一种相当流行的方式。我一直在阅读我能找到的每一篇文章,尝试不同的方法,并研究 /var/log/maillog。但就我而言,我还是不知所措。这并不是说我不能用 sendmail 发送电子邮件,也不是说我不能通过经过身份验证的 TLS 连接将其发送到 smtp.googlelemail.com:只是我无法让 sendmail 通过这样的连接发送它!我承认我是 sendmail 新手,我知道它以配置困难而闻名,所以我真的花了很多时间。但此时我已经没有线索和想法了。
我在使用 Zend Framework (1.11) 的机器上有一个 php 应用程序,它使用 Zend_Mail_Transport_Smtp。在传输的构造函数中,我指定了 smtp.googlemail.com、端口 587、tls,[电子邮件保护]和密码。该应用程序的电子邮件被快速发送,并带有干净的标题(我还在域的区域文件中添加了包括 google 的 spf txt 记录的 TXT 记录)。
我有另一个直接使用 php mail 的应用程序,而 php mail 依赖于 sendmail。该应用程序还能够在 Amazon Linux AMI 提供的默认 sendmail 配置下发送正常到达的邮件(不通过 googleemail 中继)。但到达邮件中的标题并不那么清晰,至少有一点是 spf 检查有“中性”投诉。所以我并没有陷入没有电子邮件的困境,只是我希望能够使用 sendmail 更可靠地排队发送邮件,以防网站发送大量电子邮件(因为所有 Zend Framework 应用程序的新用户都注册了帐户 :-),我不希望用户看到标题并认为事情可能不太对劲。
因此,这里的目标只是修改现有的 sendmail 配置,以便通过端口 587 tls 连接将外发邮件中继到 googlemail,就像 Zend Framework 应用程序毫无问题地执行的那样。然后我可以修改 Zend Framework 应用程序以使用 sendmail 来获得排队的过载保护。
我认为这有多难呢……
我发现,随着 sendmail 配置的更改,发出的消息总是会卡在 /var/log/maillog 中的以下消息中:
"timeout waiting for input from googlemail-smtp.l.google.com. during client greeting"
然后消息进入 mailq 并留在那里,每次重试都会失败。
以下是直接发送的 sendmail.cf 与修改为通过 google 中继的 sendmail.cf 之间的区别:
# diff sendmail.mc-orig sendmail.mc-new
26c27,30
< dnl define(`SMART_HOST', `smtp.your.provider')dnl
---
> define(`SMART_HOST', `[smtp.googlemail.com]')dnl
> define(`RELAY_MAILER_ARGS', `TCP $h 587')dnl
> define(`ESMTP_MAILER_ARGS', `TCP $h 587')dnl
> FEATURE(authinfo, `Hash -o /etc/mail/authinfo.db')dnl
52,53c56,59
< dnl TRUST_AUTH_MECH(`EXTERNAL DIGEST-MD5 CRAM-MD5 LOGIN PLAIN')dnl
< dnl define(`confAUTH_MECHANISMS', `EXTERNAL GSSAPI DIGEST-MD5 CRAM-MD5 LOGIN PLAIN')dnl
---
> dnl # TRUST_AUTH_MECH(`EXTERNAL DIGEST-MD5 CRAM-MD5 LOGIN PLAIN')dnl
> dnl # define(`confAUTH_MECHANISMS', `EXTERNAL GSSAPI DIGEST-MD5 CRAM-MD5 LOGIN PLAIN')dnl
> TRUST_AUTH_MECH(`PLAIN LOGIN')dnl
> define(`confAUTH_MECHANISMS', `PLAIN LOGIN')dnl
以下是(已清理的)模式 600 root 拥有的 authinfo 文件:
AuthInfo:[smtp.googlemail.com] "U:[email protected]" P:"xyzzy" "M:PLAIN"
我还启动了 saslauthd,并编辑 /usr/lib/sasl2/Sendmail.conf 如下:
pwcheck_method:saslauthd
mech_list: login plain
我没有设置任何证书,因为据我所知,如果 sendmail 仅在传出连接上使用 TLS,则它们不是必需的;事实上,端口 587 连接可以在没有安装证书(或运行 saslauthd)的情况下在 Zend Framework 应用程序中工作。
使用中继 sendmail 配置发送的消息的 29 级邮件日志如下所示:
[31528]: q1F5dYcB031528: [email protected], size=7085, class=0, nrcpts=1, msgid=<[email protected]>, relay=nobody@localhost
[31529]: NOQUEUE: connect from localhost [127.0.0.1]
[31529]: AUTH: available mech=PLAIN LOGIN, allowed mech=PLAIN LOGIN
[31529]: q1F5dYYY031529: Milter: no active filter
[31529]: q1F5dYYY031529: --- 220 name.compute-1.internal ESMTP Sendmail 8.14.4/8.14.4; Wed, 15 Feb 2012 05:39:34 GMT
[31529]: q1F5dYYY031529: <-- EHLO name.compute-1.internal
[31529]: q1F5dYYY031529: --- 250-name.compute-1.internal Hello localhost [127.0.0.1], pleased to meet you
[31529]: q1F5dYYY031529: --- 250-ENHANCEDSTATUSCODES
[31529]: q1F5dYYY031529: --- 250-PIPELINING
[31529]: q1F5dYYY031529: --- 250-8BITMIME
[31529]: q1F5dYYY031529: --- 250-SIZE
[31529]: q1F5dYYY031529: --- 250-DSN
[31529]: q1F5dYYY031529: --- 250-ETRN
[31529]: q1F5dYYY031529: --- 250-AUTH PLAIN LOGIN
[31529]: q1F5dYYY031529: --- 250-DELIVERBY
[31529]: q1F5dYYY031529: --- 250 HELP
[31529]: q1F5dYYY031529: <-- MAIL From:<[email protected]> SIZE=7085 [email protected]
[31529]: ruleset=trust_auth, [email protected], relay=localhost [127.0.0.1], reject=550 5.7.1 <[email protected]>... not authenticated
[31529]: q1F5dYYY031529: --- 250 2.1.0 <[email protected]>... Sender ok
[31529]: q1F5dYYY031529: <-- RCPT To:<[email protected]>
[31529]: q1F5dYYY031529: --- 250 2.1.5 <[email protected]>... Recipient ok
[31529]: q1F5dYYY031529: <-- DATA
[31529]: q1F5dYYY031529: --- 354 Enter mail, end with "." on a line by itself
[31529]: q1F5dYYY031529: from=<[email protected]>, size=7190, class=0, nrcpts=1, msgid=<[email protected]>, proto=ESMTP, daemon=MTA, relay=localhost [127.0.0.1]
[31529]: q1F5dYYY031529: --- 250 2.0.0 q1F5dYYY031529 Message accepted for delivery
[31528]: q1F5dYcB031528: [email protected], [email protected] (99/99), delay=00:00:00, xdelay=00:00:00, mailer=relay, pri=37085, relay=[127.0.0.1] [127.0.0.1], dsn=2.0.0, stat=Sent (q1F5dYYY031529 Message accepted for delivery)
[31529]: q1F5dYYZ031529: <-- QUIT
[31529]: q1F5dYYZ031529: --- 221 2.0.0 name.compute-1.internal closing connection
[31531]: q1F5dYYY031529: SMTP outgoing connect on name.compute-1.interna
[31531]: q1F5dYYY031529: timeout waiting for input from googlemail-smtp.l.google.com. during client greeting
[31531]: q1F5dYYY031529: to=<[email protected]>, delay=00:05:00, xdelay=00:05:00, mailer=relay, pri=127190, relay=googlemail-smtp.l.google.com. [74.125.91.16], dsn=4.0.0, stat=Deferred: Connection timed out with googlemail-smtp.l.google.com.
我确实看到了“ruleset=trust_auth,...未经身份验证”消息,但除了不知道如何修复它之外,我还看到它后面立即出现了一个确定消息,并且日志显示它继续尝试连接到中继,所以我认为这与超时无关......如果我错了,有人可以告诉我如何修复它,那就太好了!
使用未修改的配置发送的邮件的邮件日志,无需中继即可工作(请注意“[电子邮件保护]“实际上是一个带有 Network Solutions 服务器 mx 记录的地址,这就是为什么最后一行有一个用于 netsol.net 主机的 Relay=):
[31425]: q1F5VtLr031425: [email protected], size=6743, class=0, nrcpts=1, msgid=<[email protected]>, relay=nobody@localhost
[31426]: NOQUEUE: connect from localhost [127.0.0.1]
[31426]: AUTH: available mech=PLAIN LOGIN, allowed mech=EXTERNAL GSSAPI KERBEROS_V4 DIGEST-MD5 CRAM-MD5
[31426]: q1F5VuPd031426: Milter: no active filter
[31426]: q1F5VuPd031426: --- 220 name.compute-1.internal ESMTP Sendmail 8.14.4/8.14.4; Wed, 15 Feb 2012 05:31:56 GMT
[31426]: q1F5VuPd031426: <-- EHLO name.compute-1.internal
[31426]: q1F5VuPd031426: --- 250-name.compute-1.internal Hello localhost [127.0.0.1], pleased to meet you
[31426]: q1F5VuPd031426: --- 250-ENHANCEDSTATUSCODES
[31426]: q1F5VuPd031426: --- 250-PIPELINING
[31426]: q1F5VuPd031426: --- 250-8BITMIME
[31426]: q1F5VuPd031426: --- 250-SIZE
[31426]: q1F5VuPd031426: --- 250-DSN
[31426]: q1F5VuPd031426: --- 250-ETRN
[31426]: q1F5VuPd031426: --- 250-DELIVERBY
[31426]: q1F5VuPd031426: --- 250 HELP
[31426]: q1F5VuPd031426: <-- MAIL From:<[email protected]> SIZE=6743
[31426]: q1F5VuPd031426: --- 250 2.1.0 <[email protected]>... Sender ok
[31426]: q1F5VuPd031426: <-- RCPT To:<[email protected]>
[31426]: q1F5VuPd031426: --- 250 2.1.5 <[email protected]>... Recipient ok
[31426]: q1F5VuPd031426: <-- DATA
[31426]: q1F5VuPd031426: --- 354 Enter mail, end with "." on a line by itself
[31426]: q1F5VuPd031426: from=<[email protected]>, size=6848, class=0, nrcpts=1, msgid=<[email protected]>, proto=ESMTP, daemon=MTA, relay=localhost [127.0.0.1]
[31426]: q1F5VuPd031426: --- 250 2.0.0 q1F5VuPd031426 Message accepted for delivery
[31425]: q1F5VtLr031425: [email protected], [email protected] (99/99), delay=00:00:01, xdelay=00:00:00, mailer=relay, pri=36743, relay=[127.0.0.1] [127.0.0.1], dsn=2.0.0, stat=Sent (q1F5VuPd031426 Message accepted for delivery)
[31428]: q1F5VuPd031426: SMTP outgoing connect on name.compute-1.interna
[31426]: q1F5VuPe031426: <-- QUIT
[31426]: q1F5VuPe031426: --- 221 2.0.0 name.compute-1.internal closing connection
[31428]: q1F5VuPd031426: to=<[email protected]>, delay=00:00:00, xdelay=00:00:00, mailer=esmtp, pri=126848, relay=inbound.domain.netsolmail.net. [205.178.149.7], dsn=2.0.0, stat=Sent (OK FB/29-06630-5434B3F4)
[31428]: q1F5VuPd031426: done; delay=00:00:00, ntries=1
以下是我使用 telnet 得到的结果:
# telnet smtp.googlemail.com 587
Trying 74.125.93.16...
Connected to smtp.googlemail.com.
Escape character is '^]'.
220 mx.google.com ESMTP j17sm7987765qaj.9
502 5.5.1 Unrecognized command. j17sm7987765qaj.9
STARTTLS
503 5.5.1 EHLO/HELO first. j17sm7987765qaj.9
EHLO localhost
250-mx.google.com at your service, [nnn.nnn.nnn.nnn]
250-SIZE 35882577
250-8BITMIME
250-STARTTLS
250 ENHANCEDSTATUSCODES
STARTTLS
220 2.0.0 Ready to start TLS
非常感谢您的帮助!
答案1
您的密码声明中似乎有一个小拼写错误,请尝试以下操作:
AuthInfo:googlemail.com "U:[email protected]" "P:xyzzy" "M:PLAIN"
AuthInfo:google.com "U:[email protected]" "P:xyzzy" "M:PLAIN"
不要忘记运行 makemap 并重建 authinfo.db:
makemap hash authinfo < authinfo