March 3, 2026

Restricting Microsoft Graph Mail Access with Application Access Policies: A Complete Guide

When integrating Microsoft 365 workloads with Microsoft Graph, one of the most overlooked security risks is granting an application too much access. If an Azure AD app is assigned Mail.Read (Application) permissions, it can read email from every mailbox in the tenant using a simple Graph call:

GET https://graph.microsoft.com/v1.0/users/{id}/messages

This default behavior is powerful—but extremely risky.

Most applications only need access to a few mailboxes, not the entire directory. Without restrictions, your app could unintentionally access executive mail, HR communications, or legally sensitive data.

In this blog, we walk through how to restrict your application’s access so it can only read emails from a specific list of users, using Application Access Policies—a secure and recommended approach.

Relevant Microsoft Documentation

Understanding the Problem

Graph Application Permissions grant broad, tenant-wide access. This is ideal for:

  • Background services
  • Daemon applications
  • Automation tools

But it also means the app can access all mailboxes unless restricted.

Examples of apps that should NOT have tenant-wide access:

  • A ticketing system that reads only support@contoso.com
  • An Azure Function processing emails for one department
  • A compliance tool reading from a select shared inbox

To enforce the principle of least privilege, we need mailbox-level controls.

How Application Access Policies Solve This

Application Access Policies allow Exchange Online to limit an application to a specific set of mailboxes, defined by membership in a Mail-Enabled Security Group (MESG).

What the Policy Does

  • Allows Graph access only to users in the MESG
  • Blocks access to all other mailboxes (returns 403 Forbidden)
  • Applies automatically to all Graph calls using application permissions

Important Propagation Delay

After creating or updating a policy, it takes 30 minutes to 2 hours for the policy to fully propagate across the Microsoft 365 ecosystem.

Testing immediately after creation may produce inconsistent results until the policy finishes syncing.

End-to-End Implementation Flow

  1. Create the Azure AD App Registration
  2. Create a Mail-Enabled Security Group (MESG)
  3. Install and Connect Exchange Online PowerShell
  4. Create the Application Access Policy
  5. Validate the Policy
  6. Validate Using Microsoft Graph
  7. Review a Real-World Scenario
  8. Conclusion

1. Create the Azure AD App Registration

Steps

  • Go to Azure AD → App registrations → New registration
  • Enter a name
  • Select "Accounts in this organizational directory"
  • Register the app

Add a Client Secret

Create a client secret for authentication between your application and Microsoft identity platform.

Assign Microsoft Graph Application Permissions

  • Mail.Read
  • Mail.ReadWrite (if required)
  • User.Read.All (optional)

After adding permissions, Grant admin consent.

App registration permissions

2. Create a Mail-Enabled Security Group (MESG)

Only mail-enabled security groups are supported by Application Access Policies.

Unsupported Group Types

  • Microsoft 365 groups
  • Distribution lists
  • Standard security groups

Example MESG:

  • Name: AllowedMailboxAccess
  • Email: allowed.mailaccess@contoso.com

Add Allowed Mailboxes

  • john.doe@contoso.com
  • jane.smith@contoso.com

Do not add users who should be restricted.

MESG configuration

3. PowerShell Requirements

Install Exchange Online Module

Install-Module ExchangeOnlineManagement -Scope CurrentUser

Connect to Exchange Online

Connect-ExchangeOnline

Authentication is required before creating or managing Application Access Policies.

4. Create the Application Access Policy

New-ApplicationAccessPolicy `
  -AppId "YOUR-APP-ID-HERE" `
  -PolicyScopeGroupId "allowed.mailaccess@contoso.com" `
  -AccessRight RestrictAccess `
  -Description "Restrict Graph Mail.Read access to approved users"

What This Enforces

  • The application can only access mailboxes in the MESG
  • All other mailboxes return 403 Forbidden
  • Applies to client_credentials flow

5. Validate the Policy

Test an Allowed Mailbox

Test-ApplicationAccessPolicy `
  -Identity "john.doe@contoso.com" `
  -AppId "YOUR-APP-ID-HERE"

Expected: AccessCheckResult : Granted

Test a Blocked Mailbox

Test-ApplicationAccessPolicy `
  -Identity "unauthorized.user@contoso.com" `
  -AppId "YOUR-APP-ID-HERE"

Expected: AccessCheckResult : Denied

Note:If you receive unexpected results, allow 30 minutes to 2 hours for propagation.

6. Validate Using Microsoft Graph

Allowed mailbox:

GET https://graph.microsoft.com/v1.0/users/john.doe@contoso.com/messages

Should return 200 OK.

Blocked mailbox:

GET https://graph.microsoft.com/v1.0/users/unauthorized.user@contoso.com/messages

Should return 403 Forbidden.

7. Example: Real-World Scenario

An AI email classifier running as an Azure Function should only access:

  • support@contoso.com
  • billing@contoso.com

Without restrictions, it could access executive, HR, or legal mailboxes. With an Application Access Policy, access is limited strictly to approved accounts.

Conclusion

Application Access Policies are the safest and most effective way to restrict Microsoft Graph application permission access to specific mailboxes.

  • Least privilege access
  • Compliance-friendly restrictions
  • No accidental overexposure of user data
  • Server-enforced controls beyond application code

This creates a secure and controlled environment for Exchange Online mailbox access.

No comments:

Post a Comment