From 5256ea99e7d0b4521f516662c49ddac98d5ff402 Mon Sep 17 00:00:00 2001
From: sgoeschl
Date: Fri, 22 Nov 2024 22:09:51 +0100
Subject: [PATCH 01/13] EMAIL-163 Support for OAuth2 authentication
---
.../commons/mail2/core/EmailConstants.java | 3 ++
.../apache/commons/mail2/jakarta/Email.java | 36 +++++++++++++++++++
.../commons/mail2/jakarta/EmailTest.java | 12 +++++++
.../org/apache/commons/mail2/javax/Email.java | 36 +++++++++++++++++++
.../apache/commons/mail2/javax/EmailTest.java | 12 +++++++
5 files changed, 99 insertions(+)
diff --git a/commons-email2-core/src/main/java/org/apache/commons/mail2/core/EmailConstants.java b/commons-email2-core/src/main/java/org/apache/commons/mail2/core/EmailConstants.java
index 38e2e0077..61030067b 100644
--- a/commons-email2-core/src/main/java/org/apache/commons/mail2/core/EmailConstants.java
+++ b/commons-email2-core/src/main/java/org/apache/commons/mail2/core/EmailConstants.java
@@ -56,6 +56,9 @@ public final class EmailConstants {
/** If set to true, tries to authenticate the user using the AUTH command. */
public static final String MAIL_SMTP_AUTH = "mail.smtp.auth";
+ /** If set to true, tries to authenticate the user using the OAuth2. */
+ public static final String MAIL_SMTP_AUTH_MECHANISMS = "mail.smtp.auth.mechanisms";
+
/** The SMTP user name. */
public static final String MAIL_SMTP_USER = "mail.smtp.user";
diff --git a/commons-email2-jakarta/src/main/java/org/apache/commons/mail2/jakarta/Email.java b/commons-email2-jakarta/src/main/java/org/apache/commons/mail2/jakarta/Email.java
index bf5819aa0..dd644730b 100644
--- a/commons-email2-jakarta/src/main/java/org/apache/commons/mail2/jakarta/Email.java
+++ b/commons-email2-jakarta/src/main/java/org/apache/commons/mail2/jakarta/Email.java
@@ -214,6 +214,11 @@ public abstract class Email {
*/
private boolean startTlsRequired;
+ /**
+ * If true, use OAuth2 for authentication.
+ */
+ private boolean oauth2Required;
+
/**
* Does the current transport use SSL/TLS encryption upon connection?
*/
@@ -818,6 +823,10 @@ public Session getMailSession() throws EmailException {
properties.setProperty(EmailConstants.MAIL_SMTP_AUTH, "true");
}
+ if(isOAuth2Required()) {
+ properties.put(EmailConstants.MAIL_SMTP_AUTH_MECHANISMS, "XOAUTH2");
+ }
+
if (isSSLOnConnect()) {
properties.setProperty(EmailConstants.MAIL_PORT, sslSmtpPort);
properties.setProperty(EmailConstants.MAIL_SMTP_SOCKET_FACTORY_PORT, sslSmtpPort);
@@ -1057,6 +1066,16 @@ public boolean isStartTLSRequired() {
return startTlsRequired;
}
+ /**
+ * Tests whether the client is configured to use OAuth2 authentication.
+ *
+ * @return true if using OAuth2 for authentication, false otherwise.
+ * @since 2.0
+ */
+ public boolean isOAuth2Required() {
+ return oauth2Required;
+ }
+
/**
* Sends the email. Internally we build a MimeMessage which is afterwards sent to the SMTP server.
*
@@ -1635,6 +1654,23 @@ public Email setStartTLSRequired(final boolean startTlsRequired) {
return this;
}
+ /**
+ * Sets or disable OAuth2 authentication.
+ *
+ * Defaults to {@link #smtpPort}; can be overridden by using {@link #setSmtpPort(int)}
+ *
+ *
+ * @param oauth2Required true if OAUth2 authentication is required, false otherwise
+ * @return An Email.
+ * @throws IllegalStateException if the mail session is already initialized
+ * @since 2.0
+ */
+ public Email setOAuth2Required(final boolean oauth2Required) {
+ checkSessionAlreadyInitialized();
+ this.oauth2Required = oauth2Required;
+ return this;
+ }
+
/**
* Sets the email subject. Replaces end-of-line characters with spaces.
*
diff --git a/commons-email2-jakarta/src/test/java/org/apache/commons/mail2/jakarta/EmailTest.java b/commons-email2-jakarta/src/test/java/org/apache/commons/mail2/jakarta/EmailTest.java
index 7d72698c5..6d7d4c9bd 100644
--- a/commons-email2-jakarta/src/test/java/org/apache/commons/mail2/jakarta/EmailTest.java
+++ b/commons-email2-jakarta/src/test/java/org/apache/commons/mail2/jakarta/EmailTest.java
@@ -19,6 +19,7 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -571,6 +572,17 @@ public void testGetSetAuthentication() {
assertEquals(strPassword, retrievedAuth.getPasswordAuthentication().getPassword());
}
+ @Test
+ public void testSetOAuth2Required() throws EmailException {
+ email.setHostName(strTestMailServer);
+ email.setOAuth2Required(true);
+ final Session mailSession = email.getMailSession();
+
+ // tests
+ assertNotNull(mailSession);
+ assertEquals("XOAUTH2", mailSession.getProperties().getProperty("mail.smtp.auth.mechanisms"));
+ }
+
@Test
public void testGetSetAuthenticator() {
// setup
diff --git a/commons-email2-javax/src/main/java/org/apache/commons/mail2/javax/Email.java b/commons-email2-javax/src/main/java/org/apache/commons/mail2/javax/Email.java
index b9d5d2f8d..8cccb4b93 100644
--- a/commons-email2-javax/src/main/java/org/apache/commons/mail2/javax/Email.java
+++ b/commons-email2-javax/src/main/java/org/apache/commons/mail2/javax/Email.java
@@ -213,6 +213,11 @@ public abstract class Email {
*/
private boolean startTlsRequired;
+ /**
+ * If true, use OAuth2 for authentication.
+ */
+ private boolean oauth2Required;
+
/**
* Does the current transport use SSL/TLS encryption upon connection?
*/
@@ -817,6 +822,10 @@ public Session getMailSession() throws EmailException {
properties.setProperty(EmailConstants.MAIL_SMTP_AUTH, "true");
}
+ if(isOAuth2Required()) {
+ properties.put(EmailConstants.MAIL_SMTP_AUTH_MECHANISMS, "XOAUTH2");
+ }
+
if (isSSLOnConnect()) {
properties.setProperty(EmailConstants.MAIL_PORT, sslSmtpPort);
properties.setProperty(EmailConstants.MAIL_SMTP_SOCKET_FACTORY_PORT, sslSmtpPort);
@@ -1056,6 +1065,16 @@ public boolean isStartTLSRequired() {
return startTlsRequired;
}
+ /**
+ * Tests whether the client is configured to use OAuth2 authentication.
+ *
+ * @return true if using OAuth2 for authentication, false otherwise.
+ * @since 2.0
+ */
+ public boolean isOAuth2Required() {
+ return oauth2Required;
+ }
+
/**
* Sends the email. Internally we build a MimeMessage which is afterwards sent to the SMTP server.
*
@@ -1634,6 +1653,23 @@ public Email setStartTLSRequired(final boolean startTlsRequired) {
return this;
}
+ /**
+ * Sets or disable OAuth2 authentication.
+ *
+ * Defaults to {@link #smtpPort}; can be overridden by using {@link #setSmtpPort(int)}
+ *
+ *
+ * @param oauth2Required true if OAUth2 authentication is required, false otherwise
+ * @return An Email.
+ * @throws IllegalStateException if the mail session is already initialized
+ * @since 2.0
+ */
+ public Email setOAuth2Required(final boolean oauth2Required) {
+ checkSessionAlreadyInitialized();
+ this.oauth2Required = oauth2Required;
+ return this;
+ }
+
/**
* Sets the email subject. Replaces end-of-line characters with spaces.
*
diff --git a/commons-email2-javax/src/test/java/org/apache/commons/mail2/javax/EmailTest.java b/commons-email2-javax/src/test/java/org/apache/commons/mail2/javax/EmailTest.java
index 8adf2f00b..e22b52116 100644
--- a/commons-email2-javax/src/test/java/org/apache/commons/mail2/javax/EmailTest.java
+++ b/commons-email2-javax/src/test/java/org/apache/commons/mail2/javax/EmailTest.java
@@ -19,6 +19,7 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -571,6 +572,17 @@ public void testGetSetAuthentication() {
assertEquals(strPassword, retrievedAuth.getPasswordAuthentication().getPassword());
}
+ @Test
+ public void testSetOAuth2Required() throws EmailException {
+ email.setHostName(strTestMailServer);
+ email.setOAuth2Required(true);
+ final Session mailSession = email.getMailSession();
+
+ // tests
+ assertNotNull(mailSession);
+ assertEquals("XOAUTH2", mailSession.getProperties().getProperty("mail.smtp.auth.mechanisms"));
+ }
+
@Test
public void testGetSetAuthenticator() {
// setup
From 971fa86cd21d1c8ba14280d7c30e816bc74766f7 Mon Sep 17 00:00:00 2001
From: sgoeschl
Date: Wed, 14 May 2025 21:15:22 +0200
Subject: [PATCH 02/13] EMAIL-163 Support for OAuth2 authentication
---
.../java/org/apache/commons/mail2/core/EmailConstants.java | 2 +-
.../src/main/java/org/apache/commons/mail2/jakarta/Email.java | 4 +---
.../src/main/java/org/apache/commons/mail2/javax/Email.java | 2 --
3 files changed, 2 insertions(+), 6 deletions(-)
diff --git a/commons-email2-core/src/main/java/org/apache/commons/mail2/core/EmailConstants.java b/commons-email2-core/src/main/java/org/apache/commons/mail2/core/EmailConstants.java
index 61030067b..70bdd5d6e 100644
--- a/commons-email2-core/src/main/java/org/apache/commons/mail2/core/EmailConstants.java
+++ b/commons-email2-core/src/main/java/org/apache/commons/mail2/core/EmailConstants.java
@@ -56,7 +56,7 @@ public final class EmailConstants {
/** If set to true, tries to authenticate the user using the AUTH command. */
public static final String MAIL_SMTP_AUTH = "mail.smtp.auth";
- /** If set to true, tries to authenticate the user using the OAuth2. */
+ /** If set to true, tries to authenticate the user using an OAuth2 token. */
public static final String MAIL_SMTP_AUTH_MECHANISMS = "mail.smtp.auth.mechanisms";
/** The SMTP user name. */
diff --git a/commons-email2-jakarta/src/main/java/org/apache/commons/mail2/jakarta/Email.java b/commons-email2-jakarta/src/main/java/org/apache/commons/mail2/jakarta/Email.java
index dd644730b..7745e0851 100644
--- a/commons-email2-jakarta/src/main/java/org/apache/commons/mail2/jakarta/Email.java
+++ b/commons-email2-jakarta/src/main/java/org/apache/commons/mail2/jakarta/Email.java
@@ -215,7 +215,7 @@ public abstract class Email {
private boolean startTlsRequired;
/**
- * If true, use OAuth2 for authentication.
+ * If true, use OAuth2 token for authentication.
*/
private boolean oauth2Required;
@@ -1657,8 +1657,6 @@ public Email setStartTLSRequired(final boolean startTlsRequired) {
/**
* Sets or disable OAuth2 authentication.
*
- * Defaults to {@link #smtpPort}; can be overridden by using {@link #setSmtpPort(int)}
- *
*
* @param oauth2Required true if OAUth2 authentication is required, false otherwise
* @return An Email.
diff --git a/commons-email2-javax/src/main/java/org/apache/commons/mail2/javax/Email.java b/commons-email2-javax/src/main/java/org/apache/commons/mail2/javax/Email.java
index 8cccb4b93..960f563c8 100644
--- a/commons-email2-javax/src/main/java/org/apache/commons/mail2/javax/Email.java
+++ b/commons-email2-javax/src/main/java/org/apache/commons/mail2/javax/Email.java
@@ -1656,8 +1656,6 @@ public Email setStartTLSRequired(final boolean startTlsRequired) {
/**
* Sets or disable OAuth2 authentication.
*
- * Defaults to {@link #smtpPort}; can be overridden by using {@link #setSmtpPort(int)}
- *
*
* @param oauth2Required true if OAUth2 authentication is required, false otherwise
* @return An Email.
From f1d76f20678aefecef9e64d02e7f95735a9d681c Mon Sep 17 00:00:00 2001
From: sgoeschl
Date: Tue, 27 May 2025 20:50:01 +0200
Subject: [PATCH 03/13] EMAIL-163 Support for OAuth2 authentication
---
src/changes/changes.xml | 1 +
src/site/xdoc/userguide.xml | 17 +++++++++++++++++
2 files changed, 18 insertions(+)
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 61ade7fd9..12bc06f2d 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -24,6 +24,7 @@
+ Support for OAuth2 authentication.Bump commons-parent from 72 to 78 #279, #293, #297, #304.
diff --git a/src/site/xdoc/userguide.xml b/src/site/xdoc/userguide.xml
index 856a9b04e..a0a568e83 100644
--- a/src/site/xdoc/userguide.xml
+++ b/src/site/xdoc/userguide.xml
@@ -337,6 +337,23 @@ import org.apache.commons.mail2.javax.*;
to a known good address.
+
+
+ Checklist provided by mkomko to help future users of this feature
+
+
Create an app registration in Entra ID with the permission "Office 365 Exchange Online - SMTP.SendAsApp"
+
Create a service principal in Exchange Online for the app and give it permissions to the mailbox you want to send as, as described in https://learn.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-imap-pop-smtp-application-by-using-oauth#use-client-credentials-grant-flow-to-authenticate-smtp-imap-and-pop-connections
+
Get an Exchange Online access token (for example using the Graph API with the scope https://outlook.office365.com/.default)
+
SMTP server: smtp.office365.com, Port 587, StartTLS
+
Username: The email address of the mailbox you want to send as
+
Password: The access token
+
+
+
+
From ba7654ba75dc0256e69a0a7de4237ca79e76fd38 Mon Sep 17 00:00:00 2001
From: sgoeschl
Date: Fri, 22 Nov 2024 22:09:51 +0100
Subject: [PATCH 04/13] EMAIL-163 Support for OAuth2 authentication
---
.../commons/mail2/core/EmailConstants.java | 3 ++
.../apache/commons/mail2/jakarta/Email.java | 36 +++++++++++++++++++
.../commons/mail2/jakarta/EmailTest.java | 12 +++++++
.../org/apache/commons/mail2/javax/Email.java | 36 +++++++++++++++++++
.../apache/commons/mail2/javax/EmailTest.java | 12 +++++++
5 files changed, 99 insertions(+)
diff --git a/commons-email2-core/src/main/java/org/apache/commons/mail2/core/EmailConstants.java b/commons-email2-core/src/main/java/org/apache/commons/mail2/core/EmailConstants.java
index d2d816064..b4cc973fe 100644
--- a/commons-email2-core/src/main/java/org/apache/commons/mail2/core/EmailConstants.java
+++ b/commons-email2-core/src/main/java/org/apache/commons/mail2/core/EmailConstants.java
@@ -56,6 +56,9 @@ public final class EmailConstants {
/** If set to true, tries to authenticate the user using the AUTH command. */
public static final String MAIL_SMTP_AUTH = "mail.smtp.auth";
+ /** If set to true, tries to authenticate the user using the OAuth2. */
+ public static final String MAIL_SMTP_AUTH_MECHANISMS = "mail.smtp.auth.mechanisms";
+
/** The SMTP user name. */
public static final String MAIL_SMTP_USER = "mail.smtp.user";
diff --git a/commons-email2-jakarta/src/main/java/org/apache/commons/mail2/jakarta/Email.java b/commons-email2-jakarta/src/main/java/org/apache/commons/mail2/jakarta/Email.java
index f4f67b57b..0aafbffa7 100644
--- a/commons-email2-jakarta/src/main/java/org/apache/commons/mail2/jakarta/Email.java
+++ b/commons-email2-jakarta/src/main/java/org/apache/commons/mail2/jakarta/Email.java
@@ -214,6 +214,11 @@ public abstract class Email {
*/
private boolean startTlsRequired;
+ /**
+ * If true, use OAuth2 for authentication.
+ */
+ private boolean oauth2Required;
+
/**
* Does the current transport use SSL/TLS encryption upon connection?
*/
@@ -823,6 +828,10 @@ public Session getMailSession() throws EmailException {
properties.setProperty(EmailConstants.MAIL_SMTP_AUTH, "true");
}
+ if(isOAuth2Required()) {
+ properties.put(EmailConstants.MAIL_SMTP_AUTH_MECHANISMS, "XOAUTH2");
+ }
+
if (isSSLOnConnect()) {
properties.setProperty(EmailConstants.MAIL_PORT, sslSmtpPort);
properties.setProperty(EmailConstants.MAIL_SMTP_SOCKET_FACTORY_PORT, sslSmtpPort);
@@ -1062,6 +1071,16 @@ public boolean isStartTLSRequired() {
return startTlsRequired;
}
+ /**
+ * Tests whether the client is configured to use OAuth2 authentication.
+ *
+ * @return true if using OAuth2 for authentication, false otherwise.
+ * @since 2.0
+ */
+ public boolean isOAuth2Required() {
+ return oauth2Required;
+ }
+
/**
* Sends the email. Internally we build a MimeMessage which is afterwards sent to the SMTP server.
*
@@ -1640,6 +1659,23 @@ public Email setStartTLSRequired(final boolean startTlsRequired) {
return this;
}
+ /**
+ * Sets or disable OAuth2 authentication.
+ *
+ * Defaults to {@link #smtpPort}; can be overridden by using {@link #setSmtpPort(int)}
+ *
+ *
+ * @param oauth2Required true if OAUth2 authentication is required, false otherwise
+ * @return An Email.
+ * @throws IllegalStateException if the mail session is already initialized
+ * @since 2.0
+ */
+ public Email setOAuth2Required(final boolean oauth2Required) {
+ checkSessionAlreadyInitialized();
+ this.oauth2Required = oauth2Required;
+ return this;
+ }
+
/**
* Sets the email subject. Replaces end-of-line characters with spaces.
*
diff --git a/commons-email2-jakarta/src/test/java/org/apache/commons/mail2/jakarta/EmailTest.java b/commons-email2-jakarta/src/test/java/org/apache/commons/mail2/jakarta/EmailTest.java
index 0ce1bb622..e734b0a62 100644
--- a/commons-email2-jakarta/src/test/java/org/apache/commons/mail2/jakarta/EmailTest.java
+++ b/commons-email2-jakarta/src/test/java/org/apache/commons/mail2/jakarta/EmailTest.java
@@ -19,6 +19,7 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -571,6 +572,17 @@ public void testGetSetAuthentication() {
assertEquals(strPassword, retrievedAuth.getPasswordAuthentication().getPassword());
}
+ @Test
+ public void testSetOAuth2Required() throws EmailException {
+ email.setHostName(strTestMailServer);
+ email.setOAuth2Required(true);
+ final Session mailSession = email.getMailSession();
+
+ // tests
+ assertNotNull(mailSession);
+ assertEquals("XOAUTH2", mailSession.getProperties().getProperty("mail.smtp.auth.mechanisms"));
+ }
+
@Test
public void testGetSetAuthenticator() {
// setup
diff --git a/commons-email2-javax/src/main/java/org/apache/commons/mail2/javax/Email.java b/commons-email2-javax/src/main/java/org/apache/commons/mail2/javax/Email.java
index 1bea918c0..a0d33e2a2 100644
--- a/commons-email2-javax/src/main/java/org/apache/commons/mail2/javax/Email.java
+++ b/commons-email2-javax/src/main/java/org/apache/commons/mail2/javax/Email.java
@@ -213,6 +213,11 @@ public abstract class Email {
*/
private boolean startTlsRequired;
+ /**
+ * If true, use OAuth2 for authentication.
+ */
+ private boolean oauth2Required;
+
/**
* Does the current transport use SSL/TLS encryption upon connection?
*/
@@ -822,6 +827,10 @@ public Session getMailSession() throws EmailException {
properties.setProperty(EmailConstants.MAIL_SMTP_AUTH, "true");
}
+ if(isOAuth2Required()) {
+ properties.put(EmailConstants.MAIL_SMTP_AUTH_MECHANISMS, "XOAUTH2");
+ }
+
if (isSSLOnConnect()) {
properties.setProperty(EmailConstants.MAIL_PORT, sslSmtpPort);
properties.setProperty(EmailConstants.MAIL_SMTP_SOCKET_FACTORY_PORT, sslSmtpPort);
@@ -1061,6 +1070,16 @@ public boolean isStartTLSRequired() {
return startTlsRequired;
}
+ /**
+ * Tests whether the client is configured to use OAuth2 authentication.
+ *
+ * @return true if using OAuth2 for authentication, false otherwise.
+ * @since 2.0
+ */
+ public boolean isOAuth2Required() {
+ return oauth2Required;
+ }
+
/**
* Sends the email. Internally we build a MimeMessage which is afterwards sent to the SMTP server.
*
@@ -1639,6 +1658,23 @@ public Email setStartTLSRequired(final boolean startTlsRequired) {
return this;
}
+ /**
+ * Sets or disable OAuth2 authentication.
+ *
+ * Defaults to {@link #smtpPort}; can be overridden by using {@link #setSmtpPort(int)}
+ *
+ *
+ * @param oauth2Required true if OAUth2 authentication is required, false otherwise
+ * @return An Email.
+ * @throws IllegalStateException if the mail session is already initialized
+ * @since 2.0
+ */
+ public Email setOAuth2Required(final boolean oauth2Required) {
+ checkSessionAlreadyInitialized();
+ this.oauth2Required = oauth2Required;
+ return this;
+ }
+
/**
* Sets the email subject. Replaces end-of-line characters with spaces.
*
diff --git a/commons-email2-javax/src/test/java/org/apache/commons/mail2/javax/EmailTest.java b/commons-email2-javax/src/test/java/org/apache/commons/mail2/javax/EmailTest.java
index 0e7af00be..b6940f704 100644
--- a/commons-email2-javax/src/test/java/org/apache/commons/mail2/javax/EmailTest.java
+++ b/commons-email2-javax/src/test/java/org/apache/commons/mail2/javax/EmailTest.java
@@ -19,6 +19,7 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -571,6 +572,17 @@ public void testGetSetAuthentication() {
assertEquals(strPassword, retrievedAuth.getPasswordAuthentication().getPassword());
}
+ @Test
+ public void testSetOAuth2Required() throws EmailException {
+ email.setHostName(strTestMailServer);
+ email.setOAuth2Required(true);
+ final Session mailSession = email.getMailSession();
+
+ // tests
+ assertNotNull(mailSession);
+ assertEquals("XOAUTH2", mailSession.getProperties().getProperty("mail.smtp.auth.mechanisms"));
+ }
+
@Test
public void testGetSetAuthenticator() {
// setup
From 2c791c319025188ba86d5cc8fc9f66c840875efb Mon Sep 17 00:00:00 2001
From: sgoeschl
Date: Wed, 14 May 2025 21:15:22 +0200
Subject: [PATCH 05/13] EMAIL-163 Support for OAuth2 authentication
---
.../java/org/apache/commons/mail2/core/EmailConstants.java | 2 +-
.../src/main/java/org/apache/commons/mail2/jakarta/Email.java | 4 +---
.../src/main/java/org/apache/commons/mail2/javax/Email.java | 2 --
3 files changed, 2 insertions(+), 6 deletions(-)
diff --git a/commons-email2-core/src/main/java/org/apache/commons/mail2/core/EmailConstants.java b/commons-email2-core/src/main/java/org/apache/commons/mail2/core/EmailConstants.java
index b4cc973fe..b4210efef 100644
--- a/commons-email2-core/src/main/java/org/apache/commons/mail2/core/EmailConstants.java
+++ b/commons-email2-core/src/main/java/org/apache/commons/mail2/core/EmailConstants.java
@@ -56,7 +56,7 @@ public final class EmailConstants {
/** If set to true, tries to authenticate the user using the AUTH command. */
public static final String MAIL_SMTP_AUTH = "mail.smtp.auth";
- /** If set to true, tries to authenticate the user using the OAuth2. */
+ /** If set to true, tries to authenticate the user using an OAuth2 token. */
public static final String MAIL_SMTP_AUTH_MECHANISMS = "mail.smtp.auth.mechanisms";
/** The SMTP user name. */
diff --git a/commons-email2-jakarta/src/main/java/org/apache/commons/mail2/jakarta/Email.java b/commons-email2-jakarta/src/main/java/org/apache/commons/mail2/jakarta/Email.java
index 0aafbffa7..924872876 100644
--- a/commons-email2-jakarta/src/main/java/org/apache/commons/mail2/jakarta/Email.java
+++ b/commons-email2-jakarta/src/main/java/org/apache/commons/mail2/jakarta/Email.java
@@ -215,7 +215,7 @@ public abstract class Email {
private boolean startTlsRequired;
/**
- * If true, use OAuth2 for authentication.
+ * If true, use OAuth2 token for authentication.
*/
private boolean oauth2Required;
@@ -1662,8 +1662,6 @@ public Email setStartTLSRequired(final boolean startTlsRequired) {
/**
* Sets or disable OAuth2 authentication.
*
- * Defaults to {@link #smtpPort}; can be overridden by using {@link #setSmtpPort(int)}
- *
*
* @param oauth2Required true if OAUth2 authentication is required, false otherwise
* @return An Email.
diff --git a/commons-email2-javax/src/main/java/org/apache/commons/mail2/javax/Email.java b/commons-email2-javax/src/main/java/org/apache/commons/mail2/javax/Email.java
index a0d33e2a2..47d0959db 100644
--- a/commons-email2-javax/src/main/java/org/apache/commons/mail2/javax/Email.java
+++ b/commons-email2-javax/src/main/java/org/apache/commons/mail2/javax/Email.java
@@ -1661,8 +1661,6 @@ public Email setStartTLSRequired(final boolean startTlsRequired) {
/**
* Sets or disable OAuth2 authentication.
*
- * Defaults to {@link #smtpPort}; can be overridden by using {@link #setSmtpPort(int)}
- *
*
* @param oauth2Required true if OAUth2 authentication is required, false otherwise
* @return An Email.
From 90d5cae6f9613b9be2c0a89b14e83870738dd541 Mon Sep 17 00:00:00 2001
From: sgoeschl
Date: Tue, 27 May 2025 20:50:01 +0200
Subject: [PATCH 06/13] EMAIL-163 Support for OAuth2 authentication
---
src/site/xdoc/userguide.xml | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/src/site/xdoc/userguide.xml b/src/site/xdoc/userguide.xml
index 0edce5a01..ad46041e9 100644
--- a/src/site/xdoc/userguide.xml
+++ b/src/site/xdoc/userguide.xml
@@ -337,6 +337,23 @@ import org.apache.commons.mail2.javax.*;
to a known good address.
+
+
+ Checklist provided by mkomko to help future users of this feature
+
+
Create an app registration in Entra ID with the permission "Office 365 Exchange Online - SMTP.SendAsApp"
+
Create a service principal in Exchange Online for the app and give it permissions to the mailbox you want to send as, as described in https://learn.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-imap-pop-smtp-application-by-using-oauth#use-client-credentials-grant-flow-to-authenticate-smtp-imap-and-pop-connections
+
Get an Exchange Online access token (for example using the Graph API with the scope https://outlook.office365.com/.default)
+
SMTP server: smtp.office365.com, Port 587, StartTLS
+
Username: The email address of the mailbox you want to send as