Javamail Gmail 和 OAuth2

标签 java gmail jakarta-mail google-oauth

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

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

  • 创建了一个应用
  • 为应用程序创建了 oauth2 凭据(clientid、 客户 secret )
  • 授予应用访问 gmail api 的权限

然后,我使用 google oauth client 在我的应用程序中实现了 oauth2 流程。

授权重定向已构建:

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

这成功地重定向到谷歌网站,我可以在其中验证并授权我的应用程序代表我发送邮件。在我授权后,它成功重定向回我的应用程序,并且该应用程序处理授权代码:

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

(其中code为返回的授权码) 这似乎有效,并返回访问 token 和刷新 token 。 (我还可以返回我的 Google 帐户设置并查看我已授权该应用发送电子邮件。

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

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 状态,我将其解释为 token 无效。

我还使用 Google Rest API 验证了该 token 是否正常:

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

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

我在这里做错了什么?

最佳答案

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

This document defines the SASL XOAUTH2 mechanism for use with the IMAP AUTHENTICATE and SMTP AUTH commands. This mechanism allows the use of OAuth 2.0 Access Tokens to authenticate to a user's Gmail account.

The scope for IMAP and SMTP access is https://mail.google.com/.

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

关于Javamail Gmail 和 OAuth2,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45550385/

相关文章:

java - 如何在Qt中使用JNI创建字符串数组

java - 如何在 win 7 64 位中不使用任何 DSN 将我的 Java SE 程序连接到 MS Access DB

cURL 终端命令成功执行,而 libcurl 程序没有

email - 将邮件发送到 gmail 时,带有 href 的 anchor 标记作为 http 以外的 anchor 标记不起作用

java - ClassNotFoundException com.sun.mail.util.SharedByteArrayInputStream

java - 如何使用 spring-social-security SocialAuthenticationFilter 指定 OAuth2 范围?

java - 测量不同排序方法的时间

java - 如何在不频繁轮询的情况下了解 GMail 上的传入电子邮件?

email - 托米。发送带附件的邮件

java - 不能用Java发送邮件