Get mailbox folder permissions using EWS multithreading

A few weeks ago I was involved in a migration project. At one point in time we needed a script to retrieve permissions on mailboxes on folder-level. Besides this we needed to read the property PR_NT_SECURITY_DESCRIPTOR for folders.

Why we needed to read the property PR_NT_SECURITY_DESCRIPTOR?

Read more about in this article here!

Now back to the script. I know there are many scripts out there, which are doing this job. But we needed something to get the data real quick and a way to retrieve SIDs. I started looking for all options and ended in .NET mutlithreading for the first and MrMAPI for the second need.

I used most of Glen Scales scripts to connect to Exchange. So a huge thanks goes into his direction!

What do you need to run the script?

The script accepts the following parameters:



EmailAddress The e-mail address of the mailbox, which will be checked. The script accepts piped objects from Get-Mailbox or Get-Recipient.
Credentials Credentials you want to use. If omitted current user context will be used.
Impersonate Use this switch, when you want to impersonate.
CalendarOnly By default the script will enumerate all folders. If you want to limit to folders with type “IPF.Appointment” use this switch.
RootFolder From where you want to start the search for folders. Default is “MsgFolderRoot”. Other posible value is “Root”.
Server By default the script tries to retrieve the EWS endpoint via Autodiscover. If you want to run the script against a specific server or endpoint, just provide the name in this parameter. Not the URL!
Threads How many threads will be created. Be careful as this is really CPU intensive! By default 15 threads will be created. I limit the number of threads to 20.
MultiThread If you want to run the script multi-threaded use this switch. By default the script don’t use threads.
MaxResultTime The timeout for a job, when using multi-threads. Default is 240 seconds.
MrMapi The path to MrMapi.exe. Only full path is accepted!
UseMrMapi Switch to tell the script to use MrMapi or not.
TrustAnySSL Switch to trust any certificate.

How it looks in action?

By default it runs in the users context and also uses Autodiscover to retrieve the EWS endpoint for the given e-mail address. The root from where the script starts to search for folders is MsgFolderRoot. This is normaly the highest folder a user can reach with Outlook and set any permissions.


In order to run it against a mailbox, where you don’t have access you need to Impersonate


Otherwise you will get an error


Here when you use multithreading


Note: Please be warned that the performance heavily depends on your machine! By default 15 threads will be created, which could overhelm your machine!

When you are using multithreading and you want to stop all of the threads it is not sufficient to stop the script with CTRL+C. This will only stop the script, but the RunspacePool and the queued threads are still there. You would need to close the PS process in order to have all of them stopped.

Therefore I added some logic to the script. If you want to stop all the threads and exit the script just press CTRL+Q. The script is listening to this combination and will start to kill all the queued threads and exit the script.



To see the difference between multithreading vs. not multithreading here some statistics:


48sec. vs 138sec. makes a factor of 2,875 faster. But this was only in my lab, which is not well sized. I did the same test in a productive environment:


Here I got 152sec. vs 1441sec. , which is a factor of 9,48.

You can gain some more speed, when you define the server instead of having the script using AutoD for each mailbox.

As an example what I did during a migration and I needed to retrieve all affected mailboxes:

Get-Mailbox -ResultSize unlimited|
 .\Get-MailboxFolderPermissionEWS.PS1 -Server -Impersonate -UseMrMapi -MrMapi C:\Temp\Scripts\mrmapi.exe -MultiThread -Threads 15 |
?{($_.User -notmatch 'ANONYMOUSLOGON')-and ($_.User -ne $null) -and ($_.User -notmatch 'Everyone') -and ($_.SIDinSD -notmatch 'S-1-5-21-398472632-1282482148-99536377')}|
Export-Csv -NoTypeInformation -Path .\SID_Report.csv

With this I had a CSV file from where I could proceed.

Feedback is always welcome!



4 thoughts on “Get mailbox folder permissions using EWS multithreading

  1. Pingback: The good, the bad and sIDHistory | The clueless guy

  2. Pingback: Get-DatabaseEvent: Who deleted my items? | The clueless guy

  3. Pingback: 获取邮箱目录权限 - Exchange中文站

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s