Email OAuth2 IMAP访问GMail服务帐户

Email OAuth2 IMAP访问GMail服务帐户,email,oauth-2.0,jakarta-mail,imap,gmail-imap,Email,Oauth 2.0,Jakarta Mail,Imap,Gmail Imap,我正在尝试将通过IMAP协议访问Gmail帐户的Java应用程序从用户名/密码身份验证迁移到OAuth2(目前该应用程序正在使用“启用不太安全的应用程序”) 我从谷歌控制台下载我的服务帐户的JSON密钥开始,并设法获得一个访问令牌: GoogleCredentials credentials = ServiceAccountCredentials.fromStream( new FileInputStream("my-account.json")) .crea

我正在尝试将通过IMAP协议访问Gmail帐户的Java应用程序从用户名/密码身份验证迁移到OAuth2(目前该应用程序正在使用“启用不太安全的应用程序”)

我从谷歌控制台下载我的服务帐户的JSON密钥开始,并设法获得一个访问令牌:

GoogleCredentials credentials = ServiceAccountCredentials.fromStream(
    new FileInputStream("my-account.json"))
    .createScoped(Collections.singletonList("https://mail.google.com/"));

AccessToken accessToken = credentials.refreshAccessToken();
System.out.println(accessToken.getTokenValue());
        System.out.println(accessToken.getTokenValue());
这将创建我可以通过访问验证的访问令牌

答复是:

{
  "issued_to": "XXXX",
  "audience": "XXXX",
  "scope": "https://mail.google.com/",
  "expires_in": 3588,
  "access_type": "online"
}
当我尝试使用此访问令牌访问IMAP帐户时出现问题。 每次我获取时,查找都失败。下面是详细的JavaMail日志:

DEBUG: JavaMail version 1.6.2
DEBUG: successfully loaded resource: /META-INF/javamail.default.address.map
DEBUG: setDebug: JavaMail version 1.6.2
DEBUG: getProvider() returning javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Oracle]
DEBUG IMAP: mail.imap.fetchsize: 16384
DEBUG IMAP: mail.imap.ignorebodystructuresize: false
DEBUG IMAP: mail.imap.statuscachetimeout: 1000
DEBUG IMAP: mail.imap.appendbuffersize: -1
DEBUG IMAP: mail.imap.minidletime: 10
DEBUG IMAP: closeFoldersOnStoreFailure
DEBUG IMAP: trying to connect to host "imap.gmail.com", port 993, isSSL true
* OK Gimap ready for requests from [REMOVED_LOCAL_IP] b8mb121231068edr
A0 CAPABILITY
* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 XYZZY SASL-IR AUTH=XOAUTH2 AUTH=PLAIN AUTH=PLAIN-CLIENTTOKEN AUTH=OAUTHBEARER AUTH=XOAUTH
A0 OK Thats all she wrote! b8mb121231068edr
DEBUG IMAP: AUTH: XOAUTH2
DEBUG IMAP: AUTH: PLAIN
DEBUG IMAP: AUTH: PLAIN-CLIENTTOKEN
DEBUG IMAP: AUTH: OAUTHBEARER
DEBUG IMAP: AUTH: XOAUTH
DEBUG IMAP: protocolConnect login, host=imap.gmail.com, user=etmfdev@etmf-dev.iam.gserviceaccount.com, password=<non-null>
DEBUG IMAP: mechanism PLAIN disabled by property: mail.imap.auth.plain.disable
DEBUG IMAP: mechanism LOGIN disabled by property: mail.imap.auth.login.disable
DEBUG IMAP: mechanism NTLM disabled by property: mail.imap.auth.ntlm.disable
A1 AUTHENTICATE XOAUTH2 [REMOVED_BASE64_ENCODED_USER_PLUS_TOKEN]
+ eyJzdGF0dXMiOiI0MDAiLCJzY2hlbWVzIjoiQmVhcmVyIiwic2NvcGUiOiJodHRwczovL21haWwuZ29vZ2xlLmNvbS8ifQ==
[REMOVED_BASE64_ENCODED_USER_PLUS_TOKEN]
A1 NO Lookup failed b8mb121231068edr
你知道根本原因是什么吗?这是谷歌账户设置中的问题还是我正在使用的代码中的问题

使用的Java代码如下

GoogleCredentials credentials = ServiceAccountCredentials.fromStream(
    new FileInputStream("my-account.json"))
    .createScoped(Collections.singletonList("https://mail.google.com/"));

AccessToken accessToken = credentials.refreshAccessToken();

Properties props = new Properties();
props.put("mail.imap.ssl.enable", "true");
props.put("mail.imaps.sasl.enable", "true");
props.put("mail.imaps.sasl.mechanisms", "XOAUTH2");
props.put("mail.imap.auth.xoauth2.disable", "false");
props.put("mail.imap.auth.login.disable", "true");
props.put("mail.imap.auth.plain.disable", "true");
props.put("mail.imap.auth.ntlm.disable", "true");
props.put("mail.debug", "true");
props.put("mail.debug.auth", "true");

Session session = Session.getInstance(props);
session.setDebug(true);
Store store = session.getStore("imap");

store.connect("imap.gmail.com", imapEmailAddress, accessToken.getTokenValue());

您是否向服务帐户授予了域范围的权限并模拟了该用户?在此期间,我尝试了一件事,即将imapEmailAddress从JSON文件中提到的client_电子邮件(以…iam.gserviceaccount.com结尾的电子邮件)更改为以前使用用户名/密码身份验证的自定义域电子邮件。在这种情况下,我只是得到“A1 NO[AUTHENTICATIONFAILED]无效凭据(Failure)”,而不是查找失败。我已启用“Enable G Suite Domain wide Delegation”。我想您可能错过了模拟步骤。尝试添加
.createDelegate(“要模拟的电子邮件地址”)在构建凭据时(即,就在
.createScoped
之后)。添加.createDelegate(“我的电子邮件”)后,我得到以下信息“java.io.IOException:获取服务帐户的访问令牌时出错:401 Unauthorized POST”。Line credentials.refreshAccessToken()引发此异常。您是否已向服务帐户授予域范围的权限并模拟用户?在此期间,我尝试了一件事,即从JSON文件中提到的客户端电子邮件(以…iam.gserviceaccount.com结尾的电子邮件)更改imapEmailAddress发送到以前使用用户名/密码身份验证的自定义域的电子邮件。在这种情况下,我只是得到“A1 NO[AUTHENTICATIONFAILED]无效凭据(Failure)”,而不是查找失败。我已启用“Enable G Suite Domain wide Delegation”。我想您可能错过了模拟步骤。尝试添加
.createDelegate(“要模拟的电子邮件地址”)在构建凭据时(即,就在
.createScoped
之后)。添加.createDelegate(“我的电子邮件”)后,我得到以下信息“java.io.IOException:获取服务帐户的访问令牌时出错:401 Unauthorized POST”。Line credentials.refreshAccessToken()引发此异常。
GoogleCredentials credentials = ServiceAccountCredentials.fromStream(
    new FileInputStream("my-account.json"))
    .createScoped(Collections.singletonList("https://mail.google.com/"));

AccessToken accessToken = credentials.refreshAccessToken();

Properties props = new Properties();
props.put("mail.imap.ssl.enable", "true");
props.put("mail.imaps.sasl.enable", "true");
props.put("mail.imaps.sasl.mechanisms", "XOAUTH2");
props.put("mail.imap.auth.xoauth2.disable", "false");
props.put("mail.imap.auth.login.disable", "true");
props.put("mail.imap.auth.plain.disable", "true");
props.put("mail.imap.auth.ntlm.disable", "true");
props.put("mail.debug", "true");
props.put("mail.debug.auth", "true");

Session session = Session.getInstance(props);
session.setDebug(true);
Store store = session.getStore("imap");

store.connect("imap.gmail.com", imapEmailAddress, accessToken.getTokenValue());