davidmoten / subethasmtp

SubEtha SMTP is a Java library for receiving SMTP mail

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Should BdatInputStream send 250 to the SMTP sender after BDAT chuck has been received?

maverikki opened this issue · comments

I am using SubEthaSMTP with Microsoft Exchange. When I receive email from Exchange, it sends it in a BDAT stream. After the stream has finished the BDatInputStream sends 250 before I can send RejectException from my MessageHandler data block. I think the 250 OK should not be sent after the final byte has been read.

My code is basically:

public class SmtpMessageHandler implements MessageHandler {
  @Override
  public String data(InputStream data) throws RejectException, IOException {
    mimeMessage = new MimeMessage(session, data);
    messageSize = mimeMessage.getSize();
    Thread.sleep(200);
    throw new RejectException("Test, message size " + messageSize);
}

On Wireshark I can see SubEtha Respond with 250 OK last chunk immediately.
Then Exchange sends Quit.
Then Subetha responds again with 250 OK
And only then Subetha sends the 554 Error

.50 is running SubEtha. .48 is running Exchange

image

Commenting out line 46 in the BdatInputStream.java seems to fix this, but is there a reason why the line is there?
The line in question: session.sendResponse("250 Message OK, " + size + " bytes received (last chunk)");

Thanks, I'll have a look

From SMTP BDAT specfication https://datatracker.ietf.org/doc/html/rfc3030:

After all MAIL and RCPT responses are collected and processed, the
message is sent using a series of BDAT commands. The BDAT command
takes one required argument, the exact length of the data segment in
octets. The message data is sent immediately after the trailing
of the BDAT command line. Once the receiver-SMTP receives the
specified number of octets, it will return a 250 reply code.

The optional LAST parameter on the BDAT command indicates that this
is the last chunk of message data to be sent. The last BDAT command
MAY have a byte-count of zero indicating there is no additional data
to be sent. Any BDAT command sent after the BDAT LAST is illegal and
MUST be replied to with a 503 "Bad sequence of commands" reply code.
The state resulting from this error is indeterminate. A RSET command
MUST be sent to clear the transaction before continuing.

A 250 response MUST be sent to each successful BDAT data block within
a mail transaction. If a failure occurs after a BDAT command is
received, the receiver-SMTP MUST accept and discard the associated
message data before sending the appropriate 5XX or 4XX code. If a
5XX or 4XX code is received by the sender-SMTP in response to a BDAT
chunk, the transaction should be considered failed and the sender-
SMTP MUST NOT send any additional BDAT segments. If the receiver-
SMTP has declared support for command pipelining [PIPE], the receiver
SMTP MUST be prepared to accept and discard additional BDAT chunks
already in the pipeline after the failed BDAT.

Looks like we don't need to acknowledge the BDATA command with the LAST parameter so I'll apply the change you suggest.

I think the 250 OK should not be sent after the final byte has been read.

It does seem fair that you have the chance to reject the transaction (that is delay response till you've handled the data as you see fit). Would you like to see this done as well (will take quite a lot of rework)?

Thanks, I also read the specification and I think this one is ok as it is. I could also always see the last chunk message twice on the Wireshark capture, so maybe there was something weird in the BDAT LAST case. I will do some more testing with another email server to see how they handle the SMTP session.

Hi, I completely forgot about this. I have been using a version with this change with hMailServer for a while now and everything has been fine. What if your process of merging the changes and making new releases? It would always be nicer to use a real version instead of something I built myself.

Yep, I'll make a PR with the commit that I made to the bdat-fix branch.

#83 has been merged but check it if you like. I'll build a new release shortly.

6.0.2 is on Maven Central now

Closing this issue, reopen if something else crops up