users@javamail.java.net

Re: Issue with TLS

From: Bill Shannon <bill.shannon_at_sun.com>
Date: Fri, 07 Jan 2011 10:54:52 -0800

Gilles Gaillard wrote on 01/ 7/11 02:33 AM:
> Le 06/01/2011 23:24, Bill Shannon a écrit :
>> Gilles Gaillard wrote on 01/06/2011 12:40 PM:
>>> Hi,
>>>
>>> We're using javamail in an application that occasionally needs to send e-mails
>>> and it's usually just working fine.
>>>
>>> However, there's one case where connecting to the smtp server fails with
>>> javamail although sending the mail succeeds with another app (EmailTest.exe)
>>>
>>> Debugging the situation with wireShark shows the following steps - with the
>>> successful application (c is the client, s is the server):
>>>
>>> 1. c -> connect
>>> 2. s <- 220
>>> 3. c -> EHLO
>>> 4. s <- 250-mx.., 250-SIZE, 250-8BIMIME, 250-STARTTLS, 150 ENHANCEDSTATUSCODES
>>> 5. c -> STARTTLS
>>> 6. s <- 220 2.0.0 Ready to start TLS
>>> Here the SSL handshake and key exchange: Note that seems incomplete.
>>> 7. c -> Client Hello
>>> 8. s <- Server Hello
>>> 9. s <- Certificate. Server Hello Done.
>>> 10. c -> Client Key exchange
>>> 11. c -> Change cipher spec, Encrypted Handshake message
>>> 12. s <- 220 mx-..
>>> 13. c -> EHLO
>>> 14. s <- 250-mx.., 250-SIZE, 250-8BIMIME, 250-STARTTLS, 150 ENHANCEDSTATUSCODES
>>> 15. c -> STARTTLS
>>> 16. s <- 220 2.0.0 Ready to start TLS
>>> Then the SSL handshake again
>>> 17. c -> Client Hello
>>> 18. s <- Server Hello
>>> 19. s <- Certificate. Server Hello Done.
>>> 20. c -> Client Key exchange
>>> 21. c -> Change cipher spec, Encrypted Handshake message
>>> 22. s <- Change cipher spec, Encrypted Handshake message
>>> 23. Then the data transmission.
>>>
>>> Connecting to the same mail server with javamail gives the following:
>>> - connecting from the same machine:
>>> at step 15, instead of starting the TLSS, javamail just send 'mail from' which
>>> causes the server to refuse.
>>> c -> MAIL FROM:<xxx_at_yy>
>>> s <- 539 5.7.0 Must issue a STARTTLS first
>>> c -> RSET
>>> - connecting from another machine: works fine. Steps 12 to 21 do not show.
>>>
>>> My current guessing is that the TLS handshake failed which the successful
>>> application worked around by restarting the 'protocol connection'.
>>> I imagine that would be equivalent to calling again
>>> SMTPTransport.protocolConnect another time.
>>> On the other hand it seems that javamail just goes on without detecting the
>>> issue in the SSL handshake.
>>
>> If JavaMail is never sending the STARTTLS command, it's probably because
>> you haven't enabled STARTTLS support by setting the appropriate property.
>>
>> If you're always sending email to the same server, and some times it's
>> correctly using STARTTLS, then you should look for some error in your
>> application logic related to how you manage the Properties object that
>> the Session is initialized with.
>>
>> Also, make sure you're using Session.getInstance instead of
>> Session.getDefaultInstance; the peculiar semantics of the latter can
>> often be the source of problems such as this.
>
> Thanks for replying.
>
> Javamail did actually send the STARTTLS (step 5 above).

Ah, I see. Sorry, I didn't read carefully the first time and I failed to
notice that STARTTLS is being done *twice*.

> The initialization code is pretty simple, always set "mail.smtp.starttls.required",
> uses Session.getInstance(props), get the Transport and then connect with host,
> port,
> login and passwd.
>
> My analysis is that in the above steps, at step 12 the server stopped the ssl
> handshake
> and resent a 220 which is ignored by javamail that just goes on with the usual
> EHLO as
> if TLS was completely established.

 From the trace it looks like you're actually establishing two connections
with the server.

Are you calling transport.connect followed by transport.send? Note that "send"
is a static method that doesn't use the transport connection you already
created. Instead it creates its own connection. Use the sendMessage method
(see the FAQ).