Search code examples
javajakarta-mailsmtp-auth

Why does connecting with credentials over SMTP not perform authentication?


While trying to build an E-Mail client using JavaFX and Jakarta Mail, I wanted to implement a connection test to make sure that the credentials the user entered actually work for both the IMAP and SMTP server they specified. I have no problem with validating the IMAP credentials so far.

For my SMTP validation code, I searched the internet for a feasible approach, came across this question and implemented it in my project as follows:

public static boolean canConnectViaSmtp (String host, int port, String username, String password) {
        Properties properties = new Properties ();
        properties.put ("mail.smtp.auth", true);
        properties.put ("mail.smtp.starttls.enable", true);
        properties.put ("mail.debug", true);

        Session session = Session.getInstance (properties, null);
        session.setDebug (true);
        session.setDebugOut (System.out);
        Transport transport;

        try {
            transport = session.getTransport ("smtp");
        } catch (NoSuchProviderException e) {
            System.err.println ("Could not connect to smtp://" + host + ":" + port + ", Jakarta Mail is missing the SMTP provider");
            e.printStackTrace ();
            return false;
        }

        try {
            transport.connect (host, port, username, password);
            transport.close ();
        } catch (AuthenticationFailedException e) {
            System.err.println ("Credentials for smtp://" + host + ":" + port + " invalid");
            return false;
        } catch (MessagingException e) {
            System.err.println ("Could not connect to smtp://" + host + ":" + port + ", Jakarta Mail is reporting an error");
            e.printStackTrace ();
            return false;
        }

        return true;
}

The question I linked above seemed to indicate that this should validate that the credentials worked. However, I have tried two SMTP servers under my control so far and both connection attempts did not return false with credentials I can guarantee do not work.

In the Jakarta Mail debug output, I also do not see any attempt to perform an SMTP AUTH (log abbreviated):

DEBUG: setDebug: Jakarta Mail version 2.0.0
DEBUG: getProvider() returning jakarta.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle]
DEBUG SMTP: useEhlo true, useAuth true
DEBUG SMTP: trying to connect to host "smtpserver", port 25, isSSL false
... pre-STARTTLS communication ...
STARTTLS
220 TLS go ahead
EHLO mymachine
250-smtpserver Hello mymachine
250-SIZE 52428800
250-8BITMIME
250-PIPELINING
250 HELP
DEBUG SMTP: Found extension "SIZE", arg "52428800"
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "PIPELINING", arg ""
DEBUG SMTP: Found extension "HELP", arg ""
QUIT
221 smtpserver closing connection

While I tried to take a look at the Jakarta Mail code, I do not have the time to invest in trying to thoroughly understand it throughout all abstraction layers. This leads me to my question: Is validating SMTP credentials possible via Jakarta Mail and if so, how?


Solution

  • Your servers are not configured to advertise the SMTP authentication extension (RFC 4954), judging from the EHLO response.

    The credentials are then not sent by the client (as the server would not understand them anyway).

    You should see something like this in the server's response:

    250-AUTH GSSAPI DIGEST-MD5
    

    Excerpt from RFC 4954:

    The AUTH EHLO keyword contains as a parameter a space-separated list of the names of available [SASL] mechanisms. The list of available mechanisms MAY change after a successful STARTTLS command [SMTP-TLS].