Office 365: How to scope impersonation when migrating to and from Exchange Online

When you’re migrating to or from a Microsoft Exchange system, using an awesome tool like the BitTitan MigrationWiz, that leverages the Exchange Web Services (EWS) for the migration, you have 2 main options for administrator access to the mailboxes you’re migrating to and/or from: Impersonation and Delegation.

The best option depends on if the Exchange server is the online version (Office 365 multi tenant) or on premises. For Exchange on premises you should use delegation and for Exchange Online you should use impersonation. Why? Because you can’t create throttling policies in Exchange Online and impersonation is much less subject to throttling, when compared with delegation.

It’s important to understand that impersonation will also be subject to throttling, just not as much as delegation. When you’re migrating with delegation, all actions are done on behalf of the admin account, as opposed to when you’re migrating with impersonation, where actions are made on behalf of the account that is being migrated and impersonated.

Now that we can all agree that impersonation is the best authentication method for Exchange multi tenant systems (by the way this also applies to hosted Exchange systems outside of Office 365, but setting up impersonation on those systems might be somethings Hosters won’t do, unless they scope it, which they usually don’t), lets discuss the topic of this post: How can you scope impersonation? What exactly does that mean? And when will this be useful?

The answer for the first question is that you can scope impersonation by using management scopes and management role assignments.

As for the second question, scoping the impersonation rights means basically that the admin account will only be able to impersonate the accounts you define within that scope filter.

Finally the third question: this is useful when, for security reasons, you (or someone from the security team of the source or destination tenant) don’t want the admin account, that will perform the migration, to have access to impersonate all users in the tenant. This is a very common scenario in mergers, acquisitions and divestitures, where the admin user doesn’t need access to users that are not part of the migration.

Now lets translate all of this into a step by step guide of what you need to do, in order to scope impersonation in your Office 365 tenant.

Step 1: Create a distribution group

There are many different ways to apply a filter into a scope, and limit a management role assignment such as Application Impersonation, to a specific scope. I will teach you a simple way: via group membership.

You can create the group via the 365 management console or via the PowerShell. I recommend that you create a simple group as shown below (apologies, my current Office 365 tenant is in Portuguese, but I guess you can all recognize and understand the UI 🙂 ):


TIP: If you create this group just for the purpose of scoping impersonation, I recommend that you hide the group from the Global address list.

Now that the group is created, lets retrieve its DistinguishedName property:

Get-DistributionGroup -Identity AllowImpersonationDistributionGroup |fl name, dist*


Note: In the command above use your own Distribution group name, as you created it, or just run the Get-DistributionGroup without specifying the identity, and grab the DistinguishedName from the correct group (all will be listed).

Step 2: Create a Management Scope

Create a new management scope, use the “RecipientRestrictionFilter” parameter and the “MemberOfGroup” filter:

New-ManagementScope RestrictedMigrationScope -RecipientRestrictionFilter {MemberOfGroup -eq ‘CN=AllowImpersonationDistributionGroup,,OU=Microsoft Exchange Hosted Organizations,DC=EU


Note: To run the command above you might need to enable the Organization customization in your Office 365 tenant.

Step 3: Create the Management Role Assignment

Now that we have the scope created the last step is to create the management role assignment and associate it with the admin migration account:

New-ManagementRoleAssignment -Name:MyMigration -Role:ApplicationImpersonation -User:user10@ -CustomRecipientWriteScope:RestrictedMigrationScope


Note: In the command above use the scope name and the admin account that you are using for the migration. For my migration the admin is

And that is it, job done. Lets do some testing.

Below you can see users 1 to 5, that I will be migrating, and user10 that I will use as an admin.


Now looking at the group membership you can see that only user1, user3 and user5 are withing the scope, which means that user10 won’t be able to impersonate users 2 and 4.


Finally the result in MigrationWiz, in a project configured to use impersonation and with user10 as the source admin.


As you can see above, users 2 and 4 failed, and here’s the detailed error.


Bingo… MigrationWiz failed to impersonate at the source. Of course now that you read this that error will never happen to you!! 🙂

Happy migrations and as usual if you have any questions let me know.



The complete journey from Google to Exchange Online with Free/Busy rich coexistence

When questioned by partners, on what is the best approach to plan and execute a move of a customer’s email system, from G-Suite to Exchange Online in Office 365, the first questions that I ask are:

How many users do you have to migrate?

Are you going to do a migration in batches (Staged) or cut over all users at the same time?

Usually when there’s a large number of users, the migration in batches is the preferred option. At that point you should consider two things:

  • How can I automate the mail flow changes
  • How can I have free/busy coexistence between G-Suite and Office 365

The answer to both questions above is simple: You can automate the mail flow and have free/busy coexistence if you use BitTitan MigrationWiz to move the mailboxes, and the BitTitan automation processes to help you with the changes you need to do per migration batch.

In the past I wrote an article on how to configure mail flow coexistence between Google Apps and Office 365, that can help you understand the configurations you need to do.

BitTitan also has a very good article on how you can automate the mail flow changes, on a mail migration from Google to Office 365, as well as the entire migration guide.

But I want to focus this article more on the free/busy rich coexistence, between Google and Office 365, the value that it brings to your migration and your customer, a technical overview on how it works, and of course how you can configure it.

What is the value on having free/busy coexistence between G-Suite mail and Office 365 Exchange online

User experience. It’s all about the user experience!!! If you are moving a 20k users company from Google to Office 365, you often get questioned about what the migration journey will mean for the end users, in terms of end user experience. When you provide your customer and their end users the ability to have not only mail flow coexistence (that one is mandatory of course) but also calendar free/busy lookup capabilities, you’re giving them the best experience they can have.

I have also seen more and more companies using the BitTitan Google coexistence tool for permanent free/busy coexistence between G-Suite and Exchange Online, so don’t think about it just like an add-on to a migration project, it can be much more than that.

How can I achieve that with BitTitan

Currently BitTitan will allow you to use the Google coexistence tool for free during 3 months, if you use BitTitan MigrationWiz to move all of the mailboxes. If you want coexistence for more than 3 months, or if you’re not using MigrationWiz, you will be quoted a price per user per month.

Note: The statement above was true when I wrote this article. There no guarantee that will be true when you read it so please contNact BitTitan for more information.

Why do I need a free/busy coexistence tool between Google and Office 365

The answer to this is short and simple: the Google Calendar Interop, which is the tool that you need to configure on your Google tenant to query free/busy from Exchange mail systems, cannot query free/busy information, from an Exchange Online mailbox, via the Exchange Web Services API and the Availability Service. Instead it will try and query free/busy information from an Exchange Public folder. The problem is that the newer versions of Exchange don’t support that method anymore.

So in essence, because the Google Calendar Interop hasn’t evolved to match the changes that the Microsoft Exchange product group implemented in the way the free/busy is queried, specifically on the transition from Exchange 2010 to Exchange 2013, you need a translation tool between Google and Office 365. That translation tool is the BitTitan Google Coexistence tool.

How do I configure the BitTitan Google coexistence tool

The answer is, you don’t. You configure the Google Calendar Interop and Exchange Online by creating an Organization Relationship, both to point to the BitTitan Coexistence service, and you also create a MigrationWiz project in the BitTitan portal, so that you can obtain your authentication token from the BitTitan Support ( See here the coexistence setup guide.

This is how the Google calendar interop should look like:


And to configure the calendar interop:

  1. login to
  2. Go to Apps > G Suite > Calendar > Calendar Interop Management
  3. Enter all the information as per the coexistence setup guide

This is how the Exchange Online Organization Relationship should look like:


And to configure the Organization Relationship:

  1. Download the Coexistence script from the BitTitan setup guide
  2. Add the details to the script as per instructions on the setup guide
  3. Open an Exchange Online PowerShell session
  4. run the script
  5. Verify if the Organization Relationship was properly created by running: Get-OrganizationRelationship |fl

Do I need contacts in each organization for the free/busy to work

No, you don’t need a contact in Google for each user from Exchange Online that you want to query the free/busy, nor you need them in Office 365 for each Google user. You should have contacts in both sides, but to make sure you have a unified Global Address list.

To be clear on this:

  • is a Google mailbox
  • is an Office 365 mailbox
  • You don’t need to create as an Office 365 mail contact
  • You don’t need to create as a Google mail contact

But again.. you should.. having a unified GAL is usually mandatory and for sure highly recommended.

How do users query the free/busy information

As they do for any other internal user. They open their calendar app and enter the email address of the user on the other system or search for his contact created on the GAL if it exists.

To wrap this up, and please stay tuned for more blog post on this subject coming soon, the rich coexistence (mail flow and free busy) experience, when you’re migrating your customer from Google to Office 365, is very important and also very easy to achieve.

If you have any questions please feel free to reach out. I can help you understand it better as well as configure it.

As always I hope this post was helpful.

PS- The BitTitan coexistence tool also works between Google and Exchange 2010 Sp2+ on premises.





Understand and script the Get-MailboxFolderStatistics cmdlet

This blog post is going to give you some insight on how you can script the Get-MailboxFolderStatistics cmdlet, but also how to understand it’s output, as well as how is it important to plan a mailbox migration project.

Why are the mailbox folder statistics important to plan a migration project?

That is indeed the first thing you need to consider: Why do I need those statistics? To better answer that let me start by showing you an output of the command.


What you see above is the output of a mailbox, where I filtered the Folder Path, the number of items in the folder and sub folders, as well as the size of each folder. So let me bullet point why is this important for a migration project planning:

  • It will give you item counts per user and per item type (Mail, calendar, contacts). Those numbers are important, specially if extremely large, to estimate migration timelines when using the Bittitan MigrationWiz mailbox migration.
  • It will show you the size of every folder as well as the entire mailbox size. This is important to identify which folders are larger on a very big mailbox. I’ve seen examples of some of those folder being considered irrelevant for a migration (i.e deleted items, sent items) and with a flexible tool like the Bittitan MigrationWiz you can filter them out.
  • It will show you not only the folders visible to the end user, but also the recoverable deleted items folder. This might be very important in scenarios where you have in place hold active. It will give you the exact estimate of how many items are under in place hold on the recoverable items, that you will eventually need to move to the same folder on the destination mailbox.

So in summary, and giving a quick example, if you’re moving 1000 mailbox from Exchange Online tenantA to tenantB, you should use the Bittitan MigrationWiz tool, that will be not only fast but also flexible on what you can include and exclude in the migration, leveraging the Exchange Web Services API. To do that the insight of what’s in the mailbox is fundamental to plan the entire migration. You can plan the timelines and how long it will take, what type of licensing you will need at the destination tenant and many other important variables for the project.

How can I filter the output per item type?

When running the cmdlet you need to use the “-FolderScope” parameter to filter the output per item type. That parameter allows you to enter many different folder scope types, the most common being:

  • All
  • Calendar
  • Contacts
  • RSSSubscriptions
  • RecoverableItems

See the entire list in the official Technet article of the Get-MailboxFolderStatistics cmdlet.

Some cmdlet examples

See below some examples on how to obtain specific data:

Get total number of items in the mailbox (does not include recoverable deleted items):

Get-MailboxFolderStatistics | Where-Object {$_.foldertype -eq ‘root’} |ft folderpath, itemsinfolderandsubfolders, folderandsubfoldersize


Get total number of contacts in the mailbox:

Get-MailboxFolderStatistics -FolderScope Contacts |ft folderpath, items*, folderandsubfoldersize


Note: the above will work for calendar items if you change the folder scope from “Contacts” to “Calendar”

Get total number of items in the Recoverable deleted items folders:

Get-MailboxFolderStatistics| where {$_.FolderType -eq ‘RecoverableItemsRoot’}|ft folderpath, itemsinfolderandsubfolders, folderandsubfoldersize


And finally… the script that exports all of this to a csv:

Now that we discussed how important it is to get the statistics, and I gave you same examples on how to run some one line commands to get some insight on the mailbox, I will share with you a script that was done by me and my colleague and friend Alberto Nunes.

Below are the details of what the script does:

  • The script will run the statistics against a list of users that needs to be specified on a file called users.csv (see csv format below). The file needs to be on the same folder as the script.
  • The script runs Exchange PowerShell commands, so make sure you’re connected to the Exchange PowerShell (online or on premises)
  • The script will export the results to a file statistics.csv
  • The script will ask you for a source or destination parameter. The statistics for the recoverable deleted items folders will only be included if you select Destination.
  • This script is provided as is and there’s no guarantee that it will work in your environment.

The Users.csv file:


Note: Make sure you name the column A “EmailAddress”

The Script:

Copy the text below (in red) to a notepad. Save it as .ps1 and run it from a PowerShell session connected to Exchange.

#Start Script
[Parameter(Position=0,Mandatory = $true)][ValidateSet(‘Source’,’Destination’,’MigrationWiz’)][String]$Location,
[Parameter(Mandatory = $false)][String]$Folder = “.”,
[Parameter(Mandatory = $false)][String]$UsersCSV = “Users.csv”,
[Parameter(Mandatory = $false)][String]$OutputCSV = “Statistics.csv”
$ErrorActionPreference = “SilentlyContinue”
$SourceFile = $Folder + “\” + $UsersCSV
$OutputFile = $Folder + “\” + $OutputCSV
$mailboxes = Import-Csv -Path “$SourceFile”
$CSV = @()
Foreach ($mailbox in $mailboxes)
Write-Host “Working on $($mailbox.EmailAddress)”

$AllStats = Get-MailboxFolderStatistics $($mailbox.EmailAddress)| Where-Object {$_.foldertype -eq ‘root’}

$ContactStats = Get-MailboxFolderStatistics $($mailbox.EmailAddress) -FolderScope Contacts
$TotalContactsItems = ($ContactStats | select -expand ItemsInFolder |Measure-Object -Sum).Sum

$CalendarStats = Get-MailboxFolderStatistics $($mailbox.EmailAddress) -FolderScope Calendar
$TotalCalendarItems = ($CalendarStats | select -expand ItemsInFolder |Measure-Object -Sum).Sum

$RSSFeeds = Get-MailboxFolderStatistics $($mailbox.EmailAddress) -FolderScope RssSubscriptions -ErrorAction SilentlyContinue
If ($RSSFeeds)
$TotalRSSFeeds = ($RSSFeeds | select -expand ItemsInFolder | Measure-Object -Sum).Sum
$TotalRSSFeeds = 0

# In the source, we don’t need to know the Size of the RecovableItems
If ($Location -eq “Destination”)
$recoverableItems = Get-MailboxFolderStatistics $($mailbox.EmailAddress)| where {$_.FolderType -eq ‘RecoverableItemsRoot’}
[double]$recoverableSize = $recoverableItems.FolderAndSubfolderSize.TrimEnd(” bytes)”).Split(“(“)[1].replace(‘,’,”) |%{“{0:N2}” -f ($_ /1mb)}

$TotalMailItems = $AllStats.ItemsInFolderAndSubfolders – $TotalContactsItems – $TotalCalendarItems – $TotalRSSFeeds

$ISSize = $AllStats.FolderAndSubfolderSize.tostring()
[double]$ISSize =$ISSize.TrimEnd(” bytes)”).Split(“(“)[1].replace(‘,’,”) |%{“{0:N2}” -f ($_ /1mb)}

$Output = New-Object PSObject
$Output | Add-Member -MemberType NoteProperty -Name “User” -Value $mailbox.EmailAddress
$Output | Add-Member -MemberType NoteProperty -Name “Location” -Value $Location
$Output | Add-Member -MemberType NoteProperty -Name “TotalItems” -Value $AllStats.ItemsInFolderAndSubfolders
$Output | Add-Member -MemberType NoteProperty -Name “MailboxSize MB” -Value $ISSize
$Output | Add-Member -MemberType NoteProperty -Name “TotalContactItems” -Value $TotalContactsItems
$Output | Add-Member -MemberType NoteProperty -Name “TotalCalendarItems” -Value $TotalCalendarItems
$Output | Add-Member -MemberType NoteProperty -Name “TotalMailItems” -Value $TotalMailItems
$Output | Add-Member -MemberType NoteProperty -Name “TotalRSSFeeds” -Value $TotalRSSFeeds
If ($Location -eq “Destination”)
$Output | Add-Member -MemberType NoteProperty -Name “RecovableSize in MB” -Value $recoverableSize
$Output | Add-Member -MemberType NoteProperty -Name “RecovableItems” -Value $recoverableItems.ItemsInFolderAndSubfolders
$Output | Add-Member -MemberType NoteProperty -Name “Total Mailbox Size including Recovable” -Value $($ISSize + $recoverableSize)
$Output | Add-Member -MemberType NoteProperty -Name “Total Mailbox Count including Recovable” -Value $($AllStats.ItemsInFolderAndSubfolders + $recoverableItems.ItemsInFolderAndSubfolders)
$CSV += $Output
Write-Host “Completed $($mailbox.EmailAddress)” -ForegroundColor Green

$CSV | export-CSV “$OutputCSV” -NoTypeInformation
#End Script

To run the script you need to specify the location parameter:

.\MailboxFolderStats.ps1 -Location Source

.\MailboxFolderStats.ps1 -Location Destination (includes recoverable deleted items statistics)

As always I hope the above is helpful. Thanks for reading.

Enable-MailUser errors: “Exchange GUID is mandatory on User mailbox” & “Database is mandatory on User mailbox”

Not long ago I had to prepare an Active Directory to be synced with an Office 365 tenant. The company wanted to have Azure Active Directory Sync installed on premises, and sync all the users (and passwords) to Office 365. The plan was to use several of the Office 365 services, with of course Exchange Online included (it always is, right? ).

Because the company was using Azure Active Directory Sync, part of the preparation of the on premises Active Directory was to install an on premises Exchange 2013 Management Server (see here why should you keep at least one Exchange Management Server on premises when you are using AADSync), and to convert all users that will have a mailbox on Office 365 into mail users on premises, so that they can be manageable from the Exchange tools, and have all Exchange attributes. If you have a Hybrid deployment an Exchange mailbox user on Office 365 should be a Remote Mailbox object on premises, but if that is not the case (and for me it wasn’t) a mail user is enough.

Not let’s go straight to the problem I had and that is mentioned on this article title.

When I tried to enable all the users as mail users, I got the following error for almost all of them:

“Exchange GUID is mandatory on User mailbox”..

“Database is mandatory on User mailbox”..


So that got me thinking, and the first thing that came to mind was: What Mailbox? The users I am trying to enable as mail users are not mailboxes.

So I went and checked the users properties on AD, went to the attribute editor and find out that although all the users that I was trying to change were not mailboxes on Exchange, most of them had the msExchHomeServerName attribute populated with the LegacyExchangeDN of the server that was probably hosting their mailbox before it was disabled. Something clearly went wrong on the process of disabling those mailboxes in the past, and I needed to remove those attributes.

When I identified that attribute as the possible cause, the next thing I did was to remove that attribute from a single user, and tried to run the Enable-MailUser Exchange cmdlet only against that user. It worked, that was the attribute causing the issue. By the way I highly recommend that you follow the same approach and don’t go and remove an attribute for hundreds of users without making sure that it is the attribute that is causing you the issue.

One other thing that I need to stress here is that those users from which I removed the msExchHomeServerName attribute were NOT mailboxes on my Exchange on premises. DO NOT remove that attribute from production mailboxes!

Not let me tell you how I automated the process to remove the attribute from all my faulty users.

First I needed to have a CSV file with all the users that had the issue. In my case no user on premises had a mailbox, except my admin user, so all I had to do was take a full list of the users and exclude the admin before using the CSV to delete the attribute. On the Exchange Management Shell I ran:

Get-ADUser –filter * -Properties msExchHomeServerName | where-object {$_.msExchHomeServerName –ne $null} |ft userprincipalname, msExchHomeServerName


And to export the result to CSV:

Get-ADUser –filter * -Properties msExchHomeServerName | where-object {$_.msExchHomeServerName –ne $null} |Select-object Userprincipalname, msExchHomeServerName | Export-CSV C:\Scripts\UsersToChange.csv –NoTypeInformation



And again I can’t stress this enough, if you do have some mailboxes on premises you might want to either filter the CSV you get as an output or put an “-And” on the where-object statement above to exclude the mailboxes using an attribute that the users with problems don’t have (i.e msExchRecipientType)

Not that I had the CSV I needed a script to read from that CSV and delete that attribute on all the users with problems. I found this excellent script on the TechNet Gallery that removes Exchange Attributes using PowerShell. But the script had two problems:

  • It removed more attributes that I wanted/needed to
  • It prompted you to enter the users one by one, and I had hundreds

So I created king of a version 2.0 of the script, but to my own purpose of course, so that the script could read from the CSV and automatically remove the attributes from all the users in it.

See below the part that manners on the script, that you need to copy into a notepad and save as .ps1:


Remove Exchange Attributes


Remove Exchange 2013 Attributes for a Corrupted Active Directory Account

This Script will use a CSV as baseline

Caution : Mailbox Will Go Disconnected and Exchange Attributes will be Removed” -ForeGround “Cyan”

$AllAccounts = Import-Csv -Path C:\Scripts\UsersToChange.csv

foreach ($Account in $AllAccounts) {

$ADaccount = Get-User $Account.Userprincipalname

$FullDistinguishName = “LDAP://” + $ADaccount.distinguishedName

$AccountEntry = New-Object DirectoryServices.DirectoryEntry $FullDistinguishName

$AccountEntry.PutEx(1, “msExchHomeServerName”, $null)


write-host “Changes made to account” $Account.userprincipalname


Make sure you edit the path and the file name of the CSV, and you are ready to run the script.


Once it’s done go to the user’s attribute editor on Active Directory and see if the value of the msExchHomeServer attribute is null.


And re run the Enable-MailUser Exchange cmdlet for all your users again.


Job done! Any questions let me know.

Raise your Exchange Server EWS limits prior to starting your MigrationWiz project

There’s an excellent Microsoft article on TechNet that explains how to configure client-specific message size limits, in Exchange 2013.

There are a lot of good reasons to raise your client limits, as there are also a lot of reasons not to. As long as you’re aware of what your on premises Exchange Server can handle, and you’re not exposing the server to overload or degradation of the service, by raising those limits, than from my perspective, you’re fine doing it.

UPDATE: Michael de Rooij just brought to my attention an excellent script he has, that automates everything described on this post. You can read his article here and download the script here. If for some reason you still want to change it manually, continue reading the steps described below.

On this blog post we are going to change the Exchange Web Services limits. The reason behind it is simple: MigrationWiz leverages the Exchange Web Services to move data to and from your Exchange based systems (on premises or in the cloud), and the default limits on an Exchange 2013 will make the migration of every item over ~35MB fail. The solution to have those items migrated is to increase the EWS limits on your target Exchange Server.

Now let me show you what to do that.

To get the limits raised you need to edit the web.config file on both your Exchange 2013 Client Access and Mailbox Servers. The values you need to edit are:

Serve role Configuration file Keys and default values Size
Client Access %ExchangeInstallPath%FrontEnd\HttpProxy\ews\web.config maxAllowedContentLength=”67108864″ bytes
Mailbox %ExchangeInstallPath%ClientAccess\exchweb\ews\web.config maxAllowedContentLength=”67108864″ bytes
Mailbox %ExchangeInstallPath%ClientAccess\exchweb\ews\web.config 14 instances of maxReceivedMessageSize=”67108864″ bytes

In my case I will raise the limit to 200MB. Go here to convert the 200MB in bytes.

200MB = 209715200 Bytes

Let’s edit the web.config


Above you can see the path on the Client Access Server.


Search for the value to change on the CAS server, and edit it to match the 200MB.

Do the exact same change on the mailbox web.config file, on your mailbox server, or if you have both CAS and Mailbox on the same server, go to the path: %ExchangeInstallPath%ClientAccess\exchweb\ews\web.config

Once the maxAllowedContentLenght change is made on both web.config files, you need to change 14 instances of the maxReceivedMessageSize value, on the Mailbox Server web.config


Go to the Mailbox server web.config file location (also used on the maxAllowedContentLenght change).


Search and replace the 14 instances.

Once the changes are made, save the web.config file and do an IISReset from the command prompt.

Note: In the web.config file on Mailbox servers, there are also two instances of the value maxReceivedMessageSize=”1048576″ forUMLegacyMessageEncoderSoap11Element bindings that you don’t need to modify.

Now your on premises Exchange Server will be able to handle much larger files via EWS.

Script to Bulk create Exchange on premises mailboxes

Building an Exchange lab? Need to create some test users? Well that happens to me a lot, so I decided to build a quick script that basically creates 50 mailboxes on my newly created lab, in less than 5 seconds 🙂

So the script is very simple:

#Run this script from the Exchange Management Shell
#Author: Antonio Vargas
#Declare Variables – Change the Domain and the Database to match your environment
$Number = 1
$domain = “Domain.local”
$Database = “EXCHDB”
#Cycle to create 50 Mailboxes. If you need less than 50 change the “-lt 51”. i.e if you need five change to “-lt 6”
while ($Number -lt 51){
New-Mailbox -UserPrincipalName “User$Number@$domain” -Alias User$Number -Name “User$Number” -firstname “User$Number” -database $database -Password (ConvertTo-SecureString -String P@ssw0rd -AsPlainText -Force)
$Number = $Number + 1
write-host “All Test Mailboxes created”

So just copy and paste the above to a notepad, save the file as .ps1, and run it from an Exchange Management Shell of one of your Exchange on premises servers.

The password of each user will be set to”P@ssword” but that of course is also something on can change on the script.


And you can say goodbye to having to manually create users each time you need to spin up an Exchange lab! 🙂

As always, any questions let me know.

Yet another Exchange legacy Public Folders replication issue: Old content not replicating to new PF databases

If you´re reading this post, chances are you´re stuck with a public folder replication issue. I´ve seen all sorts of issues with the replication of legacy public folders, but none without solution, so hopefully your solution is here 🙂

My scenario:

  • Exchange 2010 Service Pack 2 in 3 servers (2 existing and 1 new)
  • CAS/HT/Mailbox roles on all servers
  • Each server has a public folder mailbox
  • One server in Asia, one in America and one in the EMEA region

My problem:

The new public folder database was not getting all the existing public folder replicas/content.

Instead of going direct to my issue, let me guide you through all the steps you should take to make sure you understand why your replicas are not being pushed to the new PF database:

Have you added all the replicas (or the ones you need) to your new public folder database?

AddReplicaToPFRecursive.ps1 -Server <ExistingServer> -ServerToAdd <NewServer> -TopPublicFolder “\”

AddReplicaToPFRecursive.ps1 -Server <ExistingServer> -ServerToAdd <NewServer> -TopPublicFolder “\NON_IPM_SUBTREE”

The script above is on the Exchange scripts folder, and can be ran from an Exchange Management Shell. Look here for more details on the script.

You can check which replicas a public folder has, by running:

GetPublicFolder -Identity ‘\’ –Recurse | fl Name, Replicas

Get-PublicFolder -Server <NewServer> -Recurse

Is the above done and your public folder database is still not up to date?

If you do have the replicas pushed to the new server, and the content is still not being replicated, then please also check if the mail flow between the source and destination server is working.

In my case of course it was working, because as stated on the title of this post, only the old content of the public folders was not being replicated. New content was fine, which means that issues like mail flow or invalid replicas were ruled out.

An example:

UserA was connecting to a database on the new server that was using the new public folder database. Via OWA UserA opened the Public Folders, and created a new item. The item was replicated to all the Public Folder databases on all servers. UserA can only see a very limited number of items on the Public folders, all recent and created after the creation of the new PF Database.

So lets take a closer look at the statistics of a specific folder:


The Public Folder “US” had zero items in the new server and 1087 on the old one. An item created now would replicate to both the new and the old server, but nothing was happening to old content.

Now before I continue, it´s mandatory for me to recommend you read an excellent Public Folder Troubleshooting article from the Ehlo Blog.

The next step is to raise the event log level on both the new and the old server. The logs you need to set to expert are under the “MSExchangeIS > 9001 Public” and are named “Replication Incoming Messages” and “Replication Outgoing Messages”.


Now let’s force an update on a public folder by running on the new server Exchange Management Shell:

Update-PublicFolder -identity “\US” -server <OldServer>

And on the new server event viewer you can see the 0x20 Status Request event (see the troubleshooting guide provided above for more info on event codes).


On the old server you can see the status request reply:


But what you never see is an event like the one below, with status 0x4 that indicates that content is being replicated.


So what is the solution? Update all the content using the ExFolders tool.

Click here to download it, and for full instructions on how to run it.

Once you have the Exfolders opened and connected to the old server, select the folders you want to update (in my case I selected the route because I wanted to update all) and click on “Modify All Items”.


IMPORTANT NOTE: This will cause a replication storm, which means that all public folders on all databases will be updated and replicated. If you have a large public folder infrastructure you might want to consider doing this procedure during off work hours.

You will then see the folders being updated.


And once that is done, wait for the replication to take place and run the public folder statistics cmdlet again.


All up to date!

Hope that the above was helpful..

Exchange Active Sync on-boarding to Office 365 – The seamless experience is finally here

For those who are thinking on moving to Office 365, and in what that might mean from a user experience perspective, the release of the Exchange 2013 Cumulative Update 8 (CU8) and Exchange 2010 SP3 Rollup Update 9 (RU9) brings a long expected feature – seamless experience on the on-boarding process of ActiveSync users, to Office 365.

You can read the full details on the article Exchange ActiveSync on-boarding to Office 365, published on the Exchange Team Ehlo Blog.

Instead of duplicating all the information that you can read on the official blog article, i will just give you my thoughts on how this works and highlight the key points.

When a user is moved to Office 365, under a Hybrid deployment, that mailbox on premises is converted to a remote mailbox, and a “RemoteRoutingAddress” of the type is configured for the remote mailbox.

That remote routing address should be configured as a domain name on an existing Organization Relationship “On premises to O365”.

Before Exchange 2013 CU8 and Exchange 2010 SP3 RU9, the experience was only seamless for users via Outlook or OWA. When those users, moved to Office 365, tried to connect to the Client Access server on premises, a mailbox wasn’t found.. so what happened next?

“The Client Access server triggers a query to find the “TargetOWAURL” property present on the organization relationship object for the Office 365 tenant. The “RemoteRoutingAddress” property, present on the remote mailbox, is used to find the correct organization relationship.”

That “TargetOWAURL” is then used by Outlook (automatically reconfigured the profile) or OWA (presents the new URL to the user) to redirect the user to the Office 365 mailbox.

After Exchange 2013 CU8 and Exchange 2010 SP3 RU9, that process will also work when the user is connecting via Exchange ActiveSync, making the experience seamless as well for all the ActiveSync users.

Of course for all of you that, like me, spend countless hours explaining to customers that recreating the exchange partnership on all of their user’s phones, was the only option, and helping on the creation of user guides, this new feature is excellent news.

From my personal perspective it makes perfect sense that, with the Client Access services already using the Organization Relationships and the TargetOWAURL, to redirect Outlook and OWA clients, the capability to redirect ActiveSync clients is now also an available feature.

Of course there are some limitations, such as the device EAS version not supporting HTTP 451 redirects or cross-forest migrations.

I highly recommend that you read the official article, for all the details on this new feature.

Well done for the Microsoft Exchange Product Group! 🙂

Public Folder migration request error creating the Public Folder Hierarchy – “Property Expression [property name] isn’t valid”

To migrate your legacy public folders to Exchange 2013, you should follow all the steps described on the official Microsoft article.

Step 2 of the article mentioned above, helps you prevent errors related to the public folder name, such as having a “\”. But this blog post is related with something which is not covered by the article, and that can make your public folder migration request throw an error: Invalid alias on mail enabled public folders.

So as described on step 5 of the article, you start your migration request by running the following cmdlet:



New-PublicFolderMigrationRequest -SourceDatabase (Get-PublicFolderDatabase -Server <Source server name>) -CSVData (Get-Content <Folder to mailbox map path> -Encoding Byte) -BadItemLimit 200 -acceptlargedataloss -largeitemlimit 200

Note: On the above cmdlet i used both the baditemlimit and largeitemlimit set to 200, because i knew that my public folders had a significant number of both bad and large items. If that is not your case keep the bad and the large item limits to a minimum if at all specified.

Once the public folder migration starts you can run the following cmdlet to see the progress. If you have invalid alias on the mail enabled public folders, the migration request will fail at 10%, when creating the Public Folder Hierarchy:




To get the details of the error you need to run the same cmdlet, but with the “|fl” at the end, as shown below:



Get-PublicFolderMigrationRequest |Get-PublicFolderMigrationRequestStatistics |fl

On the details you can see the following:


On the screenshot above you can see that the mail enabled public folder “Accountancy Properties” has an invalid alias, and that is because you cannot have spaces (and other characters as shown above) on the alias. So the next step would be to fix all mail enabled public folders with invalid aliases.

Go to your Exchange Management Shell and run a cmdlet that will list all the mail enabled public folders with spaces. Of course some other mail enabled public folders can have other problems, but in my case it was only the spaces. If you have other problems besides spaces you can adapt the “where-object” filtering from the cmdlet below, to those characters. Also to get an output of all the mail enabled public folders with issues, you can run the following cmdled and see which public folders throw a warning:


All the mail enabled public folders will throw a warning on the output, but of course we need to have a list of only the ones with problems to resolve the issue quicker. So to have a list with all the ones with spaces, and export it into a csv file, run the following cmdlet:






Get-MailPublicFolder | Where-Object {$_.Alias -like "* *"} | Select-Object alias, identity |export-csv [CSV file path and name]

Note: On the cmdlet above, if you’re problem is not limited to spaces on the alias, you can change the where-object filtering to try and find other invalid characters.

Once that is done you will get a csv file with all the mail enabled public folders with invalid aliases, as shown below:




Having that information you can now fix all the mail enabled public folders. You have two ways of doing it:

Option 1:

You can open your Exchange Management Console, go to tools and then open the Public folder Management Console. Expand the Public Folder tree and go to the properties of each public folder with problems. On the “Exchange General” tab change the alias and apply, as shown below.






Option 2:

You can use the Exchange Management Shell, and run the following cmdlet:






Get-MailPublicFolder [Public Folder Name] |Set-MailPublicFolder -Alias [PublicFolderAlias]

Once you set the valid alias you problem is solved for that specific public folder. You might be thinking “how can i automate this for the dozens or hundreds of public folders i have with issues?”. Well the answer is you should use that csv file you exported with all the public folders, insert a column with valid aliases, build a script that reads from the csv file and run it from the Exchange Management Shell to have all your folders fixed in one go. In my case i had a low number of folders with issues, so i haven’t built the script. I am planning to build 2 scripts, one to export public folders with issues and another one to use that exported file and fix those issues, but at the moment i don’t have it. Feel free to ping me an e-mail or comment if you’re interested on the script and i can find some time to build it. It should be a fairly simple script. Or feel free to have a go on doing that.

But back to the issue. Once you have all your mail public folders with valid aliases, i recommend that you remove the current public folder migration request and create a new one. To do that run the sequence of cmdlets shown below:







To see the current failed request:

To delete the current failed request:
Get-PublicFolderMigrationRequest |Remove-PublicFolderMigrationRequest
To create a new request:
New-PublicFolderMigrationRequest -SourceDatabase (Get-PublicFolderDatabase -Server <Source server name>) -CSVData (Get-Content <Folder to mailbox map path> -Encoding Byte) -BadItemLimit 200 -acceptlargedataloss -largeitemlimit 200

Finally after the new request is created, you can see that now the migration is ongoing and went past the Public Folder Hierarchy creation without issues.




Problem solved and happy migration! 🙂







Public Folders migration to 2013 gets “StalledDueToMailboxLock” Status

Are you trying to migrate your public folders from legacy Exchange versions to Exchange 2013? And are you getting stuck on a “StalledDueToMailboxLock” error when you try to resume the migration? Well then continue reading. I will try to keep this post short and simple, just like the solution to your problem.

First things first.. the migration process.. To successfully complete the migration, and if you don’t have experience on doing it, you should follow all the steps from the link below:

So in summary, you download the scripts, estimate the number of public folder mailboxes you will have, name and create those mailboxes and start the migration process, that will suspend at 95% with all the data migrated except the delta.

Once that is done you then lock the public folders on the legacy version (step 6 on the link above), by running the following cmdlet:

Set-OrganizationConfig -PublicFoldersLockedForMigration:$true

And what is the purpose of this cmdlet? Simple.. to block the access from the users to the legacy public folders, so that you can migrate the delta, unlock the access on 2013 (Step 8), and have all users using the new modern public folders.

So what can go wrong and when can you see the “StalledDueToMailboxLock” Status?

After you run the Set-OrganizationConfig -PublicFoldersLockedForMigration:$true cmdlet, the changes need to apply on the legacy public folders, before you resume your migration by running the Resume-PublicFolderMigrationRequest -Identity \PublicFolderMigration cmdlet.

If the changes are not applied yet, than your public folder migration request will resume and a minute or two later it will get into a “StalledDueToMailboxLock” status.

When you get into that status there are two things you need to do:

First try and access the public folders, from an Outlook client. Can you still access them? Well that means they are not locked and the changes didn’t apply yet.

So you can either wait for the changes to apply, and keep checking the access to the public folders until it’s blocked, or alternatively you can force the changes to apply, by restarting the Information Store service on the legacy server(s), where the public folder database being migrated is. Once you restart the Information Store service, retry accessing the public folders from an Outlook client. The access should now be blocked. Then you can suspend and resume your public folder migration request, to get it going quicker, by running:

Suspend-PublicFolderMigrationRequest -Identity \PublicFolderMigration
Resume-PublicFolderMigrationRequest -Identity \PublicFolderMigration

The request should now complete without issues, and you can continue following the steps on the link i provided earlier on this post, to get your public folders running on 2013.

Any questions about the entire process let me know.