我的Android应用必须使用OAAP2通过IMAP访问Gmail,而无需用户密码。 我已经实现了这个例子: https://java.net/projects/javamail/pages/OAuth2 根据需要添加提供程序(首次使用SASL支持时,SASL XOAUTH2提供程序将添加到Java安全配置中)
这是我的代码:
获取访问令牌
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;
}
}
创建提供者(OAuthFactory e OAuthClient类取自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连接
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;
}
但此代码提供了 [AUTHENTICATIONFAILED]无效凭据(失败)错误
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, user=myemail@gmail.com, 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)
我不明白问题是IMAP连接还是访问令牌;为了获取访问令牌,我也尝试了oauth.py,但结果是一样的。
感谢您的回复。