azure Java Oauth2使用Office 365发送电子邮件

7lrncoxx  于 2022-11-25  发布在  Java
关注(0)|答案(1)|浏览(535)

我正在使用Java 1.8,Jakarta email(版本2.1.0)连接到Microsoft 365,使用OAuth进行SMTP身份验证。客户端需要使用Oauth身份验证,而不是基本的SMTP身份验证。阅读文档https://learn.microsoft.com/en-us/exchange/client-developer...和许多其他资源后,我已将AD配置为该权限:

Microsoft Graph    offline_access
Microsoft Graph    User.Read
Microsoft Graph    Mail.Send
Microsoft Graph    openid
Microsoft Graph    IMAP.AccessAsUser.All
Microsoft Graph    SMTP.Send

Office 365 Exchange Online    full_access_as_app
Office 365 Exchange Online    POP.AccessAsApp
Office 365 Exchange Online    Mail.Send
Office 365 Exchange Online    IMAP.AccessAsApp

已在Azure https://learn.microsoft.com/en-us/exchange/clients...上使用PowerShell激活SMTP客户端身份验证

PS C:\Users\dx-2102> Get-TransportConfig | Format-List SmtpClientAuthenticationDisabled   
SmtpClientAuthenticationDisabled : False

用于发送电子邮件的实现代码(Java):

Properties prop = new Properties();
prop.put("mail.smtp.auth", "true");
prop.put("mail.smtp.starttls.enable", "true");
prop.put("mail.smtp.host", emailSettings.getSmtp().getHostname());
prop.put("mail.smtp.port", emailSettings.getSmtp().getPort());
prop.put("mail.debug", "true");
prop.put("mail.debug.auth", "true");
prop.put("mail.smtp.auth.xoauth2.disable", "false");
prop.put("mail.smtp.auth.mechanisms", "XOAUTH2");
prop.put("mail.transport.protocol", "smtp");
prop.put("mail.smtp.auth.login.disable", "true");
prop.put("mail.smtp.auth.plain.disable", "true");

session = Session.getInstance(prop);
session.setDebug(true);
String accessToken = getOAuth2AccessToken();

transport = session.getTransport("smtp");
transport.connect(emailSettings.getSmtp().getHostname(), emailSettings.getSmtp().getPort(), emailSettings.getSmtp().getUsername(), tokenForSmtp(emailSettings.getSmtp().getUsername(), accessToken));
/* -- */ 
transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients());
transport.close();

从Azure AD调用/获取令牌的方法,作为响应,我们将获得一个带有过期时间的令牌。

String url = "https://login.microsoftonline.com/" + Tenant_ID + "/oauth2/token";

MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("grant_type", "client_credentials");
map.add("response_type", "code");
map.add("client_id", ClientId);
map.add("client_secret", ClientSecret);
map.add("scope","openid offline_access https%3A%2F%2Foutlook.office365.com%2FSMTP.Send ");

RestTemplate restTemplate = new RestTemplate();
ResponseEntity<AzureResponse> response = restTemplate.postForEntity(url, map, AzureResponse.class);

一种在SMTP发送邮件过程中准备发送令牌的方法

private String tokenForSmtp(String userName, String accessToken) {
    final String ctrlA=Character.toString((char) 1);
    final String coded= "user=" + userName + ctrlA+"auth=Bearer " + accessToken + ctrlA+ctrlA;
    return Base64.getEncoder().encodeToString(coded.getBytes());
    //base64("user=" + userName + "^Aauth=Bearer " + accessToken + "^A^A")
}

发送SMTP电子邮件后,我收到错误:

AUTH XOAUTH2 dXNlcj1zb2ZhQHNvbHV0aW9uZmFjdG9yeWFnLm9ub...=
535 5.7.3 Authentication unsuccessful [VI1PR0202CA0024.eurprd02.prod.outlook.com]
Error on sending email: 535 5.7.3 Authentication unsuccessful [VI1PR0202CA0024.eurprd02.prod.outlook.com]

除了openid、offline_access和https://outlook.office.com/SMTP.Send之外,我是否需要Azure AD中的其他令牌范围?或者我是否错过了Azure配置中的其他内容?如果有人有一个Java示例,说明应该如何完成,请随时附上它。此外,如果您有一些屏幕截图,说明在Azure帐户上设置什么。

mznpcxlj

mznpcxlj1#

您是否尝试直接传递access_token作为密码?
另一件事是启用SMTP_AUTH的用户,你发送自2022年以来,我猜,见https://learn.microsoft.com/en-us/exchange/clients-and-mobile-in-exchange-online/authenticated-client-smtp-submission

相关问题