【问题标题】:Access gmail using imap with accountmanager token使用带有 accountmanager 令牌的 imap 访问 gmail
【发布时间】:2013-01-18 21:04:42
【问题描述】:

我正在尝试使用从 Android 的 AccountManager 收到的令牌而不是使用用户名和密码来实现 IMAP gmail 客户端。

Google 提供了这个带有 oauth2 http://code.google.com/p/google-mail-oauth2-tools/source/browse/#svn%2Ftrunk%2Fjava%2Fcom%2Fgoogle%2Fcode%2Fsamples%2Foauth2 http://code.google.com/p/google-mail-oauth2-tools/wiki/JavaSampleCode 的 IMAP 示例

public static IMAPStore connectToImap(String host,
                                    int port,
                                    String userEmail,
                                    String oauthToken,
                                    boolean debug) throws Exception {
Properties props = new Properties();
props.put("mail.imaps.sasl.enable", "true");
props.put("mail.imaps.sasl.mechanisms", "XOAUTH2");
props.put(OAuth2SaslClientFactory.OAUTH_TOKEN_PROP, oauthToken);
Session session = Session.getInstance(props);
session.setDebug(debug);

final URLName unusedUrlName = null;
IMAPSSLStore store = new IMAPSSLStore(session, unusedUrlName);
final String emptyPassword = "";
store.connect(host, port, userEmail, emptyPassword);
return store;

}

public static void main(String args[]) throws Exception {
if (args.length != 2) {
  System.err.println(
      "Usage: OAuth2Authenticator <email> <oauthToken>");
  return;
}
String email = args[0];
String oauthToken = args[1];

initialize();

IMAPStore imapStore = connectToImap("imap.gmail.com",
                                    993,
                                    email,
                                    oauthToken,
                                    true);
System.out.println("Successfully authenticated to IMAP.\n");

}

但是,当我运行上面的代码时,我得到了“空用户名或密码”的异常。有人可以告诉我如何使用 imap 和 xoauth2 访问 gmail 吗?谢谢。

2013/02/20 更新,以下是调试日志

 02-19 17:27:20.098  1905: 1905 I/System.out : setDebug: JavaMail version 1.4.1    
 02-19 17:27:20.098  1905: 1905 I/System.out : mail.imap.fetchsize: 16384    
 02-19 17:27:20.106  1905: 1905 I/System.out : enable SASL    
 02-19 17:27:20.106  1905: 1905 I/System.out : SASL mechanisms allowed: XOAUTH2    
 02-19 17:27:21.340  1905: 1905 I/System.out : * OK Gimap ready for requests from 36.224.98.49 z8if14713202igb.53
 02-19 17:27:21.348  1905: 1905 I/System.out : A0 CAPABILITY
 02-19 17:27:21.598  1905: 1905 I/System.out : * CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 XYZZY SASL-IR AUTH=XOAUTH AUTH=XOAUTH2
 02-19 17:27:21.598  1905: 1905 I/System.out : A0 OK Thats all she wrote! z8if14713202igb.53
 02-19 17:27:21.614  1905: 1905 I/System.out : IMAP DEBUG: AUTH: XOAUTH    
 02-19 17:27:21.614  1905: 1905 I/System.out : IMAP DEBUG: AUTH: XOAUTH2    
 02-19 17:27:21.614  1905: 1905 I/System.out : DEBUG: protocolConnect login, host=imap.gmail.com, user=2104176@gmail.com, password=<non-null>    
 02-19 17:27:21.622  1905: 1905 I/System.out : IMAP SASL DEBUG: Mechanisms: XOAUTH2    
 02-19 17:27:21.817  1905: 1905 I/System.out : IMAP SASL DEBUG: Failed to create SASL client: myjavax.security.sasl.SaslException: Cannot instantiate class com.research.oauth.OAuth2SaslClientFactory [Caused by java.lang.InstantiationException: can't instantiate class com.research.oauth.OAuth2SaslClientFactory]
  02-19 17:27:21.817  1905: 1905 I/System.out : A1 LOGIN 2104176@gmail.com ""
 02-19 17:27:22.036  1905: 1905 I/System.out : A1 NO Empty username or password. z8if14713202igb.53
 02-19 17:27:22.044  1905: 1905 D/test       : javax.mail.AuthenticationFailedException: Empty username or password. z8if14713202igb.53

我使用你的 mail.jar 和我的应用程序无法创建 SASL 客户端:myjavax.security.sasl.SaslException:无法实例化类 com.research.oauth.OAuth2SaslClientFactory,然后应用程序使用空密码登录 gmail。 请帮我解决问题,谢谢!

【问题讨论】:

  • 您是否设法获得了一个令牌并具有范围?
  • 是的,我在运行代码之前获得了帐户令牌。
  • 您使用了什么范围以及令牌的外观如何?您可以使用它“手动”进行身份验证吗? (通过使用 telnet/openssl 等并输入 IMAP 命令)
  • 令牌看起来像:ya29.AHeSvghvghvyjfgdthcjhvujyjgyfhjmvfxgvhjhbhkbgh........
  • 我使用下面的代码来获取令牌。 AccountManager 经理 = AccountManager.get(this);帐户[] 帐户 = mgr.getAccountsByType("com.google");令牌 = mgr.getAuthToken(accts[0], "oauth2:https://"mail.google.com/", null, this, new OnTokenAcquired(), null);

标签: java android gmail imap


【解决方案1】:

如果我在 main 方法中运行测试代码,这对我有用,但是在 glassfish 服务器上部署它会遇到其他问题。 遵循http://code.google.com/p/google-mail-oauth2-tools/的代码

然后触发了下面的这个异常,我开始认为这与错误或其他问题有关,但无法找出原因。回调是否需要 Google API 控制台中的一些 ULR?或者为什么它在本地工作,但在 glassfish 部署时却不能。 java.lang.IllegalStateException: WEB9031: WebappClassLoader 无法加载资源 [com.google.code.samples.oauth2.OAuth2SaslClientFactory],因为它尚未启动或已停止

还查看了此错误是否与此相关:https://groups.google.com/forum/#!msg/google-appengine/OK3FuIPuA1I/dgov_VRffVgJ

【讨论】:

    【解决方案2】:

    我做了什么来解决同样的问题重新编译java邮件包的源代码,将javax.security的调用替换为IMAPSaslAuthenticator文件中的asmack。 IMAP连接可以通过,

    11-29 15:51:46.921: D/11.28(2759):  --> the token is ya29.1.
    11-29 15:51:46.937: I/System.out(2759): DEBUG: setDebug: JavaMail version ${mail.version}
    11-29 15:51:46.937: I/System.out(2759): DEBUG IMAPS: mail.imap.fetchsize: 16384
    11-29 15:51:46.937: I/System.out(2759): DEBUG IMAPS: mail.imap.ignorebodystructuresize: false
    11-29 15:51:46.937: I/System.out(2759): DEBUG IMAPS: mail.imap.statuscachetimeout: 1000
    11-29 15:51:46.937: I/System.out(2759): DEBUG IMAPS: mail.imap.appendbuffersize: -1
    11-29 15:51:46.937: I/System.out(2759): DEBUG IMAPS: mail.imap.minidletime: 10
    11-29 15:51:46.937: I/System.out(2759): DEBUG IMAPS: enable SASL
    11-29 15:51:46.937: I/System.out(2759): DEBUG IMAPS: SASL mechanisms allowed: XOAUTH2
    11-29 15:51:46.937: I/System.out(2759): DEBUG IMAPS: trying to connect to host "imap.gmail.com", port 993, isSSL true
    11-29 15:51:47.085: D/dalvikvm(2759): GC_CONCURRENT freed 410K, 53% free 8847K/18503K, paused 3ms+6ms, total 38ms
    11-29 15:51:47.085: I/System.out(2759): A4 LOGOUT
    11-29 15:51:47.093: I/System.out(2759): DEBUG IMAPS: IMAPStore connection dead
    11-29 15:51:47.093: I/System.out(2759): DEBUG IMAPS: IMAPStore cleanup, force true
    11-29 15:51:47.093: I/System.out(2759): DEBUG IMAPS: IMAPStore cleanup done
    11-29 15:51:47.093: D/AbsListView(2759): [unregisterDoubleTapMotionListener]
    11-29 15:51:47.093: I/MotionRecognitionManager(2759):   .unregisterListener : / listener count = 0->0, listener=android.widget.AbsListView$4@41d9a1b0
    11-29 15:51:47.093: I/System.out(2759): A4 LOGOUT
    11-29 15:51:47.132: I/System.out(2759): * BYE LOGOUT Requested
    11-29 15:51:47.140: I/System.out(2759): A4 OK 73 good day (Success)
    11-29 15:51:47.140: I/System.out(2759): DEBUG IMAPS: IMAPStore connection dead
    11-29 15:51:47.140: I/System.out(2759): DEBUG IMAPS: IMAPStore cleanup, force false
    11-29 15:51:47.140: I/System.out(2759): DEBUG IMAPS: IMAPStore cleanup done
    11-29 15:51:47.140: D/AbsListView(2759): [unregisterDoubleTapMotionListener]
    11-29 15:51:47.140: I/MotionRecognitionManager(2759):   .unregisterListener : / listener count = 0->0, listener=android.widget.AbsListView$4@41de2ba0
    11-29 15:51:47.171: I/System.out(2759): * OK Gimap ready for requests from 216.16.246.195 q6if13300240veb.40
    11-29 15:51:47.171: I/System.out(2759): A0 CAPABILITY
    11-29 15:51:47.218: I/System.out(2759): * 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
    11-29 15:51:47.218: I/System.out(2759): A0 OK Thats all she wrote! q6if13300240veb.40
    11-29 15:51:47.218: I/System.out(2759): DEBUG IMAPS: AUTH: XOAUTH
    11-29 15:51:47.226: I/System.out(2759): DEBUG IMAPS: AUTH: XOAUTH2
    11-29 15:51:47.226: I/System.out(2759): DEBUG IMAPS: AUTH: PLAIN
    11-29 15:51:47.226: I/System.out(2759): DEBUG IMAPS: AUTH: PLAIN-CLIENTTOKEN
    11-29 15:51:47.226: I/System.out(2759): DEBUG IMAPS: protocolConnect login, host=imap.gmail.com, user=xxxx@gmail.com, password=<non-null>
    11-29 15:51:47.226: I/System.out(2759): DEBUG IMAPS: SASL authentication command trace suppressed
    11-29 15:51:47.226: I/System.out(2759): DEBUG IMAPS: SASL Mechanisms:
    11-29 15:51:47.226: I/System.out(2759): DEBUG IMAPS:  XOAUTH2
    11-29 15:51:47.226: I/System.out(2759): DEBUG IMAPS: 
    11-29 15:51:47.233: I/System.out(2759): DEBUG IMAPS: SASL client XOAUTH2
    11-29 15:51:47.272: I/System.out(2759): DEBUG IMAPS: SASL challenge:  :
    11-29 15:51:47.272: I/System.out(2759): DEBUG IMAPS: SASL callback length: 1
    11-29 15:51:47.272: I/System.out(2759): DEBUG IMAPS: SASL callback 0: org.apache.harmony.javax.security.auth.callback.NameCallback@41e082c8
    11-29 15:51:47.272: I/System.out(2759): DEBUG IMAPS: SASL response: user=xxxx@gmail.comauth=Bearer ya29.1...UhhyFDen9bUwcd5I :
    11-29 15:51:48.101: I/System.out(2759): DEBUG IMAPS: SASL authentication succeeded
    11-29 15:51:48.101: I/System.out(2759): A2 CAPABILITY
    11-29 15:51:48.272: I/System.out(2759): * CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 UIDPLUS COMPRESS=DEFLATE ENABLE MOVE CONDSTORE ESEARCH
    11-29 15:51:48.272: I/System.out(2759): A2 OK Success
    11-29 15:51:48.280: I/System.out(2759): A3 NAMESPACE
    11-29 15:51:48.452: I/System.out(2759): * NAMESPACE (("" "/")) NIL NIL
    11-29 15:51:48.452: I/System.out(2759): A3 OK Success
    

    我下载了

    的包
    1. javamail-1.5.0-src
    2. asmack-android-8-0.8.9.jar
    3. activation.jar

    我没用过

    的包
    1. mail.jar
    2. additionnal.jar

    【讨论】:

      【解决方案3】:

      您是否记得在 OAuth2Provider 中更改了您的包名称?我在用该代码进行测试时忘记了它。

      public static final class OAuth2Provider extends Provider {
      private static final long serialVersionUID = 1L;
      
      public OAuth2Provider() {
        super("Google OAuth2 Provider", 1.0,
              "Provides the XOAUTH2 SASL Mechanism");
        put("SaslClientFactory.XOAUTH2",
            "com.example.testjavamail.OAuth2SaslClientFactory");
      }
      

      }

      正如我在另一个答案中所说,我只测试了连接,但它对我有用。

      更新

      这是我使用的代码,基本上是示例代码,真正改变了 Java Mail 中 SASL 支持的移植。

      public class OAuth2Authenticator {
      private static final Logger logger = Logger
              .getLogger(OAuth2Authenticator.class.getName());
      private static Session mSession;
      
      public static final class OAuth2Provider extends Provider {
          private static final long serialVersionUID = 1L;
      
          public OAuth2Provider() {
              super("Google OAuth2 Provider", 1.0,
                      "Provides the XOAUTH2 SASL Mechanism");
              put("SaslClientFactory.XOAUTH2",
                      "com.example.testjavamail.OAuth2SaslClientFactory");
          }
      }
      
      public static void initialize() {
          Security.addProvider(new OAuth2Provider());
      }
      
      public static IMAPStore connectToImap(String host, int port,
              String userEmail, String oauthToken, boolean debug)
              throws Exception {
          Properties props = new Properties();
          props.put("mail.imaps.sasl.enable", "true");
          props.put("mail.imaps.sasl.mechanisms", "XOAUTH2");
          props.put(OAuth2SaslClientFactory.OAUTH_TOKEN_PROP, oauthToken);
          Session session = Session.getInstance(props);
          session.setDebug(debug);
      
          final URLName unusedUrlName = null;
          IMAPSSLStore store = new IMAPSSLStore(session, unusedUrlName);
          final String emptyPassword = "";
          store.connect(host, port, userEmail, emptyPassword);
          return store;
      }
      
      public static SMTPTransport connectToSmtp(String host, int port,
              String userEmail, String oauthToken, boolean debug)
              throws Exception {
          Properties props = new Properties();
          props.put("mail.smtp.starttls.enable", "true");
          props.put("mail.smtp.starttls.required", "true");
          props.put("mail.smtp.sasl.enable", "true");
          props.put("mail.smtp.sasl.mechanisms", "XOAUTH2");
          props.put(OAuth2SaslClientFactory.OAUTH_TOKEN_PROP, oauthToken);
          mSession = Session.getInstance(props);
          mSession.setDebug(debug);
      
          final URLName unusedUrlName = null;
          SMTPTransport transport = new SMTPTransport(mSession, unusedUrlName);
          // If the password is non-null, SMTP tries to do AUTH LOGIN.
          final String emptyPassword = null;
          transport.connect(host, port, userEmail, emptyPassword);
      
          return transport;
      }
      
      public synchronized void testImap(String user, String oauthToken) {
          try {
      
              initialize();
      
      
              IMAPStore imapStore = connectToImap("imap.gmail.com", 993, user,
                      oauthToken, true);
      
          } catch (Exception e) {
              Log.d("test", e.toString());
          }
      
      }
      
      public class ByteArrayDataSource implements DataSource {
          private byte[] data;
          private String type;
      
          public ByteArrayDataSource(byte[] data, String type) {
              super();
              this.data = data;
              this.type = type;
          }
      
          public ByteArrayDataSource(byte[] data) {
              super();
              this.data = data;
          }
      
          public void setType(String type) {
              this.type = type;
          }
      
          public String getContentType() {
              if (type == null)
                  return "application/octet-stream";
              else
                  return type;
          }
      
          public InputStream getInputStream() throws IOException {
              return new ByteArrayInputStream(data);
          }
      
          public String getName() {
              return "ByteArrayDataSource";
          }
      
          public OutputStream getOutputStream() throws IOException {
              throw new IOException("Not Supported");
          }
      }
      

      }

      这是来自 Java Mail 的调试。顺便说一句,发布您的调试日志,它应该有助于了解发生了什么问题

      02-06 10:18:11.805: I/System.out(7434): DEBUG: setDebug: JavaMail version 1.4.1
      02-06 10:18:11.905: I/System.out(7434): DEBUG: mail.imap.fetchsize: 16384
      02-06 10:18:12.025: I/System.out(7434): DEBUG: enable SASL
      02-06 10:18:12.040: I/System.out(7434): DEBUG: SASL mechanisms allowed: XOAUTH2
      02-06 10:18:12.600: I/System.out(7434): * OK Gimap ready for requests from 2.233.xxx.xxx  2if1471965eej.3
      02-06 10:18:12.605: I/System.out(7434): A0 CAPABILITY
      02-06 10:18:12.635: I/System.out(7434): * CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 XYZZY SASL-IR AUTH=XOAUTH AUTH=XOAUTH2
      02-06 10:18:12.635: I/System.out(7434): A0 OK Thats all she wrote! 2if1471965eej.3
      02-06 10:18:12.645: I/System.out(7434): IMAP DEBUG: AUTH: XOAUTH
      02-06 10:18:12.645: I/System.out(7434): IMAP DEBUG: AUTH: XOAUTH2
      02-06 10:18:12.645: I/System.out(7434): DEBUG: protocolConnect login, host=imap.gmail.com, user=xxx@gmail.com, password=<non-null>
      02-06 10:18:12.650: I/System.out(7434): IMAP SASL DEBUG: Mechanisms: XOAUTH2
      02-06 10:18:12.695: I/System.out(7434): IMAP SASL DEBUG: SASL client XOAUTH2
      02-06 10:18:12.695: I/System.out(7434): A1 AUTHENTICATE XOAUTH2
      02-06 10:18:12.720: I/System.out(7434): + 
      02-06 10:18:12.720: I/System.out(7434): IMAP SASL DEBUG: challenge:  :
      02-06 10:18:12.730: I/System.out(7434): IMAP SASL DEBUG: callback length: 1
      02-06 10:18:12.730: I/System.out(7434): IMAP SASL DEBUG: callback 0: myjavax.security.auth.callback.NameCallback@41760f78
      02-06 10:18:12.730: I/System.out(7434): IMAP SASL DEBUG: response: user=xxx@gmail.comauth=Bearer ya29.... :
      02-06 10:18:12.735: I/System.out(7434): dXNlcj1hbGVhbGVtYXp6b3R0aUBnbWFpbC5jb20BYXV0aD1CZWFyZXIgeWEyOS5BSEVTNlpRYklPeU8xU09sR01WSEo3X2tqVzlVdzNYY1RvODBtQ0hyWFVacjRsYlhIdwEB
      02-06 10:18:12.870: I/System.out(7434): * CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 UIDPLUS COMPRESS=DEFLATE
      02-06 10:18:12.870: I/System.out(7434): A1 OK xxx@gmail.com My NAME authenticated (Success)
      02-06 10:18:12.870: I/System.out(7434): A2 CAPABILITY
      02-06 10:18:13.160: I/System.out(7434): * CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 UIDPLUS COMPRESS=DEFLATE
      02-06 10:18:13.160: I/System.out(7434): A2 OK Success
      

      【讨论】:

      • 是的,我在 OAuth2Provider 中更改了我的包名。不管我改不改,在代码“store.connect(host, port, userEmail, emptyPassword);”中总是出现“空用户名或密码”的异常。如果您以另一种方式测试了连接,您可以发布总代码或将项目邮寄给我吗?谢谢。
      • 感谢您的回复,我更新了问题内容中的调试日志。我的问题是应用程序无法创建 SASL 客户端:myjavax.security.sasl.SaslException,请帮我解决问题,或者您可以将您使用的测试项目通过电子邮件发送给我,谢谢!
      • 顺便说一句,我使用了 4 个权限,我需要另一个权限吗?
      • 这里是我使用的测试项目,看起来很可怕,但它确实有效。同样,它只对 imap 进行了身份验证。里面有javamail jars。它们是我之前链接的早期版本,并且在这个项目中可以肯定地工作。也许另一个罐子有问题。 dl.dropbox.com/u/3092259/TestJavaMail.zip
      • @unluddite!请您分享您的工作示例吗?
      猜你喜欢
      • 2012-02-26
      • 2011-04-03
      • 1970-01-01
      • 2012-01-29
      • 2017-05-23
      • 2012-12-23
      • 2011-07-15
      • 2013-03-16
      • 1970-01-01
      相关资源
      最近更新 更多