在 App Engine 上使用 OAuth2 的 IMAP
Posted
技术标签:
【中文标题】在 App Engine 上使用 OAuth2 的 IMAP【英文标题】:IMAP using OAuth2 on App Engine 【发布时间】:2013-07-28 19:24:31 【问题描述】:我正在尝试在 App Engine 上实现一项服务,该服务使用 OAuth2、Java 7 和 App Engine SDK 1.8.2 与 Gmail 帐户进行交互。遇到的问题是通过使用https://code.google.com/p/google-mail-oauth2-tools/wiki/JavaSampleCode 提供的示例代码,安全提供程序似乎没有在节点上被检测到,尽管在本地工作正常。之前链接提供的代码已修改为由带有示例代码的servlet启动:
import java.io.IOException;
import java.security.Provider;
import java.security.Security;
import java.util.Properties;
import javax.mail.Session;
import javax.mail.URLName;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.code.samples.oauth2.OAuth2SaslClientFactory;
import com.sun.mail.imap.IMAPSSLStore;
import com.sun.mail.imap.IMAPStore;
import com.sun.mail.smtp.SMTPTransport;
public class RunnerServlet extends HttpServlet
public void doGet( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException
String email = request.getParameter( "email");
String oauthToken = request.getParameter( "oauthToken");
initialize();
try
IMAPStore imapStore = connectToImap("imap.gmail.com",
993,
email,
oauthToken,
true);
System.out.println("Successfully authenticated to IMAP.\n");
SMTPTransport smtpTransport = connectToSmtp("smtp.gmail.com",
587,
email,
oauthToken,
true);
System.out.println("Successfully authenticated to SMTP.");
catch( Exception e )
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
throw new RuntimeException( e );
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.google.code.samples.oauth2.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);
session.getProperties().put("mail.imaps.sasl.enable", "true");
session.getProperties().put("mail.imaps.sasl.mechanisms", "XOAUTH2");
session.getProperties().put(OAuth2SaslClientFactory.OAUTH_TOKEN_PROP, oauthToken);
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);
Session session = Session.getInstance(props);
session.setDebug(debug);
final URLName unusedUrlName = null;
SMTPTransport transport = new SMTPTransport(session, 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;
IMAP 调试跟踪是:
DEBUG IMAPS: mail.imap.fetchsize: 16384
DEBUG IMAPS: mail.imap.ignorebodystructuresize: false
DEBUG IMAPS: mail.imap.statuscachetimeout: 1000
DEBUG IMAPS: mail.imap.appendbuffersize: -1
DEBUG IMAPS: mail.imap.minidletime: 10
DEBUG IMAPS: enable SASL
DEBUG IMAPS: SASL mechanisms allowed: XOAUTH2
DEBUG IMAPS: trying to connect to host "imap.gmail.com", port 993, isSSL true
* OK Gimap ready for requests from xxx.xxx.xxx.xxx ZZZZZZZZZ
A0 CAPABILITY
* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 XYZZY
A0 OK Thats all she wrote! ZZZZZZZZZ
DEBUG IMAPS: AUTH: XOAUTH
DEBUG IMAPS: AUTH: XOAUTH2
DEBUG IMAPS: protocolConnect login, host=imap.gmail.com, user=som...@gmail.com, password=<non-null>
DEBUG IMAPS: SASL authentication command trace suppressed
DEBUG IMAPS: SASL Mechanisms:
DEBUG IMAPS: XOAUTH2
DEBUG IMAPS:
DEBUG IMAPS: No SASL support
DEBUG IMAPS: SASL authentication failed
DEBUG IMAPS: LOGIN command trace suppressed
DEBUG IMAPS: LOGIN command result: A1 NO Empty username or password. ZZZZZZZZZ
DEBUG IMAPS: trying to connect to host "imap.gmail.com", port 993, isSSL true
* OK Gimap ready for requests from xxx.xxx.xxx.xxx YYYYYYYYYY
A0 CAPABILITY
* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 XYZZY SASL-IR AUTH=XOAUTH AUTH=XOAUTH2
A0 OK Thats all she wrote! YYY
DEBUG IMAPS: AUTH: XOAUTH
DEBUG IMAPS: AUTH: XOAUTH2
DEBUG IMAPS: protocolConnect login, host=imap.gmail.com, user=som...@gmail.com, password=<non-null>
DEBUG IMAPS: SASL authentication command trace suppressed
DEBUG IMAPS: SASL Mechanisms:
DEBUG IMAPS: XOAUTH2
DEBUG IMAPS:
DEBUG IMAPS: No SASL support
DEBUG IMAPS: SASL authentication failed
DEBUG IMAPS: LOGIN command trace suppressed
DEBUG IMAPS: LOGIN command result: A1 NO Empty username or password. YYYYYYYYYY
java.lang.RuntimeException: javax.mail.AuthenticationFailedException: Empty username or password. YYYYYYYYYY
此问题仅发生在已部署的节点上。确保提供程序是正确的路径并安装和使用最新版本的 App Engine SDK,以促进 IMAP 和 SMTP 套接字。已通过示例 servlet 和任务队列上的任务尝试触发。
提前感谢您的帮助。
【问题讨论】:
你设法让它工作了吗?你添加了 javax.mail.jar 吗? 我也有同样的问题。它使用 main 方法在本地很好地执行。将其部署到 glassfish 时,无法连接到 imap 或 smtp 服务器。我想回调不起作用。 【参考方案1】:我和你有同样的问题... 我一直在研究,我认为会话没有正确实例化。我附上了一张显示差异的图片。
图片顶部显示了变量“props”的内容,它与 AppEngine 项目(左图)的值与项目 Normal(右图)的值相同。 下图显示了 Session 变量的内容,其中包括变量 Properties 的内容。就像你在左边的例子中看到的那样,是空的。但在正确的情况下有值。
这是图片:http://ricorrico.comoj.com/misc/img2.jpg
确实是个bug,有什么解决办法吗?
非常感谢您。
问候!
【讨论】:
有什么进展吗?同样的问题,我看到在 GAE 与使用相同令牌的本地项目上执行时 BEARER 为空。【参考方案2】:不确定您是否仍然遇到此问题,但@user2606850 非常接近解决方案。使用属性集初始化会话不会正确初始化会话。
但是在创建会话后添加正确的属性,工作!
Properties props = new Properties();
Session session = Session.getInstance(props);
props = session.getProperties();
props.put("mail.imaps.sasl.enable", "true");
props.put("mail.imaps.sasl.mechanisms", "XOAUTH2");
IMAPSSLStore store = new IMAPSSLStore(session, unusedUrlName);
...
测试了一个部署到 AppEngine 的经过验证的工作。
【讨论】:
以上是关于在 App Engine 上使用 OAuth2 的 IMAP的主要内容,如果未能解决你的问题,请参考以下文章
如何在Google App Engine上防止“ImportError:没有名为oauth2client.client的模块”?
如何防止 Google App Engine 上出现“ImportError:没有名为 oauth2client.client 的模块”?
如何通过 Google Drive 和 App Engine SDK 使用 Oauth2 服务帐户
使用 OAuth 2.0 Google App Engine 刷新访问令牌
是否可以在没有 OAuth2 身份验证对话框的情况下从 Google App-Engine (python) 连接和查询 BigQuery 表?