I'm having a problem connecting to GMail with JavaMail in a non-android environment. I'm being given an OAuth2 access token, which I believe to be correct. But when I try to use this access token to connect, I get an exception:
javax.mail.AuthenticationFailedException: [AUTHENTICATIONFAILED] Invalid credentials (Failure)
It looks, to me, like the Java SASL code is expecting two return values (a username and a password callback?), but is only getting one.
I've boiled the problem down to this code:
import java.io.IOException;
import java.util.Properties;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Store;
public class TestImap {
private String userId;
private String accessToken;
public TestImap(String[] args) {
userId = args[0];
accessToken = args[1];
}
public void connectImap()
throws MessagingException
{
System.out.println("Connecting to gmail with IMAP and OAUTH2.");
Properties props = new Properties();
props.put("mail.imaps.ssl.enable", "true");
props.put("mail.imaps.sasl.enable", "true");
props.put("mail.imaps.sasl.mechanisms", "XOAUTH2");
props.put("mail.imaps.auth.login.disable", "true");
props.put("mail.imaps.auth.plain.disable", "true");
props.put("mail.debug.auth", "true");
/*
props.put("mail.imaps.sasl.mechanisms.oauth2.oauthToken",
accessToken);
*/
System.out.println("Creating session...");
Session session = Session.getInstance(props);
session.setDebug(true);
System.out.println("Creating store...");
Store store = session.getStore("imaps");
System.out.println("Connecting store...");
store.connect("imap.gmail.com", 993, userId, accessToken);
System.out.println("Store connected. If we get here, things work.");
}
public static void main(String[] args) {
TestImap test = new TestImap(args);
try {
test.connectImap();
} catch (Throwable e) {
System.out.println("Died throwing an exception: ");
e.printStackTrace();
}
}
}
That, when run, gives the following output:
Connecting to gmail with IMAP and OAUTH2.
Creating session...
DEBUG: setDebug: JavaMail version 1.5.3
Creating store...
DEBUG: getProvider() returning javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Oracle]
DEBUG IMAPS: mail.imap.fetchsize: 16384
DEBUG IMAPS: mail.imap.ignorebodystructuresize: false
DEBUG IMAPS: mail.imap.statuscachetimeout: 1000
DEBUG IMAPS: mail.imap.appendbuffersize: -1
DEBUG IMAPS: mail.imap.minidletime: 10
DEBUG IMAPS: disable AUTH=LOGIN
DEBUG IMAPS: disable AUTH=PLAIN
DEBUG IMAPS: enable SASL
DEBUG IMAPS: SASL mechanisms allowed: XOAUTH2
DEBUG IMAPS: closeFoldersOnStoreFailure
Connecting store...
DEBUG IMAPS: trying to connect to host "imap.gmail.com", port 993, isSSL true
* OK Gimap ready for requests from 162.243.86.176 d92mb281521696qgf
A0 CAPABILITY
* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 XYZZY SASL-IR AUTH=XOAUTH AUTH=XOAUTH2 AUTH=PLAIN AUTH=PLAIN-CLIENTTOKEN
A0 OK Thats all she wrote! d92mb281521696qgf
DEBUG IMAPS: AUTH: XOAUTH
DEBUG IMAPS: AUTH: XOAUTH2
DEBUG IMAPS: AUTH: PLAIN
DEBUG IMAPS: AUTH: PLAIN-CLIENTTOKEN
DEBUG IMAPS: protocolConnect login, host=imap.gmail.com, user=bhurt42@gmail.com, password=<non-null>
DEBUG IMAPS: SASL Mechanisms:
DEBUG IMAPS: XOAUTH2
DEBUG IMAPS:
DEBUG IMAPS: SASL client XOAUTH2
DEBUG IMAPS: SASL callback length: 2
DEBUG IMAPS: SASL callback 0: javax.security.auth.callback.NameCallback@268d5581
DEBUG IMAPS: SASL callback 1: javax.security.auth.callback.PasswordCallback@8e89bed
A1 AUTHENTICATE XOAUTH2 dXNlcj1iaHVydDQyQGdtYWlsLmNvbQFhdXRoPUJlYXJlciB5YTI5LldBRjY1ZGZZT3YyWEdTdkozOWdTUEswN2ZHeWhCdFNjeWp0WFlGTHliN2NobHAyemlFa0MtNFo2UWdmMG9UQWR4b2NiZXpHX2ZPdW91dwEB
+ eyJzdGF0dXMiOiI0MDAiLCJzY2hlbWVzIjoiQmVhcmVyIiwic2NvcGUiOiJodHRwczovL21haWwuZ29vZ2xlLmNvbS8ifQ==
DEBUG IMAPS: SASL no response
A1 NO [AUTHENTICATIONFAILED] Invalid credentials (Failure)
Died throwing an exception:
javax.mail.AuthenticationFailedException: [AUTHENTICATIONFAILED] Invalid credentials (Failure)
at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:722)
at javax.mail.Service.connect(Service.java:364)
at TestImap.connectImap(TestImap.java:38)
at TestImap.main(TestImap.java:45)
This is with JavaMail 1.5.3. I've googled this question, and most of the answers I've found so far are sufficiently old that I'm pretty sure they predate JavaMail supporting google natively.
Any help would be greatly appreciated. Thanks.