Announcing OAuth 2.0 Client Credentials Flow support for POP and IMAP protocols in Exchange Online
Published Jun 30 2022 11:04 AM 47.2K Views

Today, we’re excited to announce the availability of OAuth 2.0 authentication via client credentials grant flow for the POP and IMAP protocols for accessing Exchange Online mailboxes.

Applications that need to access Exchange Online mailboxes without user interaction and using the identity of the application as opposed to user identity are now supported. This is enabled by using service principals in Exchange and mailbox permissions. While no user interaction is needed, Exchange Online admins will need to provide specific mailbox access (using Exchange Online PowerShell) for applications’ service principals to access the mailboxes.

How it works

Once an admin has granted consent to an Azure Active Directory application, they must register the application’s service principal in Exchange Online. This is done using the new Exchange Online PowerShell cmdlet, New-ServicePrincipal (this cmdlet is currently rolling out).

Once the application’s service principal is registered in Exchange Online, the admin can give the application access to specific mailboxes using the Add-MailboxPermission cmdlet. The application can then authenticate POP and IMAP connections to the Exchange Online mailboxes.

The OAuth 2.0 client credentials grant flow can be used to generate access tokens, which can be used as the authentication token in SASL XOAUTH2 format for POP and IMAP connections to Exchange Online mailboxes.

You can follow these step-by-step instructions on how to implement client credentials flow support for POP and IMAP in your application.

Exchange Online Team

51 Comments
Brass Contributor

Cool, any news on credentials flow support for SMTP?

Copper Contributor

Thanks for the information, I would like to stress that most of the documentation for this stuff is developer oriented, while most of the people using mail flows for applications are NOT developers.  Trying to walk a non-developer through getting an access token for Oauth grant flows, instead of just filling out the username/password fields in a nice gui that worked for years is proving to be VERY problematic.

 

I applaud increasing security, however I must state how much more of a burden this puts on admins as the usability factor on this new method is beyond awful.  I am very surprised that this went forward after 2 years of being on hold, without improvements to the user interaction experience.  Also, you may want to emphasize the user of the offline permissions so people dont end up having to request new token constantly.

 

 

@ViliusS - not yet. 

@eric watkins - yes Eric, OAuth flows and constructs require much more developer skills - but unfortunately the increase in attacks using basic auth has meant we have to move on. It's not just Exchange, it's an industry trend. 

Copper Contributor

Very very good news! Thank you very much!

We still need non-interactive access via credential flow for SMTP too.

Will this function be implemented?

Is there already any timeframe for this?

 

Thanks in advance!

@JNeck - still work in progress. No timeframe to share at this time. 

Copper Contributor

Very good news! Thanks for that!

 

I had the same questions like @BJNeu. Thanks for your answers!
Is it intended to turn off the basic authentication for SMTP? If yes, when?

 

Thanks in advance!

@MustCh - no date for SMTP has been published. We have no plans to completely disable basic for SMTP at this time. 

Copper Contributor

When basic auth for SMTP will still be supported, is it possible to use it with MFA enabled accounts and app passwords after october?
Furthermore, are we able to define new app passwords like we are used to then?

You'll be able to configure SMTP like that just as you do today, yes. 

Copper Contributor

I tried to follow the instructions... the stuff to get the token and grant is ok. But the registration in exchange with the comandlets is very confusing. There are two object ids for the same application, depending where you look. And the response of 

Get-ServicePrincipal

does not contain any <SERVICE_PRINCIPAL_ID>. It would also be very good to have a decoded token as example and real screenshots of which Id to take where. Trying now for hours and still get  A01 NO AUTHENTICATE failed

Copper Contributor

I was able to follow Tony's blog,https://office365itpros.com/2022/07/04/exchange-online-imap4-pop3/?utm_source=rss&utm_medium=rss&utm...   with a minor fix in the scope (see my comment on July 14, 2022 at 7:31 pm )

And get the pop3 + oauth2 to work.

Copper Contributor

Thanks, I found that too and got it to work ... just very frustrating if you have to write a ticket to your Admin for each try....

Copper Contributor

you could use the https://developer.microsoft.com/en-us/microsoft-365/dev-program for development work. no way can I get my IT admin allow me messing around the production email.

Copper Contributor

Can someone explain how to use New-ServicePrincipal cmdlet?

I'm new to exchange online management and I've tried to install everything on my machine to have that cmdlet but it did not show up.

I've installed latest version of exchange online management tools but that cmdlet is not present

 

https://www.powershellgallery.com/packages/ExchangeOnlineManagement/2.0.6-Preview6

 

any help will be appreciated.

Copper Contributor

Did you connect to exchange online with following command?
PS C:\> Connect-ExchangeOnline

it will redirect you to login screen for authentication. after sign in, the cmdlet should work.

Copper Contributor

I implement the OAuth 2.0 client credentials grant flow for POP3. It works fine, but only for 1 sometimes 2 or 3 hours an then not any more. The error message is “-ERR Authentication failure: unknown user name or bad password.” That is not plausible for me, because TENET ID, CLIENT ID and CLIENT SECRET are correct. Do you have an Idea what is the cause for this behavior?

 

After the first authentication failure, I try to obtain a new access token in the same way I obtained the first original one. But it seems that it does not work.

 

An auto refreshing of the access token can not work, because of the obtained token. There is no property “refresh_token” exist (see below the obtained token as json file).

{

  "token_type": "Bearer",

  "expires_in": 3599,

  "ext_expires_in": 3599,

  "access_token": "eyJ0eXAiOiJKV1QiLCJub25jZSI--XXXXXXXXXX"

}

Without the property “refresh_token” it is not possibel to refresh the access token.

 

Could you Please help me how to solve this problem.

 

Thanks!

Copper Contributor

Any news about SMTP support?

Copper Contributor

So, is in this case is it still required to create an Exchange Access Policy to restrict access to specific mailboxes? also, is it required to grant recipient permission to

SendAs? 

Copper Contributor

Hi All,

Anyone knows of C# implementation example for the POP connection using OAUTH 2 with Client Credentials? I have got the ClientId, TenantId and Client Secrat.

In Postman:

https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token 

returns the access_token for the provided:

client_id : {clientId}

grant_type : client_credentials

scope: https://ps.outlook.com/.default

client_secret: {client secret's Value created in Azure, for the registered application}

 

but, is there an example to do this in C# backend process and further creating the POP connect to use the access token and download mails?

MailKit/ MimeKit seems to be providing the POPClient implementation that allows XAUTH2 authentication type, But it there an implementation that does not require the use of third party POP client?

 

Regards,

A

Copper Contributor

@AtifMunir

Here is example for IMAP, but the authentication part is the same for POP/IMAP:

https://github.com/DanijelkMSFT/ThisandThat/blob/main/Get-IMAPAccessToken.ps1

scope should be: https://outlook.office365.com/.default

 

It's in PowerShell, it should be easy to rewrite it in C#.

 

Authentication part is handled in MSAL.PS but could be rewritten to not use it.

This is replacement for MSAL.PS:

 

$clientID = "<client id>"
$tenantID = "<tenant id>"
$clientsecret = "<client secret>"

$RequestBody = @{
client_id = $clientId;
client_secret = $clientSecret;
grant_type="client_credentials";
scope="https://outlook.office365.com/.default";
}
$OAuthResponse = Invoke-RestMethod -Method Post -Uri https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token -Body $RequestBody
$AccessToken = $OAuthResponse.access_token

# pre-requirement
# MSAL.PS - https://www.powershellgallery.com/packages/MSAL.PS/4.2.1.3
# code written in MSAL.PS
$SecuredclientSecret = ConvertTo-SecureString $clientsecret -AsPlainText -Force
$ClientApplication = New-MsalClientApplication -ClientId $clientID -TenantId $tenantID -ClientSecret $SecuredclientSecret

$MsalToken = $ClientApplication | Get-MsalToken -Scopes 'https://outlook.office365.com/.default'
$AccessToken = $MsalToken.accessToken

 

 

Copper Contributor

Nuget MailKit and Microsoft.Identity.Client. code tested.

using MailKit.Net.Pop3;
using MailKit.Security;
using Microsoft.Identity.Client;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MailKitTester
{
    class Program
    {
        public static string getMSOauth2Token(string clientId, string clientSecret, string tenantId)
        {
            
            string token;

            string authority = "https://login.microsoftonline.com/" + tenantId;
            const string scope = "https://outlook.office365.com/.default";

            IConfidentialClientApplication app;
            app = ConfidentialClientApplicationBuilder.Create(clientId)
                   .WithClientSecret(clientSecret)
                   .WithAuthority(authority)
                   .Build();

            string[] scopes = new string[]
            {
              scope,
              "offline_access"
            };
            token = app.AcquireTokenForClient(scopes).ExecuteAsync().Result.AccessToken;
            return token;

        }
        static void Main(string[] args)
        {
            string token = getMSOauth2Token("********", "********", "**********");

            using (var client = new Pop3Client())
            {
                client.Connect("Outlook.office365.com", 995, SecureSocketOptions.SslOnConnect);
                
                if (client.AuthenticationMechanisms.Contains("OAUTHBEARER") || client.AuthenticationMechanisms.Contains("XOAUTH2"))
                {
                    var oauth2 = new SaslMechanismOAuth2("email address removed for privacy reasons", token);
                    client.Authenticate(oauth2);
                }

                var msgCount = client.Count;
              
                client.Disconnect(true);
            }
        }
    }
}

 

Brass Contributor

Same question as FSOSA. If you are using Client Credential Flow with Application permissions is it still necessary to lock down the app with New-ApplicationAccessPolicy?

 

If not can someone be kind and an explain why not? Is it because you have to create a separate Service Principal in EXO and then grant permissions to that and that controls the access? If this is the case what happens to the permissions of the Azure App service principal, does it still have those permissions org wide and do i need to worry about it?

 

Thanks in advance.

 
Copper Contributor

My SMTP basic authentication access for my emailing application was disabled in the middle of September and I had to get my Administrator to re-enable it system-wide.   They were not happy about doing this however I still have users that need to use this application.   I am in the process of converting this application to use Modern Authentication after my Administrator configured my application in Azure.   I have it coded to return the bearer token that I then pass into Java Mail.   It all looks correct, however I continually get "535 5.7.3 Authentication unsuccessful" failures when I try to send a test email.

 

Is this error because SMTP Credential Flow is still not enabled, or is there something else that I'm missing?  It would be nice if the "535 5.7.3 Authentication unsuccessful" failure provided a little more information about the failure.

 

@Debra_P - client credential flow is not yet possible with SMTP. We'll announce when it's available, plan/hope is by the end of the year. 

Steel Contributor
Copper Contributor

any news on the  client credential flow with SMTP ? as we are now in 2023, i wonder whether it has become available/ been announced  ?

Steel Contributor

Hi @steven8456 

 

You can Send Emails with Graph API and OAuth Authentication.

https://blog.icewolf.ch/archive/2021/07/07/graph-api-send-mail-with-powershell.aspx 

 

Regards

Andres Bohren

Copper Contributor

@Andres Bohren - unfortunately this is not a real solution - many of us have to maintain applications that must use a standard-based solution for sending emails over SMTP, that works with different SMTP email servers (both on-premise or in the cloud) - Office 365 / Exchange Online is just one of them, where support for OAuth2 client credential flow is needed..
A code like:
if (Office365} { .... }
else if (GMail) { .... }
else if (AWS) { .... }
else if (on prem) { ... }
is not maintainable..

Copper Contributor

@Greg Taylor - EXCHANGE , Can you please let us know when the client credential flow for SMTP AUTH will be available ?

@AJNOX - still be worked on, sorry I don't have more of an update to share. 

Copper Contributor

We have a customer using Azure federated authentication with Okta, want to know if they can use the token generated from Okta side to authenticate the Office365 Pop3. Thanks.

Copper Contributor

For all waiting for client credential flow for SMTP AUTH I just saw this

https://techcommunity.microsoft.com/t5/exchange-team-blog/announcing-client-credential-flow-for-smtp...

Copper Contributor

Dear @Greg Taylor - EXCHANGE regarding "client credential flow is not yet possible with SMTP" I assume there are now updates that I probably missed.

Can you provide update for the SMTP, if available?

Thanks!

Copper Contributor

Dear @Debra_P did you finally managed to update the authentication model with SMTP?

We are facing issues like you.

Thanks

Copper Contributor

I actually just saw the new notification for SMTP client credential flow

https://techcommunity.microsoft.com/t5/exchange-team-blog/announcing-client-credential-flow-for-smtp...

and am starting to work on implementing it now.

Copper Contributor

@Sandro_Garofano 

 

I have worked with my IT administrator to make the documented changes and modified my scope from https://outlook.office365.com/.default to https://outlook.office.com/SMTP.SendAsApp but it fails consistently with a "400 - Bad Request" response when I attempt to get the bearer token from the server.  I'm stuck as well.  

 

Can anybody provide us with any direction?  A "400 - Bad Request" response is really vague.  Is there anything in the server logs that I can direct IT to look for to help me diagnose what is wrong?

Copper Contributor

Debra_P

per https://learn.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an..."You must use https://outlook.office365.com/.default in the scope property in the body payload for the access token request."

 

SMTP.SendAsApp should be added to the AD Application's permission.

Copper Contributor

@XuYang1795 

 

Thank you for the reply.  When I change the scope to https://outlook.office365.com/.default  I get a "401 - Unauthorized" response.

As far as I know, my IT Administrator has added SMTP.SendAsApp my Application's permission. 

 

I am confused though because the this link "https://learn.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-..." does say the scope should be https://outlook.office.com/SMTP.SendAsApp

 

Is there anything else I can try? 

Copper Contributor

Debra_P 
"unauthorized" is better than "bad request", isn't it? I assume you got the 401 when you request the token? 

If you set up the AD application correctly, your client need to have are  the correct values for:
clientId

clientSecret

tenantId

authority =  "https://login.microsoftonline.com/" + tenantId

scope = "https://outlook.office365.com/.default"

 

Here is a snippet from a working c# code:

 

IConfidentialClientApplication app;
app = ConfidentialClientApplicationBuilder.Create(clientId)
.WithClientSecret(clientSecret)
.WithAuthority(authority)
.Build();

string[] scopes = new string[]
{
scope,
"offline_access"
};

try
{
token = app.AcquireTokenForClient(scopes).ExecuteAsync().Result.AccessToken;
//Console.WriteLine(decodedToken(token));

}

 

Copper Contributor

@XuYang1795 

Thank you for you reply.  Yes, I am getting the "401 - Unauthorized" response when I request the token.   I am asking my IT administrator for verification that my clientId, client_secret and tenantId are correctly set.

 

Can I assume because you are using C# that you are using Microsoft Graph to acquire your token?  I did experiment with my URL but it does appear that the "/oauth2/v2.0/token" path needs to be included (otherwise I get a 404 error).

 

I did have the token part working at last year during my initial development, so unless nothing else has changed, it does look like the issue lies in my AD configuration.

Copper Contributor

Debra_P

Requesting the token does not have GraphAPI involved yet, it is the Microsoft's Identity.client package wrapped that token request, so I won't know the https request in details.

If you use Java, I think you can try the library msal4j quickly, (again, this is a working code you can verify it is your code or the AD setup)

I highly recommend you create an Azure developer sandbox, and add configuration for a testing o365, which will significantly cut the development time before you go for your IT admin.

implementation 'com.microsoft.azure:msal4j:1.13.9'

 

import com.microsoft.aad.msal4j.*;
 
    private String getToken() {
        String token = "";
        String clientId = "xxxxxxxxxxxxxxxxxxxxx";
        String clientSecret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
        String tenantId = "xxxxxxxxxxxxxxxxxxxxxxxx";
        String authority = "https://login.microsoftonline.com/" + tenantId;
        IConfidentialClientApplication app = null;
        try {
            app = ConfidentialClientApplication
                    .builder(clientId, ClientCredentialFactory.createFromSecret(clientSecret)).authority(authority)
                    .build();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
 
        Set<String> scopes = Collections.singleton("https://outlook.office365.com/.default");
         
        try {
            ClientCredentialParameters parameters = ClientCredentialParameters.builder(scopes).build();
            IAuthenticationResult result = app.acquireToken(parameters).get();
 
            // The access token can be obtained from the result
            token = result.accessToken();
            System.out.println("Access Token: " + token);
        } catch (Exception ex) {
            System.out.println("Error occurred: " + ex.getMessage());
        }
 
        return token;
    }
Copper Contributor

oh Debra_P

you said the token was working last year? It is very likely your secret got expired, I think the default was like 6months, I have mine renewed few months ago.

That's an IT change, you may ask them.

Copper Contributor

@XuYang1795 

 

Thank you, I will ask IT.  I am going to run a quick test with msal4j just to validate that the issue is due to a configuration problem.

Copper Contributor

Hi @XuYang1795 

 

Thank you for the direction.  I ran a test using the msal4j.jar using your example code and the output told me specifically that my client secret keys are expired:


Error occurred: com.microsoft.aad.msal4j.MsalServiceException: AADSTS7000222: The provided client secret keys for app 'fba4660b-7c4e-4c7f-887f-7960dff2cfcf' are expired. Visit the Azure portal to create new keys for your app: https://aka.ms/NewClientSecret, or consider using certificate credentials for added security: https://aka.ms/certCreds.
Trace ID: 273be4d1-db36-4265-b6ea-0914f4e61500
Correlation ID: d8b86a57-8872-4ab1-a637-d90a61d0400b
Timestamp: 2023-07-27 16:57:12Z

Copper Contributor

That's great. cause you said it was working last year.

Copper Contributor

Just to let everyone know, after I was able to obtain the OAUTH bearer token, I then faced an Authentication Failed error while trying to use that token to send SMTP emails using client credentials flow.

 

It turns out that my Azure server had not been fully configured with all the permissions needed to send the emails.  

 

The last steps described here-> https://learn.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-... to create the service principal and give it permissions to the target mailbox had not been done. 

 

Once this was completed, I was able to send SMTP emails  through javamail successfully.

Copper Contributor
Hi all
I have been trying setting up the mailing system using oauth2 for SMTP.
I have an account of Microsoft with the Exchnage online License. I have followed the exact steps 
I have registered the New-ServicePrincipal and given full access for mailbox.
I have the  following code:
 
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Properties;
 
public class MailSend {
    public static void sendMail(String accessToken) {
 
        // Compose the email
        String subject = "Your Subject";
        String body = "Your email body.";
        String fromEmail = "email address removed for privacy reasons";
        String toEmail = "email address removed for privacy reasons";
 
        Properties props = new Properties();
        props.put("mail.smtp.host", "smtp.office365.com");
        props.put("mail.smtp.port", "587");
        props.put("mail.smtp.starttls.enable", true);
 
    try{
        Session session = Session.getInstance(props, new Authenticator() {
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication("", accessToken);
            }
        });
        session.setDebug(true);
        Message message = new MimeMessage(session);
        message.setFrom(new InternetAddress(fromEmail));
        message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail));
        message.setSubject(subject);
        message.setText(body);
 
            // Send the email
        Transport.send(message);
        System.out.println("Email sent successfully!");
        } catch (MessagingException e) {
            e.printStackTrace();
        }
    }
}
 
 public static String aquireAccessToken() throws MalformedURLException {
        Set<String> scopes = Collections.singleton("https://outlook.office365.com/.default");
 
        ConfidentialClientApplication app = ConfidentialClientApplication.builder(
                        clientId,
                        ClientCredentialFactory.createFromSecret(clientSecret))
                .authority("https://login.microsoftonline.com/" + tenantId + "/oauth2/v2.0/token")
                .build();
 
        ClientCredentialParameters parameters = ClientCredentialParameters.builder(scopes).build();
        IAuthenticationResult result = app.acquireToken(parameters).join();
 
        // Use the accessToken for SMTP authentication
        return result.accessToken();
    }
 
public static void main(String[] args) throws Exception{
        String token = main.java.TokenProvider.aquireAccessToken();
        main.java.MailSend.sendMail(token);
    }
 
I am putting the correct tenantId, ClientSecret and clientId.
My authentication is successfull which can be seen in the logs but I always get the 530 error.
The logs shows: 
530 5.7.57 Client not authenticated to send mail. [FR2P281CA0136.DEUP281.PROD.OUTLOOK.COM 2023-09-22T12:40:18.555Z 08DBBA5C08041989]
DEBUG SMTP: got response code 530, with response: 530 5.7.57 Client not authenticated to send mail. [FR2P281CA0136.DEUP281.PROD.OUTLOOK.COM 2023-09-22T12:40:18.555Z 08DBBA5C08041989]
 
RSET
DEBUG SMTP: EOF: [EOF]
DEBUG SMTP: MessagingException while sending, THROW: 
com.sun.mail.smtp.SMTPSendFailedException: 530 5.7.57 Client not authenticated to send mail. [FR2P281CA0136.DEUP281.PROD.OUTLOOK.COM 2023-09-22T12:40:18.555Z 08DBBA5C08041989]
 
at com.sun.mail.smtp.SMTPTransport.issueSendCommand(SMTPTransport.java:2374)
at com.sun.mail.smtp.SMTPTransport.mailFrom(SMTPTransport.java:1808)
at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1285)
at javax.mail.Transport.send0(Transport.java:231)
at javax.mail.Transport.send(Transport.java:100)
at main.java.MailSend.sendMail(MailSend.java:44)
at main.java.Main.main(Main.java:8)
QUIT
javax.mail.MessagingException: Can't send command to SMTP host;
  nested exception is:
java.net.SocketException: Connection or outbound has closed
at com.sun.mail.smtp.SMTPTransport.sendCommand(SMTPTransport.java:2431)
at com.sun.mail.smtp.SMTPTransport.sendCommand(SMTPTransport.java:2418)
at com.sun.mail.smtp.SMTPTransport.close(SMTPTransport.java:1394)
at javax.mail.Transport.send0(Transport.java:233)
at javax.mail.Transport.send(Transport.java:100)
at main.java.MailSend.sendMail(MailSend.java:44)
at main.java.Main.main(Main.java:8)
Caused by: java.net.SocketException: Connection or outbound has closed
at sun.security.ssl.SSLSocketImpl$AppOutputStream.write(SSLSocketImpl.java:1181)
at com.sun.mail.util.TraceOutputStream.write(TraceOutputStream.java:116)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
at com.sun.mail.smtp.SMTPTransport.sendCommand(SMTPTransport.java:2429)
... 6 more
 
I fail to understand the exact cause. Any support will be helpful.
Regards
Kinjal
Copper Contributor

Hi Kinjal1012

I've included a snippet of my code that is working successfully.  When using OAuth, you shouldn't be adding an Authenticator to the Session variable (instead leave it as null) since you have already obtained the access (bearer) token.  That  token should be added as a value to the "mail.smtp.sasl.mechanisms.oauth2.oauthToken" property as shown below.   Also include that token as a parameter in the connect method of the transport.

 

// Create a mail session        

Properties props = new Properties();         
props.put("mail.smtp.connectiontimeout", "10000");        
props.put("mail.smtp.timeout", "10000");        
props.put("mail.smtp.sendpartial", "true");        
props.put("mail.smtp.starttls.enable", "true");  
props.put("mail.smtp.ssl.trust", "*");

props.put("mail.smtp.host", smtpHost);
props.put("mail.smtp.port", "" + smtpPort); props.put("mail.smtp.auth", "true"); // Get the bearer token for OAUTH2 Access to the MS Exchange/365 server OAuthToken oauth = new OAuthToken(); String authToken = oauth.getAuthToken(); props.put("mail.smtp.auth.mechanisms", "XOAUTH2"); props.put("mail.smtp.sasl.mechanisms.oauth2.oauthToken", authToken); props.put("mail.smtp.auth.login.disable", "true"); props.put("mail.smtp.auth.plain.disable", "true"); props.put("mail.smtp.auth.xoauth2.disable", "false");
if (debug) {
props.put("mail.debug.auth", "true"); props.put("mail.debug.auth.password", "true"); }
Session session = Session.getInstance(props, null); session.setDebug(debug); // Construct the message Message msg = new MimeMessage(session); msg.setFrom(new InternetAddress(fromAddr)); msg.setSubject(subject); msg.setText(content); msg.saveChanges(); try { transport = session.getTransport("smtp"); transport.connect(user, authToken); transport.sendMessage(msg, msg.getAllRecipients()); } finally { transport.close(); }

 

Hope this helps!

Copper Contributor

Thank you.. That was a big help

Copper Contributor

Protocol error. Connection is closed. 10

anyone know this wrong? thanks

Co-Authors
Version history
Last update:
‎Jun 30 2022 11:05 AM
Updated by: