PowerShell script for Exchange mailbox item (email, meeting, contacts, etc.) removal.

You might have a situation when someone – it might have even been you – send or receive an email that shouldn’t be sent or received.

It might have been a SPAM sent to your organization or an email that supposed to be send to your colleague but was send to a bunch of other people and had naked ladies in the attachment.

After sending such email reaction chain is as follows:

First you noticed that you have might clicked “Send” button, maybe you clicked CTRL + Enter combination, but you still not sure…


Continue reading “PowerShell script for Exchange mailbox item (email, meeting, contacts, etc.) removal.”

Exchange mailbox/folders permissions – dependency graph between users.

Following solution uses GraphViz application to visualize mailboxpermissions dependencies in the company.

Some time ago I published a scripts for reading mailbox permissions:


and mailbox folder permissions:


If some of you are wondering what GraphViz is, a quick look on google graphics and phrase “graphviz”, gives us an idea of how gorgeous graphs it can create:


All the GraphViz needs is to have properly formatted input file – that’s it!


The need of having such script showed up as one time I was standing in front of migrating users to Exchange Online. I started to wonder how shall I visualize in a simply way, who need to be migrated together…


It was not an easy task, going though a excel/csv file, or even creating lists were not satisfying for me, so I started to think about it more, even during meals…


And then I found GraphViz:


It was looking really good! So now just a matter of quick reading about it checking if it will apply…


…reviewing the idea…


…some calculations…


And after all that research the idea became clear…


As I mentioned at the beginning, input file can be done with one of the mailbox permissions / mailbox folder permissions reading scripts – links provided on the top (you might need to change delimiters a little bit as I guess in these files are “;” but go for adventure and modify something :))

The proper input should look like:


So it has columns named “Mailbox”, “User” and “AccessRights”

And now the script. In organization I was building script for – it appeared that we have so many permissions I almost shat brikcs when I saw the actual output (graph)…

Just take a look by yourself, here is just a very small piece of graph when I was checking dependencies of just one mailbox – mine:



Let’s go closer:



Imagine now that whole dependency graph contained like 10 more same chunks/pieces, 10 more, 10 fuck*ng times!

Well, I needed somehow to…


So the idea of migrating people together in chunks fell down and broke into pieces :] but at least we have that nice script.

  1. First thing is to get GraphViz application and install it:

Here you can find it:


After installation all you need to to read your mailbox permissions – you can choose to read it with scripts from links given at the beginning of that article.

     2. Next thing, is to set up 3 variables:


$GraphImageFile = “GraphImageFile.png” -> this is the name/path of your output file – actual graph

$GraphGraphVizFile = “GraphVizFile.gv” -> this is the name/path of the input file that will be passed to GraphViz to visualize your data, it will look similar to this one:


$CSVPermissionsFile = “Permissions.csv” –> and finally this is the input file for the script – so output from your script that reads permissions from mailboxes

    3. Having CSV we can start reading permissions, so here are some examples.

After running below:

.\PermissionMatrixGraphBuilder.ps1 -users “Pawel Jarosz”, “Wladek Ksiegowicz”


We will get:


Users mentioned in “Users” array will be marked on blue, nice arrows will show direction of permissions 🙂

After running:

.\PermissionMatrixGraphBuilder.ps1 -users “Pawel Jarosz”, “Wladek Ksiegowicz” -SingleUser $true


We will get:


And finally after running same but with “level” set to 1 we will get:

.\PermissionMatrixGraphBuilder.ps1 -users “Pawel Jarosz”, “Wladek Ksiegowicz” -Level 1


That will runthough the whole file ONLY ONE TIME, and what we will get would be something like:


So summing up – for me script does a good job when it comes to visualize data that would be actually really hard to see from a excel file.

It is just an easy script, please note that you can add here features like:

  • adding description to each “connection” saying to which folder permissions are given
  • reading mailboxes sizes and adding them to the graph so it can ease planing of migration of certain groups of people
  • remember – possibilities are endless:




Script can be found on TechNet and GitHub.


Remove cancelled Outlook meetings using PowerShell and EWS.



Recently there was a business demand for removal of meetings that were canceled in our resource mailboxes. Thought it was some sort of  a bug but then saw that problem was “AutomateProcessing” attribute on these was set to “AutoUpdate” not “AutoAccept” (This can be checked using Get-CalendarProcessing cmdlet).


So when someone is scheduling a meeting form his own mailbox and is picking up room – creates a meeting, and later changes his mind and removes it, it still is hanging there visible as “Canceled: Subject of the meeting“. And each time (because of that “AutoUpdate”) someone manually needs to go there and remove it.



After reading a bit about that topic, I realized that PowerShell script I was about to write needs to use EWS and impersonation in Exchange.

There are few things you need before running the script:

  • AD account used by the script
  • Security Group that will contain people who will have impersonation rights (admns/service accounts)
  • Distribution List that will contain room mailboxes – managed by admins/service accounts from Security Group
  • Management Scope in Exchange – narrowing scope for members of the Distribution List
  • Management Role Assigment – glue all that crap together – permission Security Group to Distribution List with “Application Impersonation” rights.

In commands it can look like:

1. Creating Distibution Group

New-DistributionGroup -Name ‘RoomImpersonationGroup‘ -Type ‘Distribution’ –OrganizationalUnit ‘contoso.com/Distribution Lists’ -SamAccountName ‘RoomImpersonationGroup’ -Alias ‘RoomImpersonationGroup’ –managedBy ‘PawelJarosz’

2. Creation of Exchange Management Scope:

$Grupa = Get-DistributionGroup -Identity “RoomImpersonationGroup”
New-ManagementScope “Room Mailboxes Impersonation” -RecipientRestrictionFilter “MemberOfGroup -eq ‘$($Grupa.DistinguishedName)'”

3. Creation of security group “ExchangeRoomImpersonation” in Active Directory

NEW-ADGroup –name “ExchangeRoomImpersonation” –groupscope Universal –path “OU=Offices,DC=Contoso,DC=local” -GroupCategory Security

4. Creation of new Exchange Assigment Role:

New-ManagementRoleAssignment -Name “Room Mailboxes Impersonation Assigment” -Role “ApplicationImpersonation” -CustomRecipientWriteScope “RoomImpersonationGroup” -SecurityGroup “ExchangeRoomImpersonation”


If you have all of that or you do not need to configure it as there are some service accounts you will use that are permissioned to impersonate globally – omit all these steps.

Some details about the script:

DeleteCanceledMeetings.ps1 - Cancelled meetings removal script.

.PARAMETER SearchStartDay
(OPTIONAL) Specifies START date from which sript should start searching of 
If not specified the today's date is used.

(MANDATORY) Specifies END date till which sript should start searching of 

(MANDATORY) Specifies mailboxes from which cancelled meetings should be removed.
As this is an array it accepts many mailboxes given after coma.

(OPTIONAL) Triggers HardDelete action on cancelled meetings if equal "True". 
Without it it generates a on screen report.

.\Get-MailboxPermissions.ps1 -SearchStartDay 10 -SearchEndDay 30 -Room Room1,Room2
Starts searching of meetings 10 days back and 30 days in front 
for 3 rooms Room1,Room2.
Returns a on screen report.

.\Get-MailboxPermissions.ps1 -SearchEndDay 90 -Room Room1,Room2,Room3 `
 -HardDetele True
Starts searching of meetings starting from current day and 90 days in front 
for 3 rooms Room1,Room2,Room3 and hard deletes them.
Reruns a CSV report and a log file.

You need to modify these lines in order to get logging working:


And you are ready to go! 🙂

Please remember that when runnig the script:


Script can be found on my Technet and GitHub

Have fun with IT!

Match and Like shows that string has “$”,”*” and “?” while it doesn’t.

“Microsoft Office 365: Exchange Online Implementation and Migration” tells that we need to check following users’ attributes in regards to occurrence special characters:

    sAMAccountName: Invalid character examples are !, #, $, %, ^, &, {, }, \, /, `, ~, “, [, ], :, @, <, >, +, =, ;, ?, and *
    displayName: Invalid character examples are ?, @, and +
mail: Invalid character examples are [, !, #, $, %, &, *, +, \, /, =, ?, ^, `, {, }, and ]
    mailNickname: Invalid character examples are “, \, /, [, ], :, >, <, ;, and spaces
    proxyAddresses: Invalid character examples are [, !, #, $, %, &, *, +, \, /, =, ?, ^, `, {, }, and ]
userPrincipalName: Invalid character examples are }, {, #, ‘, *, +, ), (, >, <, \, /, =, ?, and `

Well, you agree that nothing easier. So I wrote a simple script that was checking for it, but to my surprise, I noticed that in 3 of the attributes I was getting “$”, “*” and “?” characters. But attributes definitely didn’t have that value, so I replaced “-match” with “-like” in the script.

Well, it was better but still not brill. I  was still getting $ and *. But the ? char was not being reported. I started to think what the hell is wrong felling a bit like:


I was using “-match” and “-like” all the time in scripts, I was shocked it was messing around with me. So I started to check if there are any other way to compare if char exist in a string. And there it was! Totally forgot about “contains” operator/method!

Changed all my “matches” and “likes” to “-contains” and taaaddaaam 🙂 All worked like a charm!

Answer to question why it might have not worked can be found for example under here:


Tom is telling there that:

-contains is designed to work on arrays, not strings (referred to as a containment operator)
-match looks for a match inside a string and supports regexes
–like looks for a match inside a string and supports wildcards

And here is the thing, my solution was about to check if string, ex. “mail” contains: one of [, !, #, $, %, &, *, +, \, /, =, ?, ^, `, {, }, ] . Syntax was:

$Characters_To_Check = @(“[“, “!”, “#”,”$”, “%”, “&”, “*”, “+”, “\”, “/”, “=”, “?”, “^”, “`”, “{“, “}”, “]”)

$String_To_Check = “$User.mail”

Foreach ($Character in $Characters_To_Check ) {

if ($String_To_Check -match $Character) {Do things}


because “match” and “like” operators support regex and wildcards, they were treating these special characters as these. Only contains was working properly in that particular case.


Script to check mailbox permissions

Recently I have written a script for getting mailbox permissions.

Script reads permissions and puts it in CSV. I have used a lot from Get-MailboxReport.ps1 script wrote by Paul Cunningham.

Data can be read from mailboxes individually, for specific mailbox server or all mailboxes:



At the end it gives CSV output like:


Script can be found on Technet – link >> TECHNET



Capacity planning for Exchange

As I am preparing now for MCSE in Exchange 2013 and reviewing book for 70-341 exam [Core Solutions of Microsoft Exchange Server 2013 (MCSE)].

Just going through chapter about capacity planning and found some useful links in relation to that, thought worth sharing:

How to Calculate Your Disk I/O Requirements (Exchange 2003)


Exchange 2013 Server Role Requirements Calculator v7.6


Disk Performance Testing with JetStress 2013


Exchange 2010 Sizing Cheat Sheet


Exchange 2013 Mailbox Role Counters (Advanced)


Ask the Perf Guy: Sizing Exchange 2013 Deployments


Virtualization of Exchange 2013


Exchange 2010 Personal Archive

Lately I was wondering how PA engine works, basically what triggers the actual move of emails in mailbox.

I thought it was the AutoArchive setting in the AD, but as I read in the net + my colleagues shared with me some knowledge 😉  that setting applies to pst files only.

It appeared that by default the “schedule” is running once per day, you can check it by runnig cmdlet:

Get-MailboxServer <SERVERNAME> | fl *managed*

ManagedFolderWorkCycle set to 1.00:00:00 means it is scheduled every one day.

To operation we can also enable logging by setting FolderLogForManagedFoldersEnabled to $true

If we want to force this operation to be done, we can user this cmdlet:

Start-ManagedFolderAssistant <mailbox>

After running that command, person can see in her/his outlook how the elements are being moved to archive folder, and folders are being created 🙂