使用带有accountmanager令牌的imap访问gmail

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

Google通过oauth2提供了此IMAP示例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

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  "); 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"); 

}

但是,当我运行上面的代码时,我得到“空用户名或密码”的例外。 有人可以告诉我如何使用带有xoauth2的imap访问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= 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 

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

您是否记得在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"); } 

}

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

UPDATE

这是我使用的代码,它基本上是示例代码,它真正改变了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= 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 

我做了什么来解决相同的问题来重新编译java邮件包的源代码,在IMAPSaslAuthenticator文件中将javax.security的调用替换为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= 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

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

下面的这个例外是触发的,我开始认为这与错误或其他问题有关,但无法找出原因。 Callback是否需要在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