Steve Goodman's Tech Blog – The weblog of an IT pro specialising in Exchange, Exchange, VMware, Servers and Storage
17Jul/1012

Using the Exchange 2010 SP1 Mailbox Export features for Mass Exports to PST files

In Exchange 2007 SP1 thru to Exchange 2010 RTM, the Export-Mailbox command was the replacement for the once-familiar ExMerge utility when it came to exporting mailboxes to PST files.

The main problem with Export-Mailbox for most Exchange administrators is the requirement for Outlook – either on a 32-bit machine with Management Tools for Exchange 2007, or on a 64-bit machine for Exchange 2010. All in all, it wasn’t ideal and certainly didn’t facilitate scripted mailbox exports.

Thankfully, with Exchange 2010 SP1, Export-Mailbox is going the way of the dodo and new cmdlets for Mailbox imports and exports are available. Just like the New-MoveRequest cmdlet, the new import/export command use the Mailbox Replication Service to perform the move via one of the Client Access Servers giving performance benefits, such as ensuring the PST transfer doesn’t have to go via the machine with the Exchange Management Tools/Outlook installed, as was the case previously.

The main aim of this post is to give you an overview of how to use the new mailbox export cmdlets, and then show you how to put them to practical use, both at the command line and with a scheduled task for brick-level backups.

Getting it set up

The basic requirements for using the new feature are pretty straightforward. You need to use an account that’s a member of the organisational management groups, and have the “Mailbox Import Export” role assignment assigned to you or a role group you’re a member of. As the export is done at a CAS server (and if you’ve multiple CAS servers you can’t specify which one in each site will be used) you can’t specify a local drive letter and path – you must specify a UNC path to a network share that the “Exchange Trusted Subsystem” group has read/write access to.

Step One

Create a share on a server, and grant Exchange Trusted Subsystem read/write permission. In this example I’m using a share called Exports on a test server called Azua in my lab environment:

image

Step Two

Next, you’ll need to grant a user, or group, the Mailbox Import Export role assignment. You can do this using the Exchange Management shell with a single command. In this example, I’m granting my lab domain’s Administrator user the role assignment:

image

New-ManagementRoleAssignment –Role “Mailbox Import Export” –User AD\Administrator

After you’ve done this, close and re-open the Exchange Management shell, and you’re ready to go!

Exporting a Mailbox

At it’s simplest, use the New-MailboxExportRequest command with the –Mailbox parameter, to specify the mailbox to export along with the –FilePath parameter, to specify the PST file to create and export data to, e.g:

image
New-MailboxExportRequest -Mailbox Administrator -FilePath "\\AZUA\Exports\Administrator.pst"

In addition, there are some other useful options – such as –BatchName, which allows grouping of requests together, and –ContentFilter, which allows only certain content to be exported to the PST – useful for discovery purposes.  As usual, use the Get-Help New-MailboxExportRequest –detailed command to review the full plethora of options.

After submission of your requests, you can check progress, including the percentage complete, with the two Get-MailboxExportRequest and the Get-MailboxExportRequestStatistics commands. Pipe the former into the latter to get a listing:

image

Get-MailboxExportRequest | Get-MailboxExportRequestStatistics

After the requests complete, you can remove the requests in a similar fashion, using the Remove-MailboxExportRequest command:

image

Get-MailboxExportRequest | Remove-MailboxExportRequest
Performing mass exports

One benefit of Powershell is it’s very easy to put together commands enabling mass-exports of PST data with only a few commands. If you really wanted to, you could even use a Powershell script as a secondary brick-level backup!

The Basics

So to check out how to do this, let’s look at it’s simplest – backing up all the mailboxes (assuming it’s a full Exchange 2010 environment) to a single share:

image

foreach ($i in (Get-Mailbox)) { New-MailboxExportRequest -Mailbox $i -FilePath "\\AZUA\Exports\${$i.Alias).pst" }

In the above example, we’re simply performing a for-each loop through each mailbox and creating a new Mailbox Export Request, using the alias to build the name for the PST.

But – what if we’re in a mixed environment, and only want to target the Exchange 2010 mailboxes?

image

foreach ($i in (Get-Mailbox | Where {$_.ExchangeVersion.ExchangeBuild.Major -eq 14})) { New-MailboxExportRequest -Mailbox $i -FilePath "\\AZUA\Exports\${$i.Alias).pst" }

In this example above, now, we’ve added a clause to only select the mailboxes where the Exchange Major Build is 14 – Exchange 2010. Simple!

Moving on from such wide-targeting, you may want to target just a pre-defined list, using a CSV file. To do this, simply create a CSV file with the column “Alias”, and list the Mailbox alias fields you wish to export. Then, using the Import-CSV command we can use this CSV file to create the requests:

image

foreach ($i in (Import-Csv .\exports.csv)) { New-MailboxExportRequest -Mailbox $i.Alias -FilePath "\\AZUA\Exports\$($i.Alias).pst" }
Performing Mass Exports as a scheduled task

Now you’ve seen the basics of how easy it is to perform mass mailbox exports using the New-MailboxExportRequest command, I’ll finish off with a final example showing how to use this mass export feature as part of a scheduled task.

This script is aimed at backing up all the mailboxes on a single database, or a single server. After creating the requests, it waits for the requests to complete then, if you’ve specified a report directory, it will write reports showing completed and incomplete (i.e. failed!) requests. Finally it removes the requests it created.

To use the script, you need to alter the config section and specify either a server or a database, a share to export to, a share to write a report to after the process has completed and you can choose whether to remove each mailbox’s associated PST file or leave as-is at each export – merging the contents.

You’ll see the content of the script below and at the bottom of the post I’ve zipped it up along with a bootstrap CMD file you could use when setting up a schedule task. As always – use at your own risk and test out in your lab environment first. Happy Exporting!

# Exchange 2010 SP1 Mailbox Export Script
# Steve Goodman. Use at your own risk!

###############
# Settings    #
###############

# Pick ONE of the two below. If you choose both, it will use $Server.
$Server = "server"
$Database = ""

# Share to export mailboxes to. Needs R/W by Exchange Trusted Subsystem
# Must be a UNC path as this is run by the CAS MRS service.
$ExportShare = "\\server\share"

# After each run a report of the exports can be dropped into the directory specified below. (The user that runs this script needs access to this share)
# Must be a UNC path or the full path of a local directory.
$ReportShare = "\\server\share"

# Shall we remove the PST file, if it exists beforehand? (The user that runs this script needs access to the $ExportShare share)
# Valid values: $true or $false
$RemovePSTBeforeExport = $false

###############
# Code        #
###############

if ($Server)
{
if (!(Get-ExchangeServer $Server -ErrorAction SilentlyContinue))
{
throw "Exchange Server $Server not found";
}
if (!(Get-MailboxDatabase -Server $Server -ErrorAction SilentlyContinue))
{
throw "Exchange Server $Server does not have mailbox databases";
}
$Mailboxes = Get-Mailbox -Server $Server -ResultSize Unlimited
} elseif ($Database) {
if (!(Get-MailboxDatabase $Database -ErrorAction SilentlyContinue))
{
throw "Mailbox database $Database not found"
}
$Mailboxes = Get-Mailbox -Database $Database
}
if (!$Mailboxes)
{
throw "No mailboxes found on $Server"
}

if (!$Mailboxes.Count)
{
throw "This script does not support a single mailbox export."
}

# Pre-checks done

# Make batch name
$date=Get-Date
$BatchName = "Export_$($date.Year)-$($date.Month)-$($date.Day)_$($date.Hour)-$($date.Minute)-$($date.Second)"

Write-Output "Queuing $($Mailboxes.Count) mailboxes as batch '$($BatchName)'"

# Queue all mailbox export requests
foreach ($Mailbox in $Mailboxes)
{

if ($RemovePSTBeforeExport -eq $true -and (Get-Item "$($ExportShare)\$($Mailbox.Alias).PST" -ErrorAction SilentlyContinue))
{
Remove-Item "$($ExportShare)\$($Mailbox.Alias).PST" -Confirm:$false
}
New-MailboxExportRequest -BatchName $BatchName -Mailbox $Mailbox.Alias -FilePath "$($ExportShare)\$($Mailbox.Alias).PST"
}

Write-Output "Waiting for batch to complete"

# Wait for mailbox export requests to complete
while ((Get-MailboxExportRequest -BatchName $BatchName | Where {$_.Status -eq "Queued" -or $_.Status -eq "InProgress"}))
{

sleep 60
}

# Write reports if required
if ($ReportShare)
{
Write-Output "Writing reports to $($ReportShare)"
$Completed = Get-MailboxExportRequest -BatchName $BatchName | Where {$_.Status -eq "Completed"} | Get-MailboxExportRequestStatistics | Format-List
if ($Completed)
{
$Completed | Out-File -FilePath "$($ReportShare)\$($BatchName)_Completed.txt"
}
$Incomplete = Get-MailboxExportRequest -BatchName $BatchName | Where {$_.Status -ne "Completed"} | Get-MailboxExportRequestStatistics | Format-List
if ($Incomplete)
{
$Incomplete | Out-File -FilePath "$($ReportShare)\$($BatchName)_Incomplete_Report.txt"
}
}

# Remove Requests
Write-Output "Removing requests created as part of batch '$($BatchName)'"
Get-MailboxExportRequest -BatchName $BatchName | Remove-MailboxExportRequest -Confirm:$false

Command file contents:

C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -command ". 'c:\Program Files\Microsoft\Exchange Server\V14\bin\RemoteExchange.ps1'; Connect-ExchangeServer -auto; .\MassExport.ps1"

Download as ZIP

  • Share/Bookmark
Comments (12) Trackbacks (2)
  1. Great write-up! You and Henrik are neck and neck!
    http://www.msexchange.org/articles_tutorials/exchange-server-2010/management-administration/look-import-export-mailbox-improvements-exchange-2010-service-pack-1-part1.html

    Did your server have multiple roles installed or just the mailbox role? there was a bug with multiple roles and import-mailbox in 2010 RTM.

    • Hi Mike,

      This was going to be an post covering all the features but yep, Henrik is publishing a much better multi-part article therefore I thought I’d focus on just the mass-export features.

      Good point about the roles. That’s the very reason I’ve been holding back on posting this article – the lab environment I started writing this against has CAS, HT, DAG all on seperate servers, and includes a CAS array in the mix, so I hit a similar bug to the one you mention. Good news is that it’s fixed in newer builds and should hopefully stay fixed for SP1 RTW!

      If you are trying this now on SP1 beta, it should be fine on a multi-role test box though.

      Steve

  2. nice post. thanks.

  3. Great post – I get this error:
    Couldn’t connect to the source mailbox.
    + CategoryInfo : NotSpecified: (0:Int32) [New-MailboxExportRequest], RemoteTransientException
    + FullyQualifiedErrorId : B34FC71E,Microsoft.Exchange.Management.RecipientTasks.NewMailboxExportRequest

    Do you know anything about this ?

    • Yes. It’s a known big in the beta build and manifests itself mainly when there is a CAS array setup. It’s fixed in later builds and will be in RTW of SP1.

      Easiest way to test out this feature before it’s released is to setup a multi-role server on it’s own. I can provide workaround steps if you need tho.

      Steve

  4. Please to post workarround steps :-)

  5. Hi Steve, I’m interested for a workaround, since I’m using CAS array in my lab.

    Regards,

    Andrija

  6. Hi All,

    I have a lab environment with the exact same problem. (Couldn’t connect to the source mailbox.)
    My lab is build with a single server exchange installation. Anyone knows another couse for this error?

    Regard,

    Kees


Leave a comment