I’m trying to understand how exactly an email is processed by Postfix – and some of the finer details of SMTP mail transactions. My short-term goal is to debug a proprietary (binary, closed source) SMTP client but I first thought I’d examine what happens in a successful SMTP transaction.
I plan on blocking outgoing SMTP (port 25) at our LAN firewall so I configured Postfix as an internal mail server to accept mails from (primitive) local client software which can only send email via non-authenticated SMTP (over Port 25).
I turned on debugging of the Postfix smtpd
process by appending the -v
verbose flag in master.cf
as described in Troubleshooting with Postfix Logs. I then sent an email from my own workstation using Cygwin Mutt with sSMTP (a minimal implementation of sendmail
).
The Postfix logs show that after the RCPT TO:
line was successfully processed and the recipient address was acceptable, Postfix’s smtpd
assigned the transaction a Queue ID and responded to the SMTP client (sSMTP) with a 250 OK
.
However, instead of issuing a DATA
command, the SMTP client issued a RSET
to reset / abort the current mail transaction and Postfix replied with a 250 OK
.
I did some research on what this command command does and unsurprisingly, the Simple Mail Transfer Protocol, RFC 2821 provided the most comprehensive information:
This command specifies that the current mail transaction will be aborted. Any stored sender, recipients, and mail data MUST be discarded, and all buffers and state tables cleared. The receiver MUST send a "250 OK" reply to a RSET command with no arguments. A reset command may be issued by the client at any time. It is effectively equivalent to a NOOP (i.e., if has no effect) if issued immediately after EHLO, before EHLO is issued in the session, after an end-of-data indicator has been sent and acknowledged, or immediately before a QUIT. An SMTP server MUST NOT close the connection as the result of receiving a RSET; that action is reserved for QUIT (see section 4.1.1.10).
Since EHLO implies some additional processing and response by the server, RSET will normally be more efficient than reissuing that command, even though the formal semantics are the same.
There are circumstances, contrary to the intent of this specification, in which an SMTP server may receive an indication that the underlying TCP connection has been closed or reset. To preserve the robustness of the mail system, SMTP servers SHOULD be prepared for this condition and SHOULD treat it as if a QUIT had been received before the connection disappeared.
All of the above happened within the space of a second so there shouldn’t be any issues with time-outs.
In the next second, the client sent another RSET
but the client then waited a whole 10s before restarting with MAIL FROM:
, RCPT TO:
but this time it follows through and issues the DATA
command and the transaction completes (all within the same second according to the logs).
Essentially, I’m wondering why a SMTP client would interrupt its own transaction by issuing RSET
commands instead of a DATA
command.
Notes:
I can edit the question to include extract from the mail log file but with the
-v
debugging, they’re very verbose and I don’t want to overwhelm people with a firehose of irrelevant data.I searched the sSMTP source code but I didn’t find any mention of
RSET
.