Skip to content
English
  • There are no suggestions because the search field is empty.

Limit Mail-sendout to one Mailbox

This article explains how to restrict an application registration’s mail-sending permissions to a single mailbox.

This script configures Role-Based Access Control (RBAC) in Exchange Online for applications registered in Microsoft Entra ID (formerly Azure Active Directory). By default, an Entra ID application granted mail permissions can access every mailbox in your organization. This script locks each application down to a single, designated mailbox using the modern RBAC for Applications feature in Exchange Online — replacing the older, deprecated ApplicationAccessPolicy approach.

The script is fully idempotent, meaning it is safe to run multiple times. On each run it will detect and reuse any resources it has already created, making it suitable for initial deployment as well as ongoing maintenance when new applications are added.

 

Prerequisites

Before running the script, confirm the following:

PowerShell module The ExchangeOnlineManagement module must be installed. If you do not have it, install it by running the following in an elevated PowerShell session:

 
powershell
Install-Module -Name ExchangeOnlineManagement -Force

Permissions The account used to run the script must be a global administrator or have a delegated Exchange Online administrative role with rights to create and manage Service Principals, Management Scopes, and Management Role Assignments.

Entra ID application registration Each application must already be registered in Entra ID. You will need two identifiers for each app — both found in Entra ID → Enterprise Applications (not App Registrations):

  • Application (Client) ID — listed as "Application ID" on the Enterprise Application overview page.
  • Object ID — listed as "Object ID" on the same page.

Do not grant Graph API permissions in Entra ID You must not grant mail.send, Mail.Read, or similar Microsoft Graph application permissions to the app through Entra ID. The Exchange Online RBAC approach used by this script makes those Graph-level grants unnecessary, and granting both can cause conflicts. Permission is handled entirely by this script.

Target mailboxes Each application must be mapped to an existing mailbox using its primary SMTP address. Proxy/alias addresses will still work as valid sender addresses after setup, but the scope configuration must reference the primary address.

Step 1 — Download and open the script

Download Invoke-ExoRBACForEntraIDApp.ps1 and open it in a text editor or PowerShell ISE/VS Code.


Step 2 — Configure the application list

Locate the $appConfigs array near the top of the script (starting around line 30). This is the only section you need to edit. It contains one entry per application. Replace the placeholder values with your real application details.

Each entry follows this structure:

 
 
powershell
@{
DisplayName = "Your App Name"
AppId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" # Application ID from Enterprise Applications
ObjectId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" # Object ID from Enterprise Applications
AllowedMailbox = "mailbox@yourdomain.com" # Primary SMTP address of the target mailbox
}

Add as many entries as you need — one block per application. For example, to configure two applications:

 
 
powershell
$appConfigs = @(
@{
DisplayName = "CRM Mail Sender"
AppId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
ObjectId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
AllowedMailbox = "crm-sender@yourdomain.com"
},
@{
DisplayName = "Helpdesk Notifications"
AppId = "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"
ObjectId = "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"
AllowedMailbox = "helpdesk@yourdomain.com"
}
)

 

 

Step 3 — Set the test mailbox

Also near the top of the script, find the following line (around line 52):

 
powershell
$testUnauthorizedMailbox = "administrator@company.com"

Change this to any real mailbox in your organization that is not listed as an AllowedMailbox for any of your configured apps. The script uses this address to run a negative authorization test — confirming that none of your applications can access mailboxes they are not supposed to.


Step 4 — Review the assigned Exchange Online roles

The script assigns two Exchange Online roles to each application by default (around line 55):

 
 
powershell
$ExoAppRoles = @(
"Application Mail.Send",
"Application Mail.ReadWrite"
)

If an application only needs to send mail and does not need to read or write to the mailbox, you can remove "Application Mail.ReadWrite" from this list to follow the principle of least privilege. Make this change before running the script.


Step 5 — Run the script

Open an elevated PowerShell session and run the script:

 
 
powershell
.\Invoke-ExoRBACForEntraIDApp.ps1

The script will immediately connect to Exchange Online — you will be prompted to sign in with your admin credentials. Once connected, it will process each application in your $appConfigs list automatically.

 

What the script does for each application

The script processes each application entry through five steps:

Step 1 — Create or verify the Service Principal The script checks whether a Service Principal already exists in Exchange Online for the application's ObjectId. If it does not exist, it creates one using New-ServicePrincipal. This links the Entra ID app to Exchange Online.

Step 2 — Create or verify the Management Scope A Management Scope is created with a recipient filter targeting the application's AllowedMailbox. The scope is named using the convention Scope-Mailbox-{mailboxprefix} (e.g. Scope-Mailbox-helpdesk for helpdesk@yourdomain.com). If a matching scope already exists, it is reused.

Step 3 — Assign Exchange Online roles For each role in $ExoAppRoles, the script checks whether a role assignment already exists for this app + role + scope combination. If not, it creates a new ManagementRoleAssignment scoped to the mailbox scope created in Step 2. This means the application can only exercise those roles against the designated mailbox.

Step 4 — Positive authorization test The script calls Test-ServicePrincipalAuthorization to confirm the application is listed as in-scope for its AllowedMailbox. A green ✓ PASS message confirms the permission is active. A yellow warning means the permissions may not have propagated yet — wait a few minutes and re-run.

Step 5 — Negative authorization test The script calls Test-ServicePrincipalAuthorization against the $testUnauthorizedMailbox to confirm the application has no access there. A green ✓ PASS message confirms the application is correctly blocked. A red ✗ FAIL means the application has unexpected access to that mailbox and the configuration should be reviewed.


Reading the output

At the end of the run, the script prints a summary to the console with two tables:

Management Scopes in use — lists all scope names and their recipient filters, showing which mailbox each scope targets.

Role Assignments for configured apps — lists all role assignments for your applications, including the role name, the app ID, and the custom resource scope applied.

Console output is color-coded throughout:

  • Cyan — general progress headers
  • Green — successful creation or a passing test
  • Gray — resource already existed (no action needed)
  • Yellow — warning (e.g. permissions may still be propagating)
  • Red — error or failed test requiring attention

Troubleshooting

Authorization test shows FAIL immediately after running Exchange Online role assignments can take a few minutes to propagate. Wait 2–5 minutes and re-run the script. The idempotent design means no duplicate resources will be created.

"Failed to create Service Principal" error Verify that the ObjectId you have entered is from the Enterprise Applications blade in Entra ID, not from App Registrations. These are different identifiers.

App still has access to mailboxes it should not Ensure that no mail.send or Mail.ReadWrite Graph API application permissions have been granted to the application in Entra ID. Those grants are organization-wide and bypass Exchange Online RBAC scoping. Remove them from the app's API permissions in Entra ID.

Module not found error Run Install-Module -Name ExchangeOnlineManagement -Force in an elevated PowerShell session, then retry.


Reference

For further background on Exchange Online application RBAC, see the official Microsoft documentation: https://learn.microsoft.com/en-us/exchange/permissions-exo/application-rbac