Richard,

The statement that "the character sequence <CRLF>.<CRLF> IS NOT a line
containing only a period" is wrong.  As you know from your own finite state
machine, the required sequence in the stream is precisely CR-LF-.-CR-LF,
which would be interpreted as

   CR       need-lf
   LF       newline
   .        line-containing-a-period-so-far
   CR       newline-dot-cr-need-lf
   LF       end-of-data

Recognizing .<CRLF> is not sufficient; that implies already being in the
newline state.  It is the initial <CRLF> that puts the dot on a line by
itself by putting your FSM into LINE_STARTING_STATE.

Yes, there is a bug in James because it separates the command and data
streams, and doesn't start the data stream in the NEWLINE state.  And that
should be fixed, although as both Valdis and Keith pointed out, an empty
data set isn't a valid message.

The <CRLF>.<CRLF> is written as a marker for another reason, and that is to
indicate that the entire sequence is the terminator.  That was the point of
apparent disagreement between Keith and Daniel Bernstein.  But they weren't
really disagreeing.  The RFC doesn't require you to store <CRLF> or any
other line terminator at all.  It only requires that whatever you use to
represent line separation internally, you must use <CRLF> to separate lines
in the stream when transmitting the data.  As Keith illustrated, code can
ensure the proper data terminator when delivering the message via SMTP or
POP3.  What you do internally is up to the program.

Right now, as you noted
(http://marc.theaimsgroup.com/?l=james-dev&m=105527214016488&w=2), James
strips the entire <CRLF>.<CRLF> sequence, which is precisely the behavior
that both Valdis ad Keith told you was correct.  Then the POP3 handler will
send the entire <CRLF>.<CRLF> sequence, as would the SMTP transport.

Please note that JavaMail sends an explicit "\r\n.\r\n" to terminate the
data stream.  I believe that you indicated that you plan to use JavaMail.

> I see that this submission makes work for you if you undertake to
> implement and test it.

Anything that deals with RFC compliance deserves special attention, and you
seem to have a different understanding of the RFC, e.g.,

 *   <li>When the end of mail data indicator is recognized in the input
stream,
 *    the CRLF which immediately preceded the period in the indicator is
 *    returned as part of the mail data as the CRLF which concludes the
final
 *    line of mail data, rather than being discarded as part of the end of
mail
 *    data indicator.

None of this is to say that SMTPInputStream might not be useful, but if you
make different assumptions about the RFC, then we would have to adjust the
code in order to use it.

FilteredInputStream is the right thing to extend.  SMTPInputStream
implements read() based upon the real stream, which is the one
non-constructor method that is correct in the code.  The rest are wrong.
For example:

    public void close() throws IOException{
        super.close();
    }

explicitly illustrates a problem that is implicit with all of the inherited
methods.  The code invokes the inherited implementation, often a NO-OP.  It
ought to be delegating to the real stream.  FilteredInputStream provides the
core wrapper for delegation, allowing you to override just those methods
that implement your unique behavior.

        --- Noel


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to