【发布时间】:2021-03-31 04:13:51
【问题描述】:
我目前正在尝试将 OAuth2 集成到 Java 应用程序的现有电子邮件基础架构中。该应用程序使用 Jakarta 邮件,根据他们的文档支持 OAuth2 (https://eclipse-ee4j.github.io/mail/OAuth2)。出于某种原因,我正在努力连接到 Office 365 SMTP 服务器,而通过 IMAP 连接工作得非常好。所以这是我到目前为止一直在做的事情:
- 创建 Office 365 开发人员帐户,填充用户和用户数据。
- 登录azure后端,配置应用注册,包括回调url等和以下api权限:https://i.stack.imgur.com/lXjER.png
- 使用以下认证 url 创建认证码:
https://login.microsoftonline.com/{my_tenant_id}/oauth2/v2.0/authorize?
client_id={my_client_id}&
state=state_to_check&
redirect_uri=http://localhost:5555/callback/authorization&
scope=offline_access https://outlook.office.com/IMAP.AccessAsUser.All https://outlook.office.com/POP.AccessAsUser.All https://outlook.office.com/SMTP.Send
&response_type=code
如您所见,我正在使用以下范围:
offline_access
https://outlook.office.com/IMAP.AccessAsUser.All
https://outlook.office.com/POP.AccessAsUser.All
https://outlook.office.com/SMTP.Send
- 检索授权码并使用它来获取刷新和访问令牌,这会得到以下响应:
{
"token_type": "Bearer",
"scope": "https://outlook.office.com/IMAP.AccessAsUser.All https://outlook.office.com/Mail.Read https://outlook.office.com/Mail.Read.All https://outlook.office.com/Mail.Read.Shared https://outlook.office.com/Mail.ReadBasic https://outlook.office.com/Mail.ReadWrite https://outlook.office.com/Mail.Send https://outlook.office.com/Mail.Send.All https://outlook.office.com/Mail.Send.Shared https://outlook.office.com/POP.AccessAsUser.All https://outlook.office.com/SMTP.Send https://outlook.office.com/User.Read",
"expires_in": 3599,
"ext_expires_in": 3599,
"access_token": ...,
"refresh_token": ...
}
所以我想说,到目前为止,关于 OAuth 2.0 身份验证过程,一切都按预期工作。现在,继续使用访问令牌来访问用户电子邮件帐户,我在应用程序的电子邮件逻辑中添加了以下几行以通过 OAuth 启用 IMAP:
[more props stuff here]
if (useOauth) {
props.put("mail." + protocol + ".auth", "true");
props.put("mail." + protocol + ".auth.mechanisms", "XOAUTH2");
props.put("mail." + protocol + ".auth.login.disable", "true");
props.put("mail." + protocol + ".auth.plain.disable", "true");
}
return Session.getInstance(props);
这工作得很好,我可以通过 IMAP 连接、读取文件夹、消息等。我的问题是,如果我尝试以类似的方式修改 SMTP 代码,我会收到以下错误:
Exception in thread "main" jakarta.mail.AuthenticationFailedException: 451 4.7.0 Temporary server error. Please try again later. PRX4 [AM9P191CA0011.EURP191.PROD.OUTLOOK.COM]
at com.sun.mail.smtp.SMTPTransport$Authenticator.authenticate(SMTPTransport.java:947)
at com.sun.mail.smtp.SMTPTransport.authenticate(SMTPTransport.java:858)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:762)
at jakarta.mail.Service.connect(Service.java:342)
at jakarta.mail.Service.connect(Service.java:222)
at jakarta.mail.Service.connect(Service.java:243)
at Application.main(Application.java:52)
我查看了我在 github (https://github.com/eino-makitalo/vesa-mailtest/tree/master/src/main) 上找到的以下示例应用程序以及 stackoverflow 上的几个答案,看看我是否遗漏了任何专门为 SMTP 设置的属性,但我一直遇到同样的错误,使用以下配置:
Properties props = new Properties();
props.put("mail.smtp.auth.xoauth2.disable", "false");
props.put("mail.smtp.auth.mechanisms", "XOAUTH2");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.host","smtp.office365.com");
props.put("mail.smtp.port", "587");
props.put("mail.transport.protocol","smtp");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.auth.login.disable","true");
props.put("mail.smtp.auth.plain.disable","true");
props.put("mail.debug.auth", "true");
Session session = Session.getInstance(props);
session.setDebug(true);
Transport transport = session.getTransport("smtp");
transport.connect( username, token);
现在我希望,也许有人以前遇到过这个问题,可以帮助我。我能找到的关于上述异常 postet 的唯一问题都与自定义交换服务器设置以及如何在这些服务器上配置 DNS 设置有关。但我认为这与我无关,因为我没有尝试连接到自定义交换服务器。
更新: 所以我尝试了与 google 服务相同的配置,它适用于 IMAP 和 SMTP,所以肯定是 Microsoft 服务的问题。但我仍然不确定我还能做些什么来让它发挥作用。
【问题讨论】:
-
您好,有一个问题:您的 Java 应用程序是否只有后端,或者您在使用 IMAP 登录检索消息时是否有任何真人用户交互?我正在处理这样一个应用程序,需要使用 IMAP 与 jakarta 邮件一起从微软服务器获取邮件,完全后端无需任何用户交互。其他我不想使用 Graph 进行交互的任何配置。
标签: java oauth-2.0 smtp office365 jakarta-mail