Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Before migrating mailboxes from Exchange On-Premises to Exchange Online (EXO), you can run a Mailbox Analysis Request to prescan the source mailbox content. The analysis produces a report of folder paths with item counts and sizes, which helps you:
- Identify oversized mailboxes before migration starts.
- Decide how to distribute content across primary, Main Archive, and Auxiliary Archive mailboxes in EXO.
- Generate an XML mapping file for large mailbox migration
What you need to know before you begin
- It's available through Exchange Online PowerShell only. The Exchange Admin Center (EAC) doesn't support this feature yet.
- Hybrid deployment needs to be configured between On-Premises and Exchange Online organizations. Also, the migration endpoint needs to be setup and working. See Move mailboxes between on-premises and Exchange Online organizations in hybrid deployments.
- The analysis produces two outputs:
- Analysis result: folder paths with item counts and sizes. Folders with more than 1 million items or more than 100 GB are flagged with a warning.
- Mapping result: a ready-to-use XML content mapping file that distributes source data across EXO mailboxes within per-mailbox quota limits.
Step 1: Verify migration endpoint
You can verify the availability of the migration endpoint using the Test-MigrationServerAvailability cmdlet. For more information on this cmdlet, see Test-MigrationServerAvailability.
Step 2: Create a mailbox analysis batch
The source endpoint and CSV format for a mailbox analysis batch are the same as for a standard hybrid onboarding migration batch. To learn more about migration endpoints, see Get-MigrationEndpoint. For CSV file format details, see CSV files for mailbox migration.
Set these variables before running the command:
$endpointID = "" # Identity of the hybrid migration endpoint
$batchName = "" # Unique, descriptive name for this analysis batch
$csvPath = "" # Path to the CSV file listing EXO users to analyze
Create the analysis batch using New-MigrationBatch with the -Analyze parameter:
New-MigrationBatch -Analyze -SourceEndpoint $endpointID -AutoStart -Name $batchName `
-CsvData ([System.IO.File]::ReadAllBytes($csvPath))
Example:
PS C:\> $endpointID = "hybrid_endpoint"
PS C:\> $batchName = "OnPrem_Analysis_Batch1"
PS C:\> $csvPath = "C:\temp\OnPrem_analyze.csv"
PS C:\> New-MigrationBatch -Analyze -SourceEndpoint $endpointID -AutoStart -Name $batchName `
-CsvData ([System.IO.File]::ReadAllBytes($csvPath))
Identity Status Type TotalCount
-------- ------ ---- ----------
OnPrem_Analysis_Batch1 Syncing OnPremAnalysis 1
Step 3: Check analysis batch and user status
To check the status of the batch:
Get-MigrationBatch $batchName
To check the estimated total item count and size for each user in the batch:
Get-MigrationUser -BatchId $batchName | Format-Table Identity, Status, Estimate*
| Column | Description |
|---|---|
Identity |
Migration user in the batch |
Status |
Syncing while analysis is running; Completed when done |
EstimatedTotalCount |
Estimated total item count in the source mailbox |
EstimatedTotalSize |
Estimated total size in bytes |
EstimatedArchiveCount |
Estimated archive item count (if source has an archive) |
EstimatedArchiveSize |
Estimated archive size in bytes (if source has an archive) |
Example:
PS C:\> Get-MigrationUser -BatchId $batchName | Format-Table Identity, Status, Estimate*
Identity Status EstimatedTotalCount EstimatedTotalSize EstimatedArchiveCount EstimatedArchiveSize
-------- ------ ------------------- ------------------ --------------------- --------------------
OnPremMailbox@contoso.com Completed 1335 135824984515
To convert the size to GB:
PS C:\> 135824984515 / 1GB
126.496874275617
Step 4: View the analysis results
Once Get-MigrationUser shows Status = Completed, use Get-MailboxAnalysisRequestStatistics with IncludeAnalysisResult to view the detailed results.
Set the user variable:
$user = "" # Identity of the migration user to analyze
If Get-MailboxAnalysisRequestStatistics $user fails, it might be due to a soft-deleted user, and the workaround is to use the following cmdlets.
Get-MailboxLocation $user | Format-List ID # replace the below MailboxLocationIdParameter value with ID which is OrgGuid\MailboxGuid format
Get-MailboxAnalysisRequest $user | Format-List RequestGuid # replace the below RequestGuid value with GUID
Get-MailboxAnalysisRequestStatistics "IND#MapiMailbox#MailboxLocationIdParameter#RequestGuid"
Aggregated result (totals only)
$stats = Get-MailboxAnalysisRequestStatistics $user -IncludeAnalysisResult
$stats.MailboxAnalysisResult.AnalysisResultDataRows | Format-Table -AutoSize `
SourceMailbox, FolderIsSelected, FolderPath, StartTime, ItemCount, ItemSize
Example output 1
User only has primary mailbox
SourceMailbox FolderIsSelected FolderPath StartTime ItemCount ItemSize
------------- ---------------- ---------- --------- --------- --------
Total 39 17.95 MB (18,818,259 bytes)
Example output 2
User has both primary mailbox and archive mailbox
SourceMailbox FolderIsSelected FolderPath StartTime ItemCount ItemSize
------------- ---------------- ---------- --------- --------- --------
MainArchive Total 6088 128.7 MB (134,960,198 bytes)
Total 1858 14.91 MB (15,630,350 bytes)
| Column | Description |
|---|---|
SourceMailbox |
Which mailbox (MainArchive or Primary) the data is in. Empty means primary mailbox |
FolderIsSelected |
No meaning in the aggregated view |
StartTime |
Items after this time are selected for analysis; empty means all the items are selected |
FolderPath |
"Total" is to present the whole mailbox in the aggregated view |
As shown in the 1st example, when user has only primary mailbox in Exchange On-Premise, the last row “Total” shows the total size and count of the selected items in primary mailbox. As shown in the 2nd example, when user has primary and archive mailboxes, the last two rows “Total” show the statistics of both mailboxes, respectively.
Important
It’s highly recommended to run Get-MailboxStatistics on Exchange On-Premises PowerShell and compare the size with the analysis result to ensure the analysis job works as expected. See Get-MailboxStatistics.
Run Get-MailboxStatistics, compare its sum of TotalItemSize and TotalDeletedItemSize with the analysis result’s Primary total ItemSize.
Run Get-MailboxStatistics -Archive, compare its sum of TotalItemSize and TotalDeletedItemSize with the analysis result’s MainArchive total ItemSize.
Per-folder result
Add -IncludeFolderDetails to break down the results by folder or label:
$stats = Get-MailboxAnalysisRequestStatistics $user -IncludeAnalysisResult -IncludeFolderDetails
$stats.MailboxAnalysisResult.AnalysisResultDataRows | Format-Table -AutoSize `
SourceMailbox, FolderIsSelected, FolderPath, StartTime, ItemCount, ItemSize
| Column | Description |
|---|---|
SourceMailbox |
Which mailbox (MainArchive or Primary) the data is in. Empty means primary mailbox |
FolderIsSelected |
Whether the folder is included in the analysis (Yes or No) |
StartTime |
The earliest month from which items are counted (month-granular) |
FolderPath |
The folder path. Well-known folders such as Inbox, Sent Items, and Deleted Items appear with a # prefix (for example, #Inbox#, #SentItems#). The last one row or two rows “Total” show the aggregated statistics of mailboxes. |
Important
It’s highly recommended to run Get-MailboxFolderStatistics on Exchange On-Premises PowerShell and compare the size with the analysis per-folder result. See Get-MailboxFolderStatistics.
Get-MailboxFolderStatistics $user | Format-Table FolderPath,ItemsInFolder
Get-MailboxFolderStatistics $user -Archive | Format-Table FolderPath,ItemsInFolder
Filter by time window
Use -ItemsStartTime and/or -ItemsEndTime to analyze items within a specific time range. Both parameters accept dates in "yyyy/MM/dd" format and are treated with month granularity. For example, -ItemsStartTime "2025/03/01" and -ItemsStartTime "2025/03/15" both select all items from March 2025.
| Parameter | Description |
|---|---|
-ItemsStartTime |
Include only items received on or after this month. Can be used alone or together with -ItemsEndTime. Supported with both -IncludeAnalysisResult and -IncludeMappingResult. |
-ItemsEndTime |
Include only items received before this month (exclusive). Must be used together with -ItemsStartTime. Supported with -IncludeAnalysisResult only. |
Example: items from a specific start date onward (-ItemsStartTime only):
# All items from December 2024 onward
PS C:\> $stats = Get-MailboxAnalysisRequestStatistics $user -IncludeAnalysisResult `
-IncludeFolderDetails -ItemsStartTime "2024/12/01"
PS C:\> $stats.MailboxAnalysisResult.AnalysisResultDataRows | Format-Table -AutoSize `
FolderIsSelected, FolderPath, StartTime, ItemCount, ItemSize
FolderIsSelected FolderPath StartTime ItemCount ItemSize
---------------- ---------- --------- --------- --------
Yes #SentItems# 2024-12 4 52.68 MB (55,243,759 bytes)
Yes MyFolder/Foo 2024-12 500 45.9 GB (49,285,052,925 bytes)
Yes #Inbox# 2024-12 49 4.595 GB (4,934,076,159 bytes)
...
Total 1335 126.5 GB (135,824,984,515 bytes)
Example: items within a specific time range (both parameters):
# Items from August 2022 through January 2023 (i.e., before February 2023)
PS C:\> $stats_select = Get-MailboxAnalysisRequestStatistics <exo user> -IncludeAnalysisResult `
-ItemsStartTime "2022/08/01" -ItemsEndTime "2023/02/01"
PS C:\> $stats_select.MailboxAnalysisResult.AnalysisResultDataRows | Format-Table -AutoSize
Note
-ItemsStartTime and -ItemsEndTime must be in different months to produce meaningful results, since the analysis is month-granular. -ItemsEndTime is exclusive, so the range is [ItemsStartTime, ItemsEndTime).
(Optional) Export analysis results to CSV
To save the per-folder analysis output to a CSV file for offline review:
$stats = Get-MailboxAnalysisRequestStatistics $user -IncludeAnalysisResult -IncludeFolderDetails
$csvFilePath = "" # Output path for the CSV file
$stats.MailboxAnalysisResult.AnalysisResultDataRows | Export-Csv $csvFilePath -NoTypeInformation
The CSV includes these columns: SourceMailbox, FolderIsSelected, FolderPath, StartTime, ItemCount, ItemSize, Warning.
Step 5: Generate the mapping XML file
For large mailbox migrations, you need an XML mapping file that tells the system how to distribute content across EXO mailboxes. You can download a sample mapping file and edit it manually, or generate one automatically from the analysis result using Get-MailboxAnalysisRequestStatistics -IncludeMappingResult.
Using IncludeMappingResult ensures:
- Total size mapped to a target mailbox is less than 80 GB.
- Item count mapped to a regular folder in a target mailbox is less than 900,000.
- Item count mapped to a Recoverable Items folder is less than 2.8 million.
The cmdlet supports two methods for generating mapping. Which method you choose should be based on how you want to control the content distribution:
| Method | When to use |
|---|---|
ItemsStartTime |
You want to control which data goes to the EXO primary mailbox by specifying a cutoff date. |
Auto |
You want the system to automatically select the cutoff date to keep EXO primary within quota limits. |
Note
-ItemsEndTime isn't supported with -IncludeMappingResult.
Example 1: Map by cutoff date (-ItemsStartTime)
Use -ItemsStartTime to specify a cutoff date. Data on or after this date from source primary mailbox is mapped to the EXO primary mailbox. Data before this date from source primary mailbox is mapped to EXO Main Archive and Auxiliary Archive mailboxes. If user has archive mailbox on Exchange On-Premises, all contents will be mapped to EXO Main Archive and Auxiliary Archive mailboxes.
Ensure the estimated size of data on or after the cutoff date doesn't exceed your EXO primary mailbox quota before choosing a cutoff date.
To map all content in the Exchange On-Premises primary mailbox to the EXO primary mailbox, use 0001/01/01 as the ItemsStartTime value.
$stats_select = Get-MailboxAnalysisRequestStatistics <exo user> -IncludeMappingResult -ItemsStartTime "2022/08/01"
$ipgeo = New-Object System.Xml.XmlDocument
$ipgeo = [xml]$stats_select.MappingResult
$ipgeo.Save("mapping_output.xml")
Example XML output 1
User has primary mailbox on Exchange On-Premises.
<User EmailAddress="foo@contoso.com">
<Mapping ContentFilter="Received -lt '2021-01-01'" Target="MainArchive" />
<Mapping ContentFilter="Received -ge '2021-01-01' -and Received -lt '2022-08-01'" Target="AuxArchive0" />
<Mapping ContentFilter="Received -ge '2022-08-01'" Target="Primary" />
</User>
In this example:
- Source primary items before January 1, 2021 → EXO Main Archive
- Source primary items from January 1, 2021 to July 31, 2022 → EXO Auxiliary Archive
- Source primary items from August 1, 2022 onward → EXO primary mailbox
Example XML output 2
<User EmailAddress="foo@contoso.com">
<Mapping ContentFilter="" Target="MainArchive" SourceIsArchive="true" />
<Mapping ContentFilter="Received -lt '2022-08-01'" Target="AuxArchive0" />
<Mapping ContentFilter="Received -ge '2022-08-01'" Target="Primary" />
</User>
In this example:
- Source archive all items → EXO Main Archive
- Source primary items before August 1, 2022 → EXO Auxiliary Archive
- Source primary items from August 1, 2022 onward → EXO primary mailbox
Example 2: Automated mapping (-Auto)
Use -Auto to let the system automatically select a cutoff date that keeps the data mapped to the EXO primary mailbox within quota limits. Use this option when you don't want to manually determine the cutoff date.
$stats_select = Get-MailboxAnalysisRequestStatistics <exo user> -IncludeMappingResult -Auto
$ipgeo = [xml]$stats_select.MappingResult
$ipgeo.Save("mapping_output.xml")
Note
-Auto can't be combined with -ItemsStartTime or -IncludeFolderDetails.
Note
User EmailAddress in the output XML might be different from the one in the CSV file which is used when creating the analysis batch. Change the value to the one in the CSV file.
Limitations
Important
Mapping generation can fail with the error "The folder XXX with size YYY cannot be mapped automatically." This usually happens because a single month contains more data than the target mailbox quota allows. The analysis tool is month-granular, so it can't split a single month into a smaller time range. In that case, the administrator must create the XML mapping file manually and carefully.
Additionally, two mappings that share the same start month, the same end month, and different target archive mailboxes aren't supported.
Unsupported mapping example 1
<Mapping ContentFilter="Received -ge '2021-01-01' -and Received -lt '2022-01-15'" Target="AuxArchive0" />
<Mapping ContentFilter="Received -ge '2021-01-15' -and Received -lt '2022-01-31'" Target="AuxArchive1" />
Unsupported mapping example 2
<Mapping ContentFilter="Received -ge '2021-01-01' -and Received -lt '2022-01-15'" Target="AuxArchive0" />
<Mapping ContentFilter="Received -ge '2021-01-15' -and Received -lt '2022-01-31'" Target="AuxArchive1" SourceIsArchive="true"/>
If user has archive mailbox on Exchange On-Premises, mapping any item from source Primary to target MainArchive is not supported.
Unsupported mapping example 3
<Mapping ContentFilter="" Target="MainArchive" SourceIsArchive="true" />
<Mapping ContentFilter="Received -lt '2022-08-01'" Target="MainArchive" />
<Mapping ContentFilter="Received -ge '2022-08-01'" Target="Primary" />
Use the mapping XML in a migration batch
The XML output from -IncludeMappingResult contains a single <User> element. To use it in a large mailbox migration batch, wrap it in a <Users> root element:
<?xml version="1.0" encoding="utf-8" ?>
<Users>
<User EmailAddress="foo@contoso.com">
<Mapping ContentFilter="Received -lt '2021-01-01'" Target="MainArchive" />
<Mapping ContentFilter="Received -ge '2021-01-01' -and Received -lt '2022-08-01'" Target="AuxArchive0" />
<Mapping ContentFilter="Received -ge '2022-08-01'" Target="Primary" />
</User>
...
</Users>
This file can be used in large mailbox onboarding from Exchange On-Premises.