Java IMAP Gmail身份验证:凭据无效

Java IMAP Gmail身份验证:凭据无效,java,android,oauth-2.0,jakarta-mail,imap,Java,Android,Oauth 2.0,Jakarta Mail,Imap,我的Android应用程序必须使用OAuth2通过IMAP访问Gmail,无需用户密码。 我已经实现了这个示例: 根据需要添加提供程序(首次使用SASL支持时,SASL XOAUTH2提供程序将添加到Java安全配置中) 这是我的代码: 获取访问令牌 public void getAndUseAuthTokenBlocking() throws JSONException { String token = ""; try { // Re

我的Android应用程序必须使用OAuth2通过IMAP访问Gmail,无需用户密码。 我已经实现了这个示例: 根据需要添加提供程序(首次使用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和OAuthClient类取自)

  • 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)
    
    08-21 16:14:43.100:I/System.out(7346):调试:setDebug:JavaMail版本1.5.2
    08-21 16:14:43.100:I/System.out(7346):调试:getProvider()返回javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Oracle,1.5.2]
    08-21 16:14:43.100:W/dalvikvm(7346):方法Lcom/sun/mail/imap/IMAPStore;。getSession错误地覆盖了Ljavax/mail/Service中同名的包私有方法;
    08-21 16:14:43.104:I/System.out(7346):调试IMAPS:mail.imap.fetchsize:16384
    08-21 16:14:43.104:I/System.out(7346):调试IMAPS:mail.imap.ignorebodystructuresize:false
    08-21 16:14:43.104:I/System.out(7346):调试IMAPS:mail.imap.statuscachetimeout:1000
    08-21 16:14:43.104:I/System.out(7346):调试IMAPS:mail.imap.appendbuffersize:-1
    08-21 16:14:43.104:I/System.out(7346):调试IMAPS:mail.imap.minidletime:10
    08-21 16:14:43.108:I/System.out(7346):调试IMAPS:尝试连接到主机“imap.gmail.com”,端口993,isSSL true
    08-21 16:14:48.408:I/System.out(7346):*正常Gimap准备就绪,可以接收来自82.57.18.250 z47mb29911677eep的请求
    08-21 16:14:48.408:输入/系统输出(7346):A0能力
    08-21 16:14:48.468:I/System.out(7346):*功能IMAP4rev1取消选择空闲命名空间配额ID XLIST CHILDREN X-GM-EXT-1 xyzy SASL-IR AUTH=XOAUTH AUTH=XOAUTH=XOAUTH2 AUTH=PLAIN AUTH=PLAIN-CLIENTTOKEN
    08-21 16:14:48.468:I/System.out(7346):A0好的,这就是她写的全部内容!Z47MB2991677EEP
    08-21 16:14:48.468:I/System.out(7346):调试IMAPS:AUTH:XOAUTH
    08-21 16:14:48.468:I/System.out(7346):调试IMAPS:AUTH:XOAUTH2
    08-21 16:14:48.468:I/System.out(7346):调试IMAPS:AUTH:PLAIN
    08-21 16:14:48.468:I/System.out(7346):调试IMAPS:AUTH:PLAIN-CLIENTTOKEN
    08-21 16:14:48.472:I/System.out(7346):调试IMAPS:protocolConnect登录,主机=imap.gmail.com,用户=myemail@gmail.com,密码=
    08-21 16:14:48.472:I/System.out(7346):调试IMAPS:验证普通命令跟踪被抑制
    08-21 16:14:49.488:I/System.out(7346):调试IMAPS:验证普通命令结果:A1否[AUTHENTICATIONFAILED]无效凭据(失败)
    08-21 16:14:49.488:W/System.err(7346):javax.mail.AuthenticationFailedException:[AUTHENTICATIONFAILED]无效凭据(失败)
    08-21 16:14:49.492:W/System.err(7346):位于com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:715)
    08-21 16:14:49.492:W/System.err(7346):位于javax.mail.Service.connect(Service.java:364)
    08-21 16:14:49.492:W/System.err(7346):位于javax.mail.Service.connect(Service.java:245)
    08-21 16:14:49.492:W/System.err(7346):位于com.example.tickets.Reader2.doInBackground(Reader2.java:113)
    08-21 16:14:49.492:W/System.err(7346):位于com.example.tickets.Reader2.doInBackground(Reader2.java:1)
    08-21 16:14:49.492:W/System.err(7346):在android.os.AsyncTask$2.call(AsyncTask.java:287)
    08-21 16:14:49.492:W/System.err(7346):在java.util.concurrent.FutureTask.run(FutureTask.java:234)处
    08-21 16:14:49.492:W/System.err(7346):在android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
    08-21 16:14:49.492:W/System.err(7346):位于java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
    08-21 16:14:49.500:W/System.err(7346):位于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连接还是访问令牌;对于take访问令牌,我也尝试了oauth.py,但结果是一样的

    谢谢您的回复。


    您可能需要按照图片进行操作,将您的gmail帐户设置设置为

    您的日志显示您正在发出一个AUTHENTICATE普通命令,并且服务器将丢失一个带有AUTHENTICATIONFAILED响应代码的NO响应。因此,您希望使用Oauth2,但实际上您使用的是Plain。根据javamail文档,我使用了props.put(“mail.imap.auth.Plain.disable”,true”);mail.imap.auth.Plain.disable boolean如果为true,则阻止使用AUTHENTICATE Plain命令。默认值为false。您正在为“imap”设置一系列属性“协议,但您使用的是“imaps”协议。将getStore调用更改为使用“imap”。另外,如果您使用的是内置OAuth支持的最新JavaMail版本,则不需要所有Google OAuth代码。感谢Bill的回复,问题是getStore方法中的协议名称。但是现在我对SASL身份验证有一些问题:08-21 21:46:39.102:I/System.out(2234):调试IMAPS:无法加载SASL身份验证程序,抛出:08-21 21:46:39.102:I/System.out(2234):java.lang.ClassNotFoundException:com.sun.mail.imap.protocol.IMAPSASASLAuthenticator我尝试过使用,但我一直都遇到SASL身份验证问题。“你不需要所有的GoogleOAuth代码”是什么意思?我使用过javamail 1.5.2 release.tnxi如果任何人对此有解决方案,请在此处发布。如果您无法打开图片,您可以通过以下方式找到该功能:帐户-->安全-->不太安全的应用程序访问-->打开访问
    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)