My Android app must access to Gmail by IMAP with OAuth2, without the user's password. I have implemented the example: https://java.net/projects/javamail/pages/OAuth2 adding a Provider as required (The SASL XOAUTH2 provider will be added to the Java security configuration when SASL support is first used)
this is my code:
get access token
public void getAndUseAuthTokenBlocking() throws JSONException { String token = ""; try { // Retrieve a token for the given account and scope. It will always return either // a non-empty String or throw an exception. String scope = "oauth2:https://mail.google.com/"; Log.i("Access TOKEN account",accountName); token = GoogleAuthUtil.getToken(activity.getApplicationContext(), accountName, scope); // Do work with token. URL url = new URL("https://www.googleapis.com/oauth2/v1/tokeninfo?access_token="+ token); HttpURLConnection con = (HttpURLConnection) url.openConnection(); int serverCode = con.getResponseCode(); if (serverCode == 200) { access_token = token; return; //bad token, invalidate and get a new one } else if (serverCode == 401) { // invalidate the token that we found is bad so that GoogleAuthUtil won't // return it next time (it may have cached it) GoogleAuthUtil.invalidateToken(activity.getApplicationContext(), token); // consider retrying getAndUseTokenBlocking() once more Log.w("Access TOKEN","INVALIDATO"); getAndUseAuthTokenBlocking(); } else { Log.e("SERVER CODE","Server returned the following error code: " + serverCode); return; } return; } catch (GooglePlayServicesAvailabilityException playEx) { Dialog alert = GooglePlayServicesUtil.getErrorDialog( playEx.getConnectionStatusCode(), activity,1); } catch (UserRecoverableAuthException userAuthEx) { // Start the user recoverable action using the intent returned by // getIntent() activity.startActivityForResult( userAuthEx.getIntent(), 1); return; } catch (IOException ioEx) { // network or server error, the call is expected to succeed if you try again later. // Don't attempt to call again immediately - the request is likely to // fail, you'll hit quotas or back-off. Log.e("IOException", "transient error encountered: " + ioEx.getMessage()); return; } catch (GoogleAuthException authEx) { // Failure. The call is not expected to ever succeed so it should not be // retried. Log.e("GoogleAuthException", "Unrecoverable authentication exception: " + authEx.getMessage(), authEx); return; } }creation of provider (OAuthFactory e OAuthClient classes were taken from https://code.google.com/p/google-mail-oauth2-tools/source/browse/trunk/java/#java%2Fcom%2Fgoogle%2Fcode%2Fsamples%2Foauth2 )
public static final class OAuthProvider extends Provider { private static final long serialVersionUID = 1L; public OAuthProvider() { super("Google OAuth2 Provider", 1.0, "Provides the XOAUTH2 SASL Mechanism"); String className = OAuthFactory.class.getName(); put("SaslClientFactory.XOAUTH2", className); } }IMAP connection
protected String doInBackground(String... params) { Log.i("account",accountName); try { getAndUseAuthTokenBlocking(); } catch (JSONException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } Log.i("access token",access_token); initialize(); Properties props = new Properties(); props.put("mail.imap.ssl.enable", "true"); // required for Gmail props.put("mail.imap.sasl.enable", "true"); props.put("mail.imap.sasl.mechanisms", "XOAUTH2"); props.put("mail.imap.auth.login.disable", "true"); props.put("mail.imap.auth.plain.disable", "true"); Session session = Session.getInstance(props); session.setDebug(true); Store store; try { store = session.getStore("imaps"); store.connect("imap.gmail.com", accountName, access_token); } catch (NoSuchProviderException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (MessagingException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; }
But this code gives the [AUTHENTICATIONFAILED] Invalid credentials (Failure) error
08-21 16:14:43.100: I/System.out(7346): DEBUG: setDebug: JavaMail version 1.5.2
08-21 16:14:43.100: I/System.out(7346): DEBUG: getProvider() returning javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Oracle,1.5.2]
08-21 16:14:43.100: W/dalvikvm(7346): method Lcom/sun/mail/imap/IMAPStore;.getSession incorrectly overrides package-private method with same name in Ljavax/mail/Service;
08-21 16:14:43.104: I/System.out(7346): DEBUG IMAPS: mail.imap.fetchsize: 16384
08-21 16:14:43.104: I/System.out(7346): DEBUG IMAPS: mail.imap.ignorebodystructuresize: false
08-21 16:14:43.104: I/System.out(7346): DEBUG IMAPS: mail.imap.statuscachetimeout: 1000
08-21 16:14:43.104: I/System.out(7346): DEBUG IMAPS: mail.imap.appendbuffersize: -1
08-21 16:14:43.104: I/System.out(7346): DEBUG IMAPS: mail.imap.minidletime: 10
08-21 16:14:43.108: I/System.out(7346): DEBUG IMAPS: trying to connect to host "imap.gmail.com", port 993, isSSL true
08-21 16:14:48.408: I/System.out(7346): * OK Gimap ready for requests from 82.57.18.250 z47mb29911677eep
08-21 16:14:48.408: I/System.out(7346): A0 CAPABILITY
08-21 16:14:48.468: I/System.out(7346): * 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
08-21 16:14:48.468: I/System.out(7346): A0 OK Thats all she wrote! z47mb29911677eep
08-21 16:14:48.468: I/System.out(7346): DEBUG IMAPS: AUTH: XOAUTH
08-21 16:14:48.468: I/System.out(7346): DEBUG IMAPS: AUTH: XOAUTH2
08-21 16:14:48.468: I/System.out(7346): DEBUG IMAPS: AUTH: PLAIN
08-21 16:14:48.468: I/System.out(7346): DEBUG IMAPS: AUTH: PLAIN-CLIENTTOKEN
08-21 16:14:48.472: I/System.out(7346): DEBUG IMAPS: protocolConnect login, host=imap.gmail.com, [email protected], password=<non-null>
08-21 16:14:48.472: I/System.out(7346): DEBUG IMAPS: AUTHENTICATE PLAIN command trace suppressed
08-21 16:14:49.488: I/System.out(7346): DEBUG IMAPS: AUTHENTICATE PLAIN command result: A1 NO [AUTHENTICATIONFAILED] Invalid credentials (Failure)
08-21 16:14:49.488: W/System.err(7346): javax.mail.AuthenticationFailedException: [AUTHENTICATIONFAILED] Invalid credentials (Failure)
08-21 16:14:49.492: W/System.err(7346): at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:715)
08-21 16:14:49.492: W/System.err(7346): at javax.mail.Service.connect(Service.java:364)
08-21 16:14:49.492: W/System.err(7346): at javax.mail.Service.connect(Service.java:245)
08-21 16:14:49.492: W/System.err(7346): at com.example.tickets.Reader2.doInBackground(Reader2.java:113)
08-21 16:14:49.492: W/System.err(7346): at com.example.tickets.Reader2.doInBackground(Reader2.java:1)
08-21 16:14:49.492: W/System.err(7346): at android.os.AsyncTask$2.call(AsyncTask.java:287)
08-21 16:14:49.492: W/System.err(7346): at java.util.concurrent.FutureTask.run(FutureTask.java:234)
08-21 16:14:49.492: W/System.err(7346): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
08-21 16:14:49.492: W/System.err(7346): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
08-21 16:14:49.500: W/System.err(7346): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
08-21 16:14:49.500: W/System.err(7346): at java.lang.Thread.run(Thread.java:841)
I don't understand if the problem is the IMAP connection or the access token; for take the access token I also tried oauth.py but the result is the same.
Thanks for your reply.