【问题标题】:IMAP Gmail Authentication: Invalid CredentialsIMAP Gmail 身份验证:凭据无效
【发布时间】:2014-10-15 06:24:52
【问题描述】:

我的 Android 应用必须通过具有 OAuth2 的 IMAP 访问 Gmail,无需用户密码。 我已经实现了这个例子: https://java.net/projects/javamail/pages/OAuth2 根据需要添加提供程序(SASL XOAUTH2 提供程序将在首次使用 SASL 支持时添加到 Java 安全配置中)

这是我的代码:

  1. 获取访问令牌

    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;
     }
    } 
    
  2. 提供者的创建(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);
      }
    }
    
  3. 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] Invalid credentials (Failure) 错误

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 但结果是一样的。

感谢您的回复。

【问题讨论】:

  • 您的日志显示您正在发出 AUTHENTICATE PLAIN 命令,而服务器正在发出带有 AUTHENTICATIONFAILED 响应代码的 NO 响应。所以你想使用 Oauth2,但实际上你使用的是 Plain。
  • 根据 javamail 文档,我使用了 props.put("mail.imap.auth.plain.disable", true"); mail.imap.auth.plain.disable boolean If true , 阻止使用 AUTHENTICATE PLAIN 命令。默认为 false。
  • 您正在为“imap”协议设置一堆属性,但您使用的是“imap”协议。将 getStore 调用更改为使用“imap”。此外,如果您使用的是内置 OAuth 支持的最新 JavaMail 版本,则不需要所有 Google OAuth 代码。
  • 感谢 Bill 的回复,问题是 getStore 方法中的协议名称。但现在我对 SASL 身份验证有一些问题:08-21 21:46:39.102: I/System.out(2234): DEBUG IMAPS: Can't load SASL authenticationator, THROW: 08-21 21:46:39.102: I/System.out(2234): java.lang.ClassNotFoundException: com.sun.mail.imap.protocol.IMAPSaslAuthenticator 我试过使用mannaz.at/codebase/imap-ssl-mail-android,但我总是遇到 sasl 身份验证问题。 “您不需要所有的 Google OAuth 代码”是什么意思?我使用 javamail 1.5.2 release.Tnx
  • 如果有人对此有解决方案,请在此处发布。

标签: java android oauth-2.0 jakarta-mail imap


【解决方案1】:

enter image description here

您可能需要按照图片,输入您的 gmail 帐户设置

【讨论】:

  • 如果无法打开图片,可以通过以下方式找到该功能:账号-->安全性--->不太安全的应用访问--->开启访问
猜你喜欢
  • 2015-12-20
  • 2020-04-10
  • 1970-01-01
  • 1970-01-01
  • 2022-06-11
  • 2018-12-21
  • 2012-01-29
  • 2020-07-18
  • 2023-02-08
相关资源
最近更新 更多