Javamail gmail和OAuth2

时间:2017-08-07 15:17:17

标签: java gmail javamail google-oauth2

我正在尝试在网络应用程序(java 1.8 / tomcat8)中使用最新的javamail 1.6.0 api代表该应用程序的客户端用户发送电子邮件。有些客户使用gmail。 我不想让他们按照javamail FAQ的建议在他们的Google帐户中启用对不安全应用的访问,如果需要,我愿意实施oauth2。

为此,我在google developer console上执行了以下操作:

  • 创建了一个应用
  • 为应用创建了oauth2凭据(clientid, clientsecret)
  • 授予应用程序访问权限gmail api

然后,我使用google oauth client

在我的应用中实现了oauth2流程

构建授权重定向:

String url = 
        new GoogleAuthorizationCodeRequestUrl(clientId, 
            redirectUrl, 
            Collections.singleton(GmailScopes.GMAIL_SEND)
            ).setAccessType("offline").build();

成功重定向到google网站,我可以在其中对我的应用进行身份验证并授权我代表我发送邮件。我授权后成功重定向回我的应用程序,应用程序处理授权代码:

GoogleTokenResponse response =
                new GoogleAuthorizationCodeTokenRequest(
                        new NetHttpTransport(), 
                        new JacksonFactory(),
                      clientId, 
                      clientSecret,
                      code, 
                      redirectUrl)
                .execute();

(其中代码是返回的授权码) 这似乎有效,并返回访问令牌和刷新令牌。 (我也可以回到我的谷歌帐户设置,看看我已授权该应用程序发送电子邮件。

所以现在我想尝试使用访问令牌通过javamail api使用我的gmail用户名(我登录以授权应用程序),访问令牌和以下设置来发送邮件:

host = "smtp.gmail.com";
port = 587;
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.auth.mechanisms", "XOAUTH2");

javamail代码适用于其他smtp服务器。 我还打开调试来跟踪smtp流程

DEBUG: JavaMail version 1.6.0
DEBUG: successfully loaded resource: /META-INF/javamail.default.providers
DEBUG: Tables of loaded providers
DEBUG: Providers Listed By Class Name: {com.sun.mail.smtp.SMTPSSLTransport=javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Oracle], com.sun.mail.smtp.SMTPTransport=javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle], com.sun.mail.imap.IMAPSSLStore=javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Oracle], com.sun.mail.pop3.POP3SSLStore=javax.mail.Provider[STORE,pop3s,com.sun.mail.pop3.POP3SSLStore,Oracle], com.sun.mail.imap.IMAPStore=javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Oracle], com.sun.mail.pop3.POP3Store=javax.mail.Provider[STORE,pop3,com.sun.mail.pop3.POP3Store,Oracle]}
DEBUG: Providers Listed By Protocol: {imaps=javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Oracle], imap=javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Oracle], smtps=javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Oracle], pop3=javax.mail.Provider[STORE,pop3,com.sun.mail.pop3.POP3Store,Oracle], pop3s=javax.mail.Provider[STORE,pop3s,com.sun.mail.pop3.POP3SSLStore,Oracle], smtp=javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle]}
DEBUG: successfully loaded resource: /META-INF/javamail.default.address.map
DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle]
DEBUG SMTP: useEhlo true, useAuth true
DEBUG SMTP: trying to connect to host "smtp.gmail.com", port 587, isSSL false
220 smtp.gmail.com ESMTP c7sm3632131pfg.29 - gsmtp
DEBUG SMTP: connected to host "smtp.gmail.com", port: 587

EHLO 10.0.0.5
250-smtp.gmail.com at your service, [216.165.225.194]
250-SIZE 35882577
250-8BITMIME
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-PIPELINING
250-CHUNKING
250 SMTPUTF8
DEBUG SMTP: Found extension "SIZE", arg "35882577"
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "STARTTLS", arg ""
DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg ""
DEBUG SMTP: Found extension "PIPELINING", arg ""
DEBUG SMTP: Found extension "CHUNKING", arg ""
DEBUG SMTP: Found extension "SMTPUTF8", arg ""
STARTTLS
220 2.0.0 Ready to start TLS
EHLO 10.0.0.5
250-smtp.gmail.com at your service, [216.165.225.194]
250-SIZE 35882577
250-8BITMIME
250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH
250-ENHANCEDSTATUSCODES
250-PIPELINING
250-CHUNKING
250 SMTPUTF8
DEBUG SMTP: Found extension "SIZE", arg "35882577"
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "AUTH", arg "LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH"
DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg ""
DEBUG SMTP: Found extension "PIPELINING", arg ""
DEBUG SMTP: Found extension "CHUNKING", arg ""
DEBUG SMTP: Found extension "SMTPUTF8", arg ""
DEBUG SMTP: protocolConnect login, host=smtp.gmail.com, user=<myemail@gmail.com>, password=<non-null>
DEBUG SMTP: Attempt to authenticate using mechanisms: XOAUTH2
DEBUG SMTP: Using mechanism XOAUTH2
DEBUG SMTP: AUTH XOAUTH2 command trace suppressed
DEBUG SMTP: AUTH XOAUTH2 failed, THROW: 


 javax.mail.AuthenticationFailedException: OAUTH2 asked for more
...
DEBUG SMTP: AUTH XOAUTH2 failed
ERROR 2017-08-06 18:39:57,443  - send: 334 eyJzdGF0dXMiOiI0MDAiLCJzY2hlbWVzIjoiQmVhcmVyIiwic2NvcGUiOiJodHRwczovL21haWwuZ29vZ2xlLmNvbS8ifQ==

解码最后一行我发现错误是400状态,我将其解释为表示令牌无效。

我还使用google rest api验证了令牌是好的:

https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=<token>

我也尝试使用启用了ssl的端口465,但是遇到了同样的错误。

我在这里做错了什么?

2 个答案:

答案 0 :(得分:2)

这是对user2000974的回答的补充。 Google关于使用OAuth对IMAP或SMTP服务器Gmail > IMAP > OAuth 2.0 Mechanism进行身份验证的文档明确说明了以下内容

  

本文档定义了与IMAP AUTHENTICATE和SMTP AUTH命令一起使用的SASL XOAUTH2机制。此机制允许使用OAuth 2.0访问令牌对用户的Gmail帐户进行身份验证。

     

IMAP和SMTP访问的范围是https://mail.google.com/

我希望这会引导将来偶然发现这个问题的人找到正确的文档页面。

答案 1 :(得分:-1)

我尝试使用请求的范围,最后通过请求完全访问gmail帐户(scope =“https://mail.google.com/”)来使其工作。有限的documentation of the scopes表明发送邮件的具体范围应该有效,但显然没有。请求完全访问帐户有效,但似乎无法限制范围。它开始听起来像SMTP服务器只是不尊重有限的范围。