我试图了解Postfix如何处理一封电子邮件 – 以及SMTP邮件交易的一些细节。 我的短期目标是debugging一个专有的(二进制,封闭源代码)SMTP客户端,但是我首先想到的是,我会研究一个成功的SMTP交易中会发生什么。
我计划在我们的局域网防火墙上阻塞外发SMTP(端口25),所以我configurationPostfix作为内部邮件服务器,以接受来自(原始)本地客户端软件的邮件,该软件只能通过未经validation的SMTP(通过端口25)发送电子邮件。
我通过在master.cf追加-v verbose标志来打开Postfix smtpd进程的debugging过程,如使用Postfix Logs进行故障排除中所述。 然后,我使用Cygwin Mutt和sSMTP (最小的sendmail实现)从我自己的工作站发送了一封电子邮件。
Postfix日志显示,在RCPT TO:行成功处理并且收件人地址可以接受之后,Postfix的smtpd为事务分配了一个队列ID,并以250 OK响应SMTP客户端(sSMTP)。
但是,SMTP客户端发出一个RSET来重置/中止当前邮件事务,而不是发出一个DATA命令,而用一个250 OK回复。
我对这个命令的function做了一些研究,不出所料, 简单邮件传输协议RFC 2821提供了最全面的信息:
该命令指定当前邮件交易将被中止。 任何存储的发送者,收件人和邮件数据必须被丢弃,并清除所有的缓冲区和状态表。 接收者必须发送一个“250 OK”的回复给没有参数的RSET命令。 客户可以随时发出重置命令。 如果在EHLO之后立即发出,在会话中发出EHLO之前,在发送并确认数据结束指示符之后,或在QUIT之前立即发出,它实际上等效于NOOP(即,如果无效)。 由于接收RSET,SMTP服务器不能closures连接; 该操作保留给QUIT(请参阅第4.1.1.10节)。
由于EHLO意味着服务器的一些额外的处理和响应,即使forms语义相同,RSET通常比重新发布该命令更有效率。
在这种情况下,与本规范的意图相反,SMTP服务器可能会收到有关底层TCP连接已closures或重置的指示。 为了保持邮件系统的健壮性,SMTP服务器应该为这种情况做好准备,并且应该把它看作是在连接消失之前收到了一个QUIT。
上述情况都发生在一秒钟的时间内,所以暂停时间不应该有任何问题。
在下一秒,客户端发送另一个RSET但客户端然后等待整整10秒,然后重新启动MAIL FROM: , RCPT TO:但这次它通过并发出DATA命令,交易完成(所有在同一秒内根据到日志)。
本质上,我想知道为什么SMTP客户端会通过发出RSET命令而不是DATA命令来中断自己的事务。
笔记:
我可以编辑这个问题,包括从邮件日志文件中提取,但使用-vdebugging,他们是非常详细的,我不想用不相关的数据fireshose压倒人。
我search了sSMTP源代码,但是我没有发现任何提及的RSET 。
我一直在想,为什么SMTP客户端会通过发出RSET命令而不是DATA命令来中断自己的事务。 简单的答案是,它不会; 这是由反病毒软件拦截的SMTP连接的症状。
我在sSMTP的configuration中启用了Debug选项,但是我花了一些时间来弄清楚如何在Cygwin中安装和configurationsyslog,以便将来自Cygwin进程的消息logging到/var/log/messages而不是Windows事件查看器。
但是,它只logging了第一个MAIL FROM:和RCPT TO:命令; 没有迹象表明这些命令被多次发送 – 或者sSMTP曾经发送过一个RSET命令。
正如我的问题所述,我已经检查了sSMTP源代码,但没有代码发送RSET命令。
用户masegaloehbuild议防病毒软件可能正在修改SMTP数据包 – 他是对的:我暂时在我的计算机上禁用了Symantec Endpoint Protection ,并且SMTP事务处理正常进行。
重新启用Symantec Endpoint Protection之后,我使用Windows Sysinternals中的TCPView实用程序监视TCP连接,我可以看到Symantec ccSvcHst.exe进程正在代理目标端口为25的所有TCP通信。
我telnet到邮件服务器上的端口25(netcat将无法正常工作,可能是由于赛门铁克拦截)通过手动inputSMTP命令发送testing邮件。 同时,运行sudo tail -F /var/log/maillog同时监视SMTP服务器正在查看的sudo tail -F /var/log/maillog ,同时打开另一个terminal窗口,并通过与邮件主机的SSH连接打开。
赛门铁克代理进行的拦截是微妙的。 从邮件客户端的angular度来看,很less有迹象表明它不直接与SMTP服务器通话。 大多数命令都会在发送时通过邮件服务器传递,并且响应是您所期望的。 直到我inputDATA命令,Symantec代理才开始改变:它的回应是:
354 Please start mail input.
这似乎是正常的,但实际上,我的Postfix服务器的响应应该是
354 End data with <CR><LF>.<CR><LF>
另外:它实际上并没有把DATA命令传递给Postfix,直到我完成了消息体并且跟着一个QUIT 。
注意:在inputtesting消息的内容时,Symantec代理通过发出NOOP命令保持其与Postfix服务器的连接。
我在我的问题中提到,我的最终目标是对我的组织使用的专有(二进制,封闭源代码)邮件客户端进行故障排除。 我发现这个客户端实在是太麻烦了:它发送了一个无效的HELO命令(没有任何主机名),然后简单地放弃并在SMTP服务器通知其语法错误后退出QUIT – 尽pipe我已经configurationPostfix不需要HELO (有效或其他)。
我解决了这个问题,安装了一个新的CentOS 7服务器,它附带了一个Postfix版本,可以完全禁用后缀HELO检查 (类似于MS Exchange如何忽略无效的HELO命令)。
我也一直想知道在SMTP交易中使用RSET的一般用法,并且在原来的RFC 821 for SMTP中find了以下内容:
该命令指定当前的邮件交易将被中止。 任何存储的发件人,收件人和邮件数据必须被丢弃,并清除所有缓冲区和状态表。 接收者必须发送OK回复。
如果事实certificate收件人的电子邮件地址是不存在的用户,将使用RSET 。 以下SMTP事务是中止SMTP事务scheme的示例。
R: 220 MIT-Multics.ARPA Simple Mail Transfer Service Ready S: HELO ISI-VAXA.ARPA R: 250 MIT-Multics.ARPA S: MAIL FROM:<[email protected]> R: 250 OK S: RCPT TO:<[email protected]> R: 250 OK S: RCPT TO:<[email protected]> R: 550 No such user here S: RSET R: 250 OK S: QUIT R: 221 MIT-Multics.ARPA Service closing transmission channel