Understanding the admin authentication options when using the EWS API in your migration project

One of the major concerns of the consultant or the project manager, on a migration project, is how long will it take to migrate the mailboxes, and what timelines can they define as reasonable for the migration (or the migration batch) to be finished.

Having that in mind, the conversation around it needs to focus on two major factors:

  • What authentication method should we use
  • How can we minimize (or avoid) throttling

So let’s start by talking about the authentication method.

What are the available authentication methods?

Bittitan MigrationWiz, which of course leverages the Exchange Web Services (EWS) as the API to migrate to and from Exchange 2010+, allows you to use two type of admin authentication methods:

  • Delegation
  • Impersonation

Note: MigrationWiz also allows non admin authentication methods, which we will not discuss on this blog post.

What is delegation and how do I configure it?

Delegation is the authentication method in which the entire migration will be done from the calling account (admin account), that needs to have full access to all of the mailboxes that are being migrated. The requirements for delegation are:

  • admin account needs to be mailbox enabled
  • full access is required to all of the mailboxes being migrated (explicit permissions)
  • a throttling policy should be created and associated with the admin account

In the Bittitan community website you will be able to find instructions on how to configure delegation on the source and target Exchange systems. You can also find there how to create the throttling policy.

By default the MigrationWiz project will try and use delegation, so there’s no other change needed.

What is impersonation and how do I configure it?

Impersonation is the authentication method in which the migration will be done on behalf of the user account, that is being impersonated by the calling account (admin account). For this to happen the admin account needs to be granted rights to impersonate the user accounts being migrated. the requirements for impersonation are:

  • the admin account does not need a mailbox
  • impersonation rights need to be granted to the admin account, over all of the users being migrated
  • a throttling policy is not required but highly recommended

In the Bittitan community website, you will also find instructions on how to configure impersonation on the source and target Exchange systems. The instructions to create the throttling policy are the same you can find on the section above.

The default behavior from MigrationWiz is not to use impersonation, so please make sure you follow the MigrationWiz steps of the article above, to configure impersonation at the project level.

Should I use Delegation or Impersonation?

Now that I described what is Delegation and what is Impersonation, let’s discuss which one should you use for each scenario.

In my professional opinion, that I will detail below and explain why, this is what you should do:

  • If the Exchange system is Exchange Online (Office 365) use Impersonation
  • If the Exchange system is Hosted Exchange (online but not in Office 365) use Delegation
  • If the Exchange system is on premises use Delegation

So now let’s break it down per system.

Exchange Online (Office 365)

The main reason that you should use Impersonation when authenticating against Exchange Online is simple: You cannot create a throttling policy in Office 365 and impersonation is less subject to throttling than delegation. 

I don’t think I need to explain why you can’t create a throttling policy in Office 365, but why is impersonation less subject to throttling? Well the explanation is logic: The subscriptions will be charged against the throttling budget of the target mailbox and not the calling account (admin account), which in other words means that the admin account is doing the migration impersonating each target account and the throttling is being charged to the target accounts, making the limits much more flexible and the migration faster.

Another good thing about Exchange Online is that when you set the impersonation rights, you are of course setting them within the boundaries of your tenant, which is not necessarily true for hosted Exchange systems, as you’ll see below.

Hosted Exchange (not in Office 365)

Now when we look at a hosted Exchange and what admin authentication methods we can have, the main thing you need to keep in mind is that, we will have what the Hoster is willing to configure. And what might that be? Short answer will be Delegation.

Don’t get me wrong, if you manage to get a Hoster (or if you are part of a Hoster Exchange management team and you’re also driving the migration) to either create a throttling policy or configure impersonation associated with a management scope, then what I recommend is:

  1. If you can create a throttling policy then use Delegation and associate that throttling policy to the admin account
  2. If you can’t create a throttling policy but you can enable impersonation with a scope (explanation below) than enable and use Impersonation
  3. If none of the above is possible, then use Delegation

Note: when you set impersonation, if you don’t use a management scope, that will allow the admin account to impersonate any account on that hosted Exchange. That might (and should) be considered a security breach by the Hoster and therefore not possible to configure. Although possible, many Hosters might not be willing to configure impersonation with a management scope, or configure impersonation at all.

On Premises Exchange

Finally when the system is on premises Exchange, you will be able to do all necessary tasks, so why use delegation?

To be able to reach maximum speeds you will still have to create a throttling policy (if you can), so between impersonating and using delegation I do think that delegation and a throttling policy is the best way to go.

Remember when I said “Impersonation is the authentication method in which the migration will be done on behalf of the user account, that is being impersonated by the calling account (admin account).”? Well that’s not 100% true in all cases. Depending on your Exchange version, the subscription might be charged to the calling account, which in essence makes impersonation as effective as delegation in terms of throttling. See the table below:

Exchange version EWSMaxSubscriptions throttling budget accounting
Exchange Online Charged against the target mailbox.
Exchange 2013 Charged against the target mailbox.
Exchange 2010 SP3 Charged against the target mailbox.
Exchange 2010 SP2 Charged against the calling account. Starting with Exchange 2010 SP2 RU4, the budget is charged against the target mailbox.
Exchange 2010 SP1 Charged against the calling account.
Exchange 2010 Charged against the calling account.

Source: EWS throttling in Exchange

From the above table you will see that if you have an Exchange system older than Exchange 2010 SP2 RU4, impersonation and delegation will have the same impact from the throttling perspective. We know that Exchange Online does have a version newer than the one just mentioned, but that is not necessarily true for Hosted Exchange or Exchange On Premises, so have that in mind when planning the authentication methods.

So let me outline the reasons that should make you choose delegation when migrating from an on premises Exchange:

  • the speed of the migration will be highly dependent on the throttling policy, that you can and should create, as well as monitor the Exchange performance during the migration
  • Implementing delegation is easier, specially in cases where you want the admin account to just have rights over a subset of the mailboxes. It’s much easier to just give full access to some mailboxes when compared to give impersonation rights to just some users
  • the way throttling reacts when using impersonation and delegation is different. In my opinion when using impersonation you’re more likely face ErrorServerBusy errors (if you go over the limit of concurrent migrations) and that causes normally more migrations to fail. When using delegation the failures are more likely to happen on the accounts that caused the admin account to over the maximum subscriptions allowed

I know that the explanation above might be a little confusing, specially the last bullet point, but I do highly recommend that you read the EWS throttling in Exchange article, and if you have another idea on what method to use feel free to share it.

I do think that impersonation makes sense only on those scenarios where you cannot fully implement proper delegation, with throttling policies and processes defined to monitor the Exchange server resources during the migration window.

Some useful articles around this subject

The importance of EWS impersonation while using an application account: you will can read the author outline how impersonation is better from an application perspective, and delegation is more oriented towards user access. I also mentions that user access can be controlled and revoked by the end user, which can be true. But on a migration project MigrationWiz will use user access to get into the mailbox and move the data to a destination mailbox, which is exactly what delegation provides you. He also outlines how less complex and global the impersonation setting can be, which is true, but on a project when you only need to migrate a subset of the mailboxes, and where you don’t want to give global access, impersonation will be significantly more complex. In essence this article is a good read that outlines the positives of impersonation and why it’s a good option for application level access and not user level access.

Impersonation and EWS in Exchange: This is an excellent article and a must read, that details how application level impersonation works in Exchange.

So what is the bottom line? At the end of the day it’s still your decision of whether to use delegation or impersonation. I’d say that for some scenarios like Office 365, the decision is a no-brainer (impersonation of course), and in some other scenarios it will depend on what can you configure and what is the simpler and more effective configuration.

Like I stated above I am always more inclined to decide for delegation against Exchange on premises and hosted Exchange, and impersonation against Office 365.

As always I hope this article is helpful, and feel free to share your thoughts.

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 user@domain.com | Where-Object {$_.foldertype -eq ‘root’} |ft folderpath, itemsinfolderandsubfolders, folderandsubfoldersize


Get total number of contacts in the mailbox:

Get-MailboxFolderStatistics user@domain.com -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 user@domain.com| 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.