Managing mailbox folder permissions in bulk in Microsoft 365

Few years back, I published few PowerShell script samples to illustrate how you can add/set/remove/reset mailbox folder permissions in bulk. Now, it’s time to update said scripts to leverage the Exchange Online V3 PowerShell module, which in turn means the new versions of the scripts will only work for Exchange Online. For on-premises installs, you can still leverage the old versions.

The idea behind the scripts remains the same – they allow you to bulk add or remove permissions on the folder level, while taking care of enumerating all the (user accessible) folders within the mailbox(es) in question, so instead of running one cmdlet for each folder, you can make the changes in one go. In order to obtain the list of folders, the scripts call the Get-ExOMailboxFolderStatistics cmdlet, then apply some logic to filter out folders that are not accessible by the user, or might simply be of no interest. Two variables are involved in the process:

$includedfolders = @("Root", "Inbox", "Calendar", "Contacts", "DeletedItems", "Drafts", "JunkEmail", "Journal", "Notes", "Outbox", "SentItems", "Tasks", "CommunicatorHistory", "Clutter", "Archive", "Scheduled")

$excludedfolders = @("News Feed", "Quick Step Settings", "Social Activity Notifications", "Suggested Contacts", "SearchDiscoveryHoldsUnindexedItemFolder", "SearchDiscoveryHoldsFolder", "Calendar Logging", "EventCheckPoints")

The $includedfolders variable holds the list of default folders, addressed by their folder type value. Unfortunately, not every folder created by Exchange or email clients is tagged as default, so the above variable does not address all such folder (i.e. “News Feeds” or “Suggested Contacts”). To give you the opportunity to exclude such folders, as well as any user-created folder you might not want to act against, the $excludedfolders variable contains a list of folder names to exclude. As the name can vary due to regional settings, make sure to replace the default values for any non-English mailboxes.

And since in some cases you might want to only run the script against a set of (sub)folders under say Inbox, the script features the –ParentFolderPath parameter to further scope down the list of folders. The whole logic of gathering the set of folders is contained within the ReturnFolderList helper function, which you can edit as you see fit.

Once the set of mailbox folders is obtained, the scripts loop over each of them and execute the Add-/Set-/Remove-MailboxFolderPermission cmdlet as needed. The beauty of the scripts is that they allow you not only to run said cmdlets against each folder in a given mailbox, but you can also run them in bulk against a set of mailboxes and/or a set of users. To avoid unnecessary executions and speed up the overall processing time, the scripts also feature some logic to detect erroneous values for the mailbox and/or user parameters, but do not expect every corner case to be addressed.

Speaking of parameters, here’s the full set:

  • Mailbox: used to designate the mailbox on which permissions will be adjusted. Any valid Exchange mailbox identifier can be specified. Multiple delegates can be specified in a comma-separated list or array. You can also use the Identity parameter as alias.
  • User: used to designate the user to which permissions will be granted (or removed). Any valid Exchange security principal can be specified, including Security groups. Multiple delegates can be specified in a comma-separated list or array. You can also use the Delegate parameter as alias.
  • AccessRights: used to specify the permission level to be granted. Any valid folder-level permission can be specified. Roles have precedence over individual permissions entries. For more details read here: https://docs.microsoft.com/en-us/powershell/module/exchange/mailboxes/Add-MailboxFolderPermission?view=exchange-ps
  • ParentFolderPath: used to scope the script execution to only the set of folders under the specified parent path.
  • ResetDefaultLevel: used for the Reset_Folder_Permissions_recursive_BULKV2.ps1 script only. Signals whether you want to reset the permission entries for the Default principal to their standard values (AvailabilityOnly for the Calendar folder, None for all other folders).
  • WhatIf: used to run the script in a “simulation” mode, without making any actual changes. Works the same way as with other Exchange cmdlets.
  • Verbose: used to force the script to provide additional details on the cmdlet progress. Useful when troubleshooting issues or previewing the execution.
  • Quiet: used to suppress output to the console. By default, each added/changed permission entry will be displayed in the console, apart from saving it to the CSV file.

The set of parameters available will differ between the scripts, as there is no need for a –User parameter when resetting mailbox folder permissions to their default values, for example. Similarly, there is no need for –AccessRights parameter when resetting or removing mailbox folder permissions. The rest of the parameters should be available for all scripts. Speaking of which, here are the actual script files:

Here are also some examples on how to utilize the scripts. Let’s start with the “add permissions” scenario, where you need to specify the mailbox, user and access rights. The below example will enumerate each folder within the “shared” mailbox and recursively grant the Owner permission level to the user UserX. If an existing permission entry is found for said user, it will be replaced with the newly provided AccessRights value.

.\Set_Folder_Permissions_recursive_BULKV2.ps1 -Mailbox shared -User UserX -AccessRights Owner

Of course, processing mailboxes one at a time is no fun, so here’s how to leverage the script to add permissions in bulk. Here, we provide a set of mailboxes, designated by their Alias value. The script will try to resolve the provided values against the set of mailboxes within the organization, removing any non-existent or duplicate entries. Similarly, the set of provided user identifiers will be matched against the directory to ensure that a valid security principal object is found. Lastly, instead of using a built-in role such as “Owner”, we specify individual permissions to be added.

.\Set_Folder_Permissions_recursive_BULKV2.ps1 -Mailbox shared1,shared2,shared3 -User john@contoso.com,jane@contoso.com -AccessRights CreateItems,DeleteOwnedItems

An even better example illustrates how you can pass values directly from cmdlets such as Get-Mailbox or Get-User, for even more flexibility. Herein, we also make use of the –ParentFolderPath parameter to limit the permission changes to the Calendar folder and any subfolders therein. Lastly, for any bulk scenarios I’d strongly recommend you leverage the –Verbose and –WhatIf parameters in order to “preview” the changes first.

.\Set_Folder_Permissions_recursive_BULKV2.ps1 -Mailbox (Get-Mailbox -RecipientTypeDetails RoomMailbox) -User (Get-User -Filter {Department -eq "Sales"}) -AccessRights Author -ParentFolderPath "/Calendar" -WhatIf -Verbose

Here’s also a good place to mention that each script will generate output listing the mailboxes, users and permission changes involved. The output is dumped to the console and a CSV file within the script directory by default, though you can “silence” it via the –Quiet parameter. Here’s how sample output looks like:

Mailbox FolderName User
------- ---------- ----
shared@michev.info IM huku
shared@michev.info IM vasil
shared@michev.info Vasil Michev-7/11/2016 5:36:12 PM huku
shared@michev.info Vasil Michev-7/11/2016 5:36:12 PM vasil
shared@michev.info Primary Mailbox huku
shared@michev.info Primary Mailbox vasil

 

As an example of removing permissions via the Remove_Folder_Permissions_recursive_BULKV2.ps1 script, the below will process the mailboxes “shared” and “sh1ared” (non-existent one), enumerate each folder under the /IM subtree within them, and for each folder found remove any permissions granted to the set of users specified. Well, once you remove the –WhatIf switch, that is 🙂

.\Remove_Folder_Permissions_recursive_BULKV2.ps1 -Mailbox shared,sh1ared -User huku,tanya,vasil -Whatif -Verbose -ParentFolderPath "/IM"

As the Remove-MailboxFolderPermission cmdlet does not feature an –AccessRights parameter, there is no need to provide such for the script either. Similarly, when using the Reset_Folder_Permissions_recursive_BULKV2.ps1 script to “reset” folder-level permissions, there is no need for a –User parameter either. Thus, the example below will process any folder within the “shared” mailbox for which the “Kalender” one is parent (note the German value provided due to the mailbox’s locale), and purge any non-default entry found therein. In addition, the permission level for the Default principal will be set to it’s “standard” value of “AvailabilityOnly”, since we have specified the corresponding –ResetDefaultLevel switch.

.\Reset_Folder_Permissions_recursive_BULKV2.ps1 -Mailbox shared -Verbose -ParentFolderPath "/Kalender" -WhatIf -ResetDefaultLevel

 

Compared to the original version of the scripts, some additional changes have been made (apart from switching to the V3 ExO module that is). The biggest ones are around error handling, as the PowerShell Core/v7 versions of the module returns crappier error objects, thus we’re forced to parse the Exception.Message property instead or relying on an actual CategoryInfo.Reason value. Some additional changes were forced due to other bits and pieces overlooked by Microsoft’s engineers, such as the fact that the Get-SecurityPrincipal cmdlet no longer supports an –ErrorAction parameter?!

Other minor changes to the scripts include “silencing” some of the Verbose output, as the ExO V3 module cmdlets seem to be way too chatty when said switch is invoked. The connectivity block is replaced with one suitable for the ExO V3 module, the logic of which is contained within the Check-Connectivity helper function. By default the scripts will check for existing connection via the Get-ConnectionInformation cmdlet, then try the Get-ExOMailbox one and if no active session is found will try to establish a new one. Be warned that only the cmdlets required by the script will be loaded in such session, in order to minimize the footprint of running the script. To be on the safe side, I’ve left some of the Start-Sleep anti-throttling controls, though the V3 module should handle things much better.

2 thoughts on “Managing mailbox folder permissions in bulk in Microsoft 365

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.