由于 Google 将在其 SMTP 中放弃对 PLAIN 身份验证的支持,我想迁移到基于 OAuth2 的身份验证。
在 this 文档之后,我开始设置服务帐户并创建 json 格式的密钥。
然后尝试使用此代码进行身份验证:
import com.google.auth.oauth2.ServiceAccountCredentials;
import com.sun.mail.smtp.SMTPTransport;
import jakarta.mail.Session;
import java.io.InputStream;
import java.util.Base64;
import java.util.Collections;
import java.util.Properties;
public class ForSendingEmailOauthAdapater {
void send() throws Exception {
InputStream secret = this.getClass().getClassLoader().getResourceAsStream("keys.json");
String email = "[email protected]"; // in my production code this set to the related service account email
GoogleCredentials credentials = ServiceAccountCredentials.fromStream(secret)
.createScoped(Collections.singletonList("https://mail.google.com/"));
credentials.refreshIfExpired();
String token = credentials
.getAccessToken()
.getTokenValue();
Properties props = new Properties();
props.put("mail.smtp", "true");
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.auth.mechanisms", "XOAUTH2");
props.put("mail.smtp.starttls.enable", "true");
Session session = Session.getInstance(props);
session.setDebug(true);
SMTPTransport transport = (SMTPTransport) session.getTransport("smtp");
transport.connect("smtp.gmail.com", 587, email, null);
String authString = "user=" + email + "\001auth=Bearer " + token + "\001\001";
String base64oauth2String = Base64.getEncoder().encodeToString(authString.getBytes());
transport.issueCommand("AUTH XOAUTH2 " + base64oauth2String, 235);
}
}
不幸的是失败了:
STARTTLS
220 2.0.0 Ready to start TLS
EHLO <myhostname>
250-smtp.gmail.com at your service, [89.64.21.109]
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 ""
AUTH XOAUTH2 <base64 encoded user&token>
555-5.5.2 Syntax error, goodbye. For more information, go to
555-5.5.2 https://support.google.com/a/answer/3221692 and review RFC 5321
555 5.5.2 specifications. a640c23a62f3a-a725f5e1b52sm262436666b.135 - gsmtp
它看起来与此处几乎相同(请参阅 SMTP 部分)。
555-5.5.2 错误表明它是一个无效的电子邮件地址(例如收件人的),但它在身份验证时失败,而不是发送电子邮件的事件失败。
我也通过curl尝试了相同的操作,但失败并出现相同的错误:
curl -sv --url 'smtp://smtp.gmail.com:587' \
--ssl-reqd \
--login-options 'AUTH=XOAUTH2' --oauth2-bearer <access_token> \
--user <service account email> \
--mail-from [email protected] --mail-rcpt [email protected]
有什么想法我做错了什么吗?
您还有问题吗?
对我来说奇怪的是您试图直接使用服务帐户进行身份验证。这可能是问题的原因,因为它不是 Gmail 帐户 (smtp.gmail.com 是 gmail smtp 服务器)。
您链接的指南解释了如何使用服务帐户来模拟用户(仅限工作区)。
您应该尝试使用同意屏幕来作为 Gmail 用户进行身份验证并获取令牌,然后在 xoauth2 身份验证中发送该令牌。
查看Gmail API java 快速入门,您可以使用其中的身份验证流程以 gmail 用户身份登录,然后使用其余代码。我知道您不想使用 Gmail API,我只是链接此示例,因为身份验证过程与您的用例相关。