Programmatic access to an Exchange Online mailbox

Last updated: September 14, 2022
Audience: IT Staff / Technical

You may have a valid business need to access a single Exchange Online mailbox via code. That sort of access can only be accomplished via use of OAuth. Microsoft provides several solutions for this via either Microsoft Graph or the Exchange Web Services APIs. However, depending on the approach, those solutions may require what are generally broad & risky permissions, i.e. getting admin consent for OAuth permission scopes, which effectively mean your identity has access to *all* Exchange mailboxes. This generally is not acceptable–it is too risky to allow any account access to all UW Exchange mailboxes. Microsoft recognized this problem and provided a solution in the form of ApplicationAccessPolicy which limit the effective permissions of OAuth permission scopes to specific Exchange resources. Another solution is to have the single user whose mailbox you need to access to interactively consent to the permissions.

Solution 1: OAuth delegated permissions (user consent), with a single interactive access of the Azure AD identity and thereafter non-interactive access

  1. Get an Azure AD application identity created. Azure AD application creation & configuration is mostly a self-service activity. We’ve created documentation about the many related activities at: https://itconnect.uw.edu/wares/msinf/aad/apps/integration/.
  2. Configure the code using that Azure AD app identity using the OAuth client credential grant flow: https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow
  3. That AAD app will need to use either the MS Graph API or Exchange Web Services API (with one of the corresponding permission scopes documented at https://docs.microsoft.com/en-us/graph/auth-limit-mailbox-access). MS Graph is preferred as it provides more granular permission scopes. The permission scopes will need to be configured to be OAuth delegated permissions (not application permissions): https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-permissions-and-consent#permission-types
  4. Interactively access your Azure AD application identity and sign in as the user whose mailbox is your target. The user will get consent prompt which you must accept. How you accomplish this step depends on how your application identity is configured and your code.
  5. Use your code in a non-interactive manner from then on.

Solution 2: OAuth application permissions (admin consent) & completely non-interactive

  1. Get an Azure AD application identity created. Azure AD application creation & configuration is mostly a self-service activity. We’ve created documentation about the many related activities at: https://itconnect.uw.edu/wares/msinf/aad/apps/integration/.
  2. Configure the code using that Azure AD app identity using the OAuth client credential grant flow: https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow
  3. That AAD app will need to use either the MS Graph API or Exchange Web Services API (with one of the corresponding permission scopes documented at https://docs.microsoft.com/en-us/graph/auth-limit-mailbox-access). MS Graph is preferred as it provides more granular permission scopes. The permission scopes will need to be configured to be OAuth application permissions (not delegated permissions): https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-permissions-and-consent#permission-types
    1. NOTE: If your client is interactive, then you can and should use delegated permissions. In that case, you would not need admin consent and could skip #4 and #5. Each user would then be asked to consent to the permissions via the interactive sign in process the first time they try to get an access token. But this page is about programmatic access, so it is assumed this is not an interactive client.
  4. Open a Productivity Platform Recharge Request: https://itconnect.uw.edu/connect/productivity-platforms/pplat-recharge-services/
    1. In that request ask them to create an Exchange ApplicationAccessPolicy which limits that AAD app to the specific mailbox(es) necessary: https://docs.microsoft.com/en-us/graph/auth-limit-mailbox-access
  5. Open a risky Azure AD application admin consent request: https://itconnect.uw.edu/wares/msinf/aad/apps/risky-aad-app-perms/
    1. In that request ask for admin consent of the OAuth permission scopes needed.
    2. Make sure to reference the REQ number from step #4 as a mitigating factor.
  6. Use your code

Authenticate an IMAP, POP or SMTP connection using OAuth

If you are trying to authenticate an IMAP, POP or SMTP connection using OAuth, Microsoft has some general guidance about it here:

https://docs.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-imap-pop-smtp-application-by-using-oauth

There is also a video walkthrough here:

https://www.youtube.com/watch?v=bMYA-146dmM