I'm using Java 1.8, Jakarta email (version 2.1.0) to connect to Microsoft 365 using OAuth for authentication with SMTP. Client has required to use Oauth authenticate, not basic smtp authentification. After reading of documentation https://learn.microsoft.com/en-us/exchange/client-developer... and lots other resources I have configured AD to this permissions:
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
Activated SMTP client authentication using PowerShell on Azure https://learn.microsoft.com/en-us/exchange/clients...
PS C:\Users\dx-2102> Get-TransportConfig | Format-List SmtpClientAuthenticationDisabled
SmtpClientAuthenticationDisabled : False
implemented code for send email (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();
method for calling/getting token from Azure AD, in response we get a token with expiration time.
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);
method for preparing token for sending within the SMTP send-mail process
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")
}
After send of SMTP email I receive error:
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]
Do I need a some other token scope's from Azure AD other then openid, offline_access and https://outlook.office.com/SMTP.Send ? Or do I miss something else in the configuration of Azure? Of someone has a Java example of how it should be done, please feel free to attach it. Also if you have some screenshots of what to set up on the Azure account.