我正在尝试使用
jakarta.mail 2.0.1
发送电子邮件。
下面提到的错误最近开始发生。我不确定是什么原因造成的,但我怀疑它可能与 Outlook 365 和 SMTP 设置有关。
然而,当我尝试这样做时,出现以下错误:
2023-07-28T00:36:08.077359363Z javax.mail.AuthenticationFailedException: 535 5.7.139 Authentication unsuccessful, the request did not meet the criteria to be authenticated successfully. Contact your administrator. [xxxxx 2023-07-28T00:36:07.942Z xxxxx]
2023-07-28T00:36:08.077401363Z
2023-07-28T00:36:08.077407063Z at com.sun.mail.smtp.SMTPTransport$Authenticator.authenticate(SMTPTransport.java:947)
2023-07-28T00:36:08.077411063Z at com.sun.mail.smtp.SMTPTransport.authenticate(SMTPTransport.java:858)
2023-07-28T00:36:08.077414563Z at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:762)
2023-07-28T00:36:08.077417963Z at javax.mail.Service.connect(Service.java:342)
2023-07-28T00:36:08.077427964Z at javax.mail.Service.connect(Service.java:222)
2023-07-28T00:36:08.077431564Z at javax.mail.Service.connect(Service.java:243)
2023-07-28T00:36:08.077434864Z at javax.mail.Transport.send0(Transport.java:228)
2023-07-28T00:36:08.077456364Z at javax.mail.Transport.send(Transport.java:150)
2023-07-28T00:36:08.077459864Z at com.nomnom.communicationserver.communication.SMTPHelper.sendEmail(SMTPHelper.java:324)
2023-07-28T00:36:08.081170884Z at com.nomnom.communicationserver.servlet.SenderServlet.doPost(SenderServlet.java:191)
该程序之前已经运行过,但是最近开始出现上述错误。
我设置 Transporter 的配置如下:
Properties smtpProps = new Properties();
// SMTP
smtpProps.put("mail.smtp.auth", "true");
smtpProps.put("mail.smtp.starttls.enable", "true");
smtpProps.put("mail.smtp.auth.mechanisms", "XOAUTH2");
smtpProps.put("mail.smtp.host", "smtp.office365.com");
smtpProps.put("mail.smtp.port", "587"); // required for outlook
smtpSession = Session.getInstance(smtpProps);
smtpSession.setDebug(true);
transport = (SMTPTransport) smtpSession.getTransport("smtp");
除此之外,这是我用来发送请求的代码:
private static String acquireToken() throws Exception {
ConfidentialClientApplication app = ConfidentialClientApplication.builder(
dotenv.get("CLIENT_ID"),
ClientCredentialFactory.createFromSecret(dotenv.get("CLIENT_SECRET")))
.authority(dotenv.get("CLIENT_AUTHORITY"))
.build();
ClientCredentialParameters clientCredentialParam = ClientCredentialParameters.builder(
Collections.singleton(scope))
.build();
CompletableFuture<IAuthenticationResult> future = app.acquireToken(clientCredentialParam);
IAuthenticationResult result = future.get();
return result.accessToken();
}
public void sendEmail(String destination) throws Exception {
MimeMessage message = new MimeMessage(session);
// [...]
// Connect if not already connected
if (!transport.isConnected()) {
String accessToken = acquireToken();
transport.connect("smtp.office365.com", dotenv.get("MAIL_USERNAME"), accessToken);
}
transport.sendMessage(message, message.getAllRecipients());
}
我尝试过的事情:
由于某种原因,我无法为电子邮件创建应用程序密码。还应该提到的是,该电子邮件是工作帐户并且是 Outlook 电子邮件。我注意到其他人的 Outlook 个人帐户也遇到了类似的问题。但是,我还没有看到工作帐户解决方案中提到的错误。
如果需要更多信息,请随时索取:)
我找出了导致问题的原因。这个问题不是由 MFA 或类似的东西引起的。这是由于
accessToken
没有配置正确的权限造成的。
我解决这个问题的方法是进入“应用程序注册”->“API 权限”。 此后,应用程序需要
SMTP.SendAsApp
权限。我之前已经添加了 Mail.Send
权限。然而这还不够。还应该提到的是,它需要在 Office 365 Exchange Online
类别下。
我定位问题的方式: 如果其他人偶然发现这个问题,我建议您获取 oauth 访问令牌并将其放入像 jwt.io 这样的网站中。在这里可以看到令牌的范围以及其他内容。这帮助我看到了缺少的权限。
这是使用旧版身份验证时存在的一个广泛存在的问题,您可以找到很多有关该问题的帖子。您应该检查以下几件事:
使用 Exchange Online PowerShell 验证应用程序用于连接到 Microsoft 365 或 Office 365 的许可邮箱上是否启用了经过身份验证的 SMTP 提交(也称为
SMTP AUTH
)。
在正在使用的许可邮箱上禁用多重身份验证 (MFA):
通过将“启用安全默认值”切换为“否”来禁用 Azure 安全默认值:
将用户从阻止旧身份验证的条件访问策略中排除:
这些设置会阻止
Legacy Authentication
。请参阅错误:身份验证失败了解更多信息。