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 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.
Note: If you still get an error running the New-ServicePrincipal cmdlet after you perform these steps, it is likely due to the fact thatthe user doesn’t have enough permissions in Exchange online to perform the operation. By default this cmdlet is available to users assigned the Role Management role
string clientId = "Application (client) ID";
string tenantId = "Directory (tenant) ID";
string clientSecret = "Client secret value";
// for @outlook.com/@hotmail accounts instead of setting .WithTenantId use:
var app = ConfidentialClientApplicationBuilder
// This allows saving access/refresh tokens to some storage
var scopes = new string
In addition, you should request offline_access scope. When a user approves the offline_access scope, your app can receive refresh tokens from the Microsoft identity platform token endpoint. Refresh tokens are long-lived. Your app can get new access tokens as older ones expire.
Now try finding account by an identifier (it will be null on first access) in MSAL cache:
string identifier = null;
var account = await app.GetAccountAsync(identifier);
AuthenticationResult refresh = await app
userName = refresh.Account.Username;
accessToken = refresh.AccessToken;
catch (MsalUiRequiredException e)
// no token cache entry - perform authentication:
Uri msUri = await app
// Add a redirect code to the above
// Microsoft authentication uri and end this request.
On the first run user will be redirected to the msUri and will see a Microsoft login screen, with option to log-in, using a known account and granting access to the app (if needed):
After successful authentication Microsoft will redirect user’s browser back to your application – to the app’s RedirectUri (in our case http://localhost/MyApp/):