OAuth 2.0 client credential flow with Office365/Exchange IMAP/POP3/SMTP

This article shows how to implement OAuth 2.0 client credential flow to access Office365 via IMAP, POP3 or SMTP using Mail.dll .net email client. This flow is particularly useful for daemon/service apps that need to monitor certain mailboxes, without any user interaction.

Make sure IMAP/POP3/SMTP is enabled for your organization and mailbox:
Enable IMAP/POP3/SMTP in Office 365

Register your application in Azure Portal, here’s a detailed guide how to do that:
https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app

Add permissions to your application in the API permissions / Add a permission wizard:

Select APIs my organization uses and search for Office 365 Exchange Online:

…then click Application permissions:

For POP access, choose the POP.AccessAsApp permission.
For IMAP access, choose the IMAP.AccessAsApp permission.

Remember to Grant admin consent:

Create an application secret in Certificates & secrets panel by clicking ‘New client secret’ button:

Note the secret value as it is shown only during creation.

Use Windows PowerShell on your machine to Register service principals in Exchange.

Set execution policy first:

Set-ExecutionPolicy RemoteSigned

Install ExchangeOnlineManagement module:

Install-Module -Name ExchangeOnlineManagement

Connect and log in as an administrator (you’ll be prompted for password):

Connect-ExchangeOnline -UserPrincipalName your-admin-account@your-domain.onmicrosoft.com

Create service principal

New-ServicePrincipal -AppId <APPLICATION_ID> -ServiceId <OBJECT_ID> [-Organization <ORGANIZATION_ID>]

You can find ApplicationId and ObjectId in Enterprise applications in your application’s Overview panel:

New-ServicePrincipal -AppId 061851f7-08c0-40bf-99c1-ebd489c11f16 -ServiceId 4352fc11-5c2f-4b0b-af40-447ff10664e8

Add permissions to a specific mailbox:

Add-MailboxPermission -Identity "AdeleV@your-domain.onmicrosoft.com" -User 4352fc11-5c2f-4b0b-af40-447ff10664e8 -AccessRights FullAccess

Use Microsoft Authentication Library for .NET (MSAL.NET) nuget package to obtain an access token:
https://www.nuget.org/packages/Microsoft.Identity.Client/

string clientId = "Application (client) ID";    // 061851f7-...
string tenantId = "Directory (tenant) ID";
string clientSecret = "Client secret value";

string userEmail = "Username for mailbox";    // AdeleV@...

var app = ConfidentialClientApplicationBuilder
    .Create(clientId)
    .WithTenantId(tenantId)
    .WithClientSecret(clientSecret)
    .Build();

string[] scopes = new string[] { 
        "https://outlook.office365.com/.default" 
    };

Now acquire an access token:

var result = await app.AcquireTokenForClient(scopes)
    .ExecuteAsync();

string accessToken = result.AccessToken;

Finally you can connect using IMAP/POP3/SMTP, authenticate and download user’s emails:

using (Imap client = new Imap())
{
    client.ConnectSSL("outlook.office365.com");
    client.LoginOAUTH2(userName, accessToken);
 
    client.SelectInbox();

    List<long> uids = imap.Search(Flag.Unseen);
    foreach (long uid in uids)
    {
        IMail email = new MailBuilder()
                .CreateFromEml(imap.GetMessageByUID(uid));
        string subject = email.Subject;
   }

    client.Close();
} 

Additional links:

https://docs.microsoft.com/en-us/powershell/exchange/exchange-online-powershell-v2?view=exchange-ps#install-and-maintain-the-exo-v2-module
https://docs.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-imap-and-pop-connections

Tags:     

Questions?

Consider using our Q&A forum for asking any questions.