Java Mail to Exchange Server "no login methods supported"

egerardus picture egerardus · May 4, 2012 · Viewed 36.5k times · Source

I am trying to implement a Java Mail servlet, first step is connecting to the IMAP server.

I am able to telnet to the server on port 143 (default IMAP port), telnet says: OK The Microsoft Exchange IMAP4 service is ready.

Now I am trying to connect to the server using the Java Mail API like this:

Properties props = new Properties();
session = Session.getDefaultInstance(props, null);
store = session.getStore("imap");
store.connect("host","user","password");

And I am able to connect to this same server using an existing Outlook Webapp with the same credentials I am trying to pass to it in java.

But running this with session.setDebug(true) produces the following output:

DEBUG: setDebug: JavaMail version 1.4.5
DEBUG: getProvider() returning javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Sun Microsystems, Inc]
DEBUG: mail.imap.fetchsize: 16384
DEBUG: mail.imap.statuscachetimeout: 1000
DEBUG: mail.imap.appendbuffersize: -1
DEBUG: mail.imap.minidletime: 10
DEBUG: trying to connect to host "myHost", port 143, isSSL false
* OK The Microsoft Exchange IMAP4 service is ready.
A0 CAPABILITY
* CAPABILITY IMAP4 IMAP4rev1 LOGINDISABLED STARTTLS UIDPLUS CHILDREN IDLE NAMESPACE LITERAL+
A0 OK CAPABILITY completed.
DEBUG: protocolConnect login, host=myHost, user=myUser, password=<non-null>
javax.mail.MessagingException: No login methods supported!;

EDIT:

I added prop.setProperty("mail.imap.starttls.enable", "true") as suggested.

However, I started getting this debug output:

DEBUG: setDebug: JavaMail version 1.4.5
DEBUG: getProvider() returning javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Sun Microsystems, Inc]
DEBUG: mail.imap.fetchsize: 16384
DEBUG: mail.imap.statuscachetimeout: 1000
DEBUG: mail.imap.appendbuffersize: -1
DEBUG: mail.imap.minidletime: 10
DEBUG: enable STARTTLS
DEBUG: trying to connect to host "myHost", port 143, isSSL false
* OK The Microsoft Exchange IMAP4 service is ready.
A0 CAPABILITY
* CAPABILITY IMAP4 IMAP4rev1 LOGINDISABLED STARTTLS UIDPLUS CHILDREN IDLE NAMESPACE LITERAL+
A0 OK CAPABILITY completed.
DEBUG: protocolConnect login, host=myHost, user=myUser, password=<non-null>
A1 STARTTLS
A1 OK Begin TLS negotiation now.
DEBUG IMAP: STARTTLS Exception: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

Assuming that this was a certificate problem I followed these instructions and added mail server to my cacerts file. The test program included there ran totally fine and I could connect using an SSL url but I still got the same exception when running the java mail class.

I also tried changing to "imaps" with: session.getStore("imaps") (instead of "imap") and wasn't even able to get the "Microsoft Exchange Server is now ready" message. I think because it is trying to connect on port 993 whenever "imaps" was specified. But using telnet to port 993 does not show any connection to the email server.

So next I tried to force the program to use SSL on port 143 like this:

// Use SSL
prop.setProperty("mail.imap.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
prop.setProperty("mail.imap.socketFactory.fallback", "false");

// Use port 143
prop.setProperty("mail.imap.port", "143");
prop.setProperty("mail.imap.socketFactory.port", "143");

Only to receive this exception, so I don't think it wants anything to do with SSL:

DEBUG: mail.imap.fetchsize: 16384
DEBUG: mail.imap.statuscachetimeout: 1000
DEBUG: mail.imap.appendbuffersize: -1
DEBUG: mail.imap.minidletime: 10
DEBUG: trying to connect to host "myHost", port 143, isSSL false
Not able to process the mail reading.
javax.mail.MessagingException: Unrecognized SSL message, plaintext connection?;

Could that TLS exception above (DEBUG IMAP: STARTTLS Exception: javax.net.ssl.SSLHandshakeException:) come from TLS not being enabled on the Exchange Server?

I don't have ready access to the e-mail server but I could probably get someone to let me in.

SOLUTION:

HulkingUnicorn's comment below his answer pointed out this answer which was the exact handling needed. Apparently MS Exchange Server has this problem. Along with adding the class listed in that answer to my package, I simply implemented my mail connections like this and all was well:

Properties prop = new Properties();
prop.setProperty("mail.imap.starttls.enable", "true");
prop.setProperty("ssl.SocketFactory.provider", "my.package.name.ExchangeSSLSocketFactory");
prop.setProperty("mail.imap.socketFactory.class", "my.package.name.ExchangeSSLSocketFactory");
session = Session.getDefaultInstance(prop, null);
session.setDebug(true);
store = session.getStore("imap");
store.connect("myHost","myUser","myPassword");

Answer

HulkingUnicorn picture HulkingUnicorn · May 4, 2012

This part, * CAPABILITY IMAP4 IMAP4rev1 LOGINDISABLED suggest you can't log in, in this thread the OP solved it by updating his Javamail to 1.4.4 (although your debug output suggests you've already got that). Try using 1.4.5.

Actually, try adding this line before you create the session; your email server supports it and it's disabled by default: props.put("mail.imap.starttls.enable", "true");

This answer solved the problem.