The reason is that Microsoft made changes to the email authentication earlier, which resulted in the failure to send. When searching for answers online, it is necessary to apply registration in Azure and add permissions according to the answer process. After these operations, authentication failed when using OAuth2 authentication. The code steps used to compare answers are completely consistent, but it is unclear whether the question is set up in Azure or something else.
Here is the code:
package com.tianrun.common.email;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Properties;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
public class OAuth2Helper {
public static void main(String[] args) throws Exception {
String accessToken = getAccessToken();
sendEmail(accessToken, "****@outlook.com", "******", "Subject", "Body of the email");
}
private static String getAccessToken() throws Exception {
String clientId = "****";
String clientSecret = "****";
String tenantId = "*****";
String scope = "https://outlook.office365.com/.default";
String authUrl = "https://login.microsoftonline.com/" + tenantId + "/oauth2/v2.0/token";
URL url = new URL(authUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setDoOutput(true);
String postParams = "client_id=" + clientId +
"&scope=" + scope +
"&client_secret=" + clientSecret +
"&grant_type=client_credentials";
conn.getOutputStream().write(postParams.getBytes());
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String inputLine;
StringBuffer content = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
content.append(inputLine);
}
in.close();
conn.disconnect();
// Parse the JSON response to get the access token
String accessToken = content.toString().split("\"access_token\":\"")[1].split("\"")[0];
System.out.println(accessToken);
return accessToken;
}
private static void sendEmail(String accessToken, String sender, String recipient, String subject, String body)
throws MessagingException {
Properties props = new Properties();
props.setProperty("mail.debug", "true");
props.setProperty("mail.smtp.auth", "true");
props.setProperty("mail.host", "smtp.office365.com");
props.setProperty("mail.transport.protocol", "smtp");
props.setProperty("mail.smtp.port", "587");
props.put("mail.smtp.ssl.protocols", "TLSv1.2");
props.put("mail.smtp.starttls.enable", "true");
// Create a custom Authenticator with the OAuth2 access token
Session session = Session.getInstance(props, null);
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(sender));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipient));
message.setSubject(subject);
message.setText(body);
Transport.send(message);
}
}
This is an error log
javax.mail.AuthenticationfailedException: 535 5.7.3 Authentication unsuccesful [SI2PR6CA0e12.apcprd6.prod.outlook.com 224-11-1T96:16:51.8952 809172787151CE]
I tried the following Java code to send an email to an Outlook account using the Mail.Send
scope and successfully sent the email to the Outlook account.
OutlookMailSender.java :
import com.azure.identity.InteractiveBrowserCredential;
import com.azure.identity.InteractiveBrowserCredentialBuilder;
import com.microsoft.graph.authentication.TokenCredentialAuthProvider;
import com.microsoft.graph.models.*;
import com.microsoft.graph.requests.GraphServiceClient;
import java.util.Arrays;
public class OutlookMailSender {
private static final String CLIENT_ID = "<clientID>";
private static final String TENANT_ID = "common";
private static final String[] SCOPES = {"Mail.Send"};
public static void main(String[] args) {
try {
InteractiveBrowserCredential credential = new InteractiveBrowserCredentialBuilder()
.clientId(CLIENT_ID)
.tenantId(TENANT_ID)
.build();
TokenCredentialAuthProvider authProvider = new TokenCredentialAuthProvider(Arrays.asList(SCOPES), credential);
GraphServiceClient<?> graphClient = GraphServiceClient
.builder()
.authenticationProvider(authProvider)
.buildClient();
Message message = new Message();
message.subject = "Holiday Notice";
ItemBody body = new ItemBody();
body.contentType = BodyType.TEXT;
body.content = "I am currently on holiday and will respond to your email upon my return.";
message.body = body;
Recipient toRecipient = new Recipient();
toRecipient.emailAddress = new EmailAddress();
toRecipient.emailAddress.address = "sender@outlook.com";
Recipient ccRecipient = new Recipient();
ccRecipient.emailAddress = new EmailAddress();
ccRecipient.emailAddress.address = "receiver@outlook.com";
message.toRecipients = Arrays.asList(toRecipient);
message.ccRecipients = Arrays.asList(ccRecipient);
UserSendMailParameterSet sendMailParameterSet = new UserSendMailParameterSet();
sendMailParameterSet.message = message;
sendMailParameterSet.saveToSentItems = Boolean.FALSE;
graphClient.me().sendMail(sendMailParameterSet).buildRequest().post();
System.out.println("Email sent successfully!");
} catch (Exception e) {
System.err.println("Error sending email: " + e.getMessage());
}
}
}
pom.xml :
<dependencies>
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-identity</artifactId>
<version>1.9.0</version>
</dependency>
<dependency>
<groupId>com.microsoft.graph</groupId>
<artifactId>microsoft-graph</artifactId>
<version>5.13.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.0-alpha1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.0-alpha1</version>
</dependency>
</dependencies>
I have added the below URL in the Azure AD app's Authentication under Mobile and desktop applications
.
http://localhost
I enabled the public client flow
as shown below.
I have added the Mail.Send scope in the API permissions and Granted admin consent
for it, as shown below.
Output :
When I ran the code, it redirected me to log in to my Outlook account, as shown below.
I successfully authenticated to my outlook account.
The email was sent successfully, as shown below.
The email was sent to Outlook as shown below.