Last active
March 11, 2024 10:51
-
-
Save shuuryou/5ccede3a303cb53b34037e0359b05973 to your computer and use it in GitHub Desktop.
Exchange Server 2010 mailbox export with splitting by year if the mailbox is too large.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Exchange Server 2010 eats up extreme amounts of memory when exporting large | |
| # mailboxes. This script attempts to provide a workaround by splitting exports | |
| # of mailboxes that are larger than 10 GB into yearly chunks. | |
| # | |
| # This script will obviously create a few PSTs that are empty. You can easily | |
| # spot these by their file size. Empty PSTs are 265 KB in size. | |
| # | |
| # It worked for my one-off use case, but is provided AS-IS and without any | |
| # warranty or guarantees of correctness. | |
| $startyear = 1999 # Email older than 25 years hopefully isn't relevant anymore | |
| # The reason for not just going by the user's creation date | |
| # is that the user may have content in their mailbox from | |
| # before their creation date (someone gave them MSG files, | |
| # they restored from someone else's email archive, etc.) | |
| $destination = '\\server\exports\' # Where to store exports | |
| ############################################################################ | |
| function Wait-ForExportCompletion | |
| { | |
| param( | |
| [Parameter(Mandatory = $true)] | |
| $reqName | |
| ) | |
| Write-Host "Exporting $reqName" -NoNewline | |
| $req = Get-MailboxExportRequest -Name $reqName | |
| while ($req.Status -ne 'Completed' -and $req.Status -ne 'Failed') | |
| { | |
| $exportStats = $req | Get-MailboxExportRequestStatistics | |
| if ($null -ne $exportStats.PercentComplete) | |
| { | |
| try | |
| { | |
| $averageTimePerItem = ($exportStats.TotalInProgressDuration.TotalSeconds) / $exportStats.ItemsTransferred | |
| $itemsRemaining = $exportStats.EstimatedTransferItemCount - $exportStats.ItemsTransferred | |
| $predictedRemainingDurationSeconds = $averageTimePerItem * $itemsRemaining | |
| $predictedRemainingDuration = [TimeSpan]::FromSeconds($predictedRemainingDurationSeconds) | |
| Write-Progress -Activity "Processing $($req.Name)" -Status "$($exportStats.PercentComplete)% Complete. ETA: $($predictedRemainingDuration.ToString()), Remaining: $itemsRemaining" -PercentComplete $exportStats.PercentComplete | |
| } | |
| catch | |
| { | |
| Write-Progress -Activity "Processing $($req.Name)" -Status 'Initializing' -PercentComplete 0 | |
| } | |
| Write-Host '.' -NoNewline | |
| } | |
| Start-Sleep -Seconds 5 | |
| $req = Get-MailboxExportRequest -Name $reqName | |
| } | |
| 'Done.' | |
| Write-Progress -Activity "Processing $reqName" -Status 'Export completed.' -PercentComplete 100 | |
| if ($req.Status -eq 'Failed') | |
| { | |
| $req | Get-MailboxExportRequestStatistics | Format-List | |
| throw 'Export failed.' | |
| } | |
| } | |
| $username = Read-Host 'Enter the mailbox identity' | |
| $mailbox = $null | |
| try | |
| { | |
| $mailbox = Get-Mailbox -identity $username | |
| } | |
| catch | |
| { | |
| Write-Error 'Invalid mailbox identity.' | |
| throw | |
| } | |
| 'Determining mailbox size. This may take a while...' | |
| $mailboxsize = $mailbox | Get-MailboxStatistics | Select-Object @{Name = 'TotalItemSizeGB'; Expression = { [math]::Round(($_.TotalItemSize.ToString().Split('(')[1].Split(' ')[0].Replace(',', '') / 1GB), 0) } } | |
| if ($mailboxsize.TotalItemSizeGB -le 10) | |
| { | |
| 'This mailbox is small. Exporting as a single PST file.' | |
| $reqName = "$username.complete" | |
| New-MailboxExportRequest -Mailbox $username -Name $reqName -FilePath "$destination\$reqName.pst" | Out-Null | |
| Wait-ForExportCompletion -reqName $reqName | |
| } | |
| else | |
| { | |
| 'This mailbox is large. It will be split into yearly PST files.' | |
| $y = $startyear | |
| $endyear = (Get-Date).Year | |
| While ($y -le $endyear) | |
| { | |
| $start = New-Object DateTime $y, 1, 1 | |
| $end = New-Object DateTime ($y + 1), 1, 1 | |
| $reqName = "$username.email.$y" | |
| New-MailboxExportRequest -ContentFilter "MessageKind -eq 'Email' -and ((Received -ge '$start') -and (Received -lt '$end') -or (Sent -ge '$start') -and (Sent -lt '$end'))" -Mailbox $username -Name $reqName -FilePath "$destination\$reqName.pst" | Out-Null | |
| Wait-ForExportCompletion -reqName $reqName | |
| $y++ | |
| } | |
| # Items that are not email don't have a sent or received property. | |
| $reqName = "$username.nonemail" | |
| New-MailboxExportRequest -ContentFilter "MessageKind -ne 'Email'" -Mailbox $username -Name $reqName -FilePath "$destination\$reqName.pst" | Out-Null | |
| Wait-ForExportCompletion -reqName $reqName | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment