Link to home
Start Free TrialLog in
Avatar of MacGyver80
MacGyver80Flag for United States of America

asked on

Exchange 2010 SP3 - Export all Mail and Public Folder DBs to pst

I'm trying to find the command that will allow me to export all mailstores and Public Folders to PSTs.  I also need to find away to export any rules that the users have.

The Mailstores need to be exported by date range.  I've been trying to use the following for just one mailbox:

Export-Mailbox -Identity <mailbox-alias> -StartDate "01/01/2014" -EndDate "03/31/2014" -PSTFolderPath \\IP Address\folder\folder\username.pst

and all it did was bring me to:  >>

Not sure if there was anything I was missing but I wanted to use this just to test how the export of one mailbox would go.

Does anyone know what command and syntax I would use to export all of the mailstores to individual PSTs?
Avatar of Frosty555
Frosty555
Flag of Canada image

The way I've done it in the past, a Mailbox Export happens asynchronously in the background. You begin the request using the New-MailboxExportRequest command, and you check on the request periodically with Get-MailboxExportRequest. That command will give you error and status information. Later when the export is finished, you remove the request using the Remove-MailboxExportRequest command.

You must specify the target UNC path where the PST will be written to, and this path must have it's security and sharing settings configured so that it may be written to by the "Exchange Trusted Subsystem" domain group and the "SYSTEM" group.

I modified a script by Steve Goodman that I found some time ago that exports all user mailboxes. I run it as part of a backup strategy for some smaller clients. It probably doesn't do public folders or rules, but you can use it as a starting point.

backup_exchange_mailboxes.bat:

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

Open in new window


backup_exchange_mailboxes.ps1:

# 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. If you choose neither, all mailboxes will be exported
$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 = "\\YOURBACKUPSERVER\MailboxBackupFolder"

# 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 = "\\YOURBACKUPSERVER\MailboxBackupFolder"

# 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 = $true

###############
# 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
} else {
    $Mailboxes = Get-Mailbox
}


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" -AcceptLargeDataLoss -BadItemLimit 2147483646
}

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"}))
{
    Write-Output ""
    Write-Output "Current Status:"
    Get-MailboxExportRequest -BatchName $BatchName
    sleep 60
}

Write-Output ""
Write-Output "Batch is complete. Final results:"
Get-MailboxExportRequest -BatchName $BatchName
Write-Output ""

# 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

Open in new window

Avatar of VB ITS
Export-Mailbox -Identity <mailbox-alias> -StartDate "01/01/2014" -EndDate "03/31/2014" -PSTFolderPath \\IP Address\folder\folder\username.pst

and all it did was bring me to:  >>

Not sure if there was anything I was missing but I wanted to use this just to test how the export of one mailbox would go.
Usually when you receive a >> it means you may have forgotten to close off a command with the quotation marks.

e.g. You may have missed the " at the end of the -PSTFolderPath "\\IP Address\folder\folder\username.pst

By the way, the Export-Mailbox command won't work in Exchange 2013 - you'll need to use the New-MailboxExportRequest command however I'm not 100% sure this will work with Public Folders. The simplest solution would be to just export the PF data using Outlook. You can use filters to export a specific date range however doing this through Outlook will pretty much render it useless during the export process, so you'll basically need a spare machine with Office installed to use this method.
Avatar of MacGyver80

ASKER

Thank you Frosty555 and VB ITS!

Frosty,

Are there any specifics that need to be included or modified in the supplied script?

----------------------------------------------

VB ITS,

When using: New-MailboxExportRequest -Identity <mailbox-alias> -StartDate "01/01/2014" -EndDate "03/31/2014" -PSTFolderPath "\\IP Address\folder\folder\username.pst", I get the following:

A Positional parameter cannot be found that accepts argument 'username'.

         + CategoryInfo                  :InvalidArgument: <:> [New-MailboxExportRequest], ParameterBindingExeption
         + PositionalParameter     :PositionalParameterNotFound,New-MailboxExportRequest
If you are using the mailbox alias to identify the mailbox being exported then you're better off using the -Mailbox switch. The -StartDate and -EndDate switches don't work in 2010 either. To export the contents of a mailbox within a date range you'll need to use the -ContentFilter switch instead.

New-MailboxExportRequest -Mailbox <mailbox alias> -ContentFilter {(Received -lt ’03/31/2014′) -and (Received -ge ’01/01/2014′) -or (Sent -lt ’03/31/2014') -and (Sent -ge ’01/01/2014′)} -FilePath "\\Server\Share\Username.PST"

Open in new window

VB,

I just try it and it brought me back to the >>.  So I think something is missing from the command but not sure what.  

I also ensured the " were placed in the correct locations.
Looks like drive mapping issue, can you change the export path to C:\temp\user.pst and test it again.
My apologies MacGyver80, I didn't realise you replied! I just tested the command and I ran into the same issue. I had to play around with the code a bit and managed to get it working. Below is the modified version of it:

New-MailboxExportRequest -Mailbox <mailbox alias> -ContentFilter {((Received -lt "03/31/2014") -and (Received -ge "01/01/2014")) -or ((Sent -lt "03/31/2014") -and (Sent -ge "01/01/2014"))} -FilePath "\\Server\Share\Username.PST"

Open in new window

Thanks VB. I'm trying it out now and I'll report back with the output.

And, thank you as well Netminder!

Frosty,

If you could elaborate more on any specifics that need to be applied to the give script, it would be much appreciated.
That command worked perfectly VB, thanks!  I really needed this for testing purposes.

I just need to find the command that will allow me to export the entire mailstore to respective user PSTs. The company is doing this dirty way and I have to export all mailboxes to corresponding user PSTs in preparation for the merger.  

I've going back and forth with the client to open up a Two-Way Transitive Trust but I'm getting nothing but push back because the IT Security Officer is wet behind the ears and doesn't want to change anything,

If a command to export the entire Mailstore to PSTs can be shared, I would be extremely grateful.
Do you still require the ability to export date ranges or just a straight export of the entire mailbox?
What I'm looking is ability to export the entire maidstone to PSTs but the need to be broken up by users.

Your command confirmed what kind of output I am looking for but I need to be able to do this to the entire Mailstore so that it breaks up the output in to individual PSTs per user.

I run the command and I get... :

UserA.PST
UserB.PST
UserB.PST
Etc....

... In to the specified folder.

This would be efficient for me so that I don't have have to apply the command over and over.
SOLUTION
Avatar of VB ITS
VB ITS
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Great.

Two questions however:

1. If I omit the, "-ContentFilter {((Received -lt "03/31/2014") -and (Received -ge "01/01/2014")) -or ((Sent -lt "03/31/2014") -and (Sent -ge "01/01/2014"))}", will it do the entire Mail Database ??

2. Will this code allow the exportation of all Mailboxes in the database?  Only reason I ask is because I'm noticing the "-Mailbox <mailbox alias>", which in my experience with Powershell, which isn't much, specifies the individual mailbox.
1. If I omit the, "-ContentFilter {((Received -lt "03/31/2014") -and (Received -ge "01/01/2014")) -or ((Sent -lt "03/31/2014") -and (Sent -ge "01/01/2014"))}", will it do the entire Mail Database ??
Yes, that will work fine.
2. Will this code allow the exportation of all Mailboxes in the database?  Only reason I ask is because I'm noticing the "-Mailbox <mailbox alias>", which in my experience with Powershell, which isn't much, specifies the individual mailbox.
My apologies, you're correct. the -Mailbox switch isn't needed, I must have forgotten to take it out.

I've updated the commands for you below:
$Export = Get-Mailbox -Database <name of database>
$Export | %{$_ | New-MailboxExportRequest -FilePath "\\Server\Share\$($_.alias).PST}"

Open in new window

Thanks.  I'll give it a run sometime this week and report the output.
To ensure functionality, this will run on SP3, right?

I only ask because I've been noticing changes to Powershell commands within SP releases.
Should work perfectly fine, I confirmed the cmdlets are listed for Exchange 2010 SP3 on TechNet and on some Exchange 2010 SP3 servers I have access to. You can use the -WhatIf switch at the end of the second line to test the output as this won't actually run the command but will instead give you the output of what will happen.
Good to know. Thanks VB.
I'm getting an error when running the first command.

A positional parameter cannot be found that accepts argument 'Database'
     + CategoryInfo                  : InvalidArguement: (:) [Get-Mailbox], ParameterBindingException
     + FullyQualifiedErrorId    : PositionalParameterNotFound,Get-Mailbox

Command entered:

$Export = Get-Mailbox -Database Mailbox Database ****
Did you specify the name of your database after the -Database switch? You can get the name by going to Organization ConfigurationMailboxDatabase Management tab.
The actual name of the database that was created is "Mailbox Database (some digits)"
I'm assuming you put quotation marks around the database name? i.e. $Export = Get-Mailbox -Database "Mailbox Database (some digits)"?

Do you only have the one database? If so you can just type $Export = Get-Mailbox
Silly me.

So that worked with the Quotation Marks however, when running the second line:

$Export | %{$_ | New-MailboxExportRequest -FilePath "\\IP\Share\Folder\$($_.alias).PST}" -WhatIf

...I get the dreaded >>. Which I'm assuming means that something is missing from the command...??
I really should double check my codes...

The quotation marks are after the bracket at the end of the command. Swap them around and it should work like a charm.

i.e. $_.alias).PST"}
ForEach-Object : Cannot bind parameter 'Process'. Cannot convert the "WhatIf" value of type "System.String" to type "System.Management.Automation.ScriptBlock".
At line:1 char:12
+ $Export | % <<<< {$_ | New-MailboxExportRequest -FilePath "\\IP\share\folder\$($_.alias).PST"} -WhatIf
         + CategoryInfo               : InvalidArguement: (:) [ForEach-Object], ParameterBindingException
         + FullyQualifiedErrorId : CannotConvertArguementNoMessage,Microsoft.PowerShell.Commands.ForEachObjectCommand
Hi VB,

I think I've been getting confused with the edits that have been given.  Can you please provide me a clean version of the second command?

It would be much appreciated.

Thanks!
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thank you. However, I don't think it likes the -WhatIf command.  I'm get this when I run the above with, -WhatIf:

ForEach-Object : Cannot bind parameter 'Process'. Cannot convert the "-WhatIf" value of type "System.String" to type "S At line:1 char:12
+ $Export | % <<<< {$_ | New-MailboxExportRequest -FilePath "IP\*\*\$($_.alias).PST"} -WhatIf
        +CategoryInfo               :  InvalidArguement: (:) [ForEach-Object], ParameterBindingException
        +FullyQualifiedErrorId :  CannotConvertArgumentNoMessage,Microsoft.Powershell.Commands.ForEachObjectCommand

I've yet to run the command without what if but I can't run it during Production hours and was hoping this would provide some sort of output as to what I can expect.
Where did you put the -WhatIf switch? You need to put the -WhatIf switch before the last bracket so the command would look something like this:
$Export | %{$_ | New-MailboxExportRequest -FilePath "\\Server\Share\$($_.alias).PST" -WhatIf}

Make sure you specify a valid path for the exported PST file and that the Exchange Trusted Subsystem account has full access to the -FilePath folder.

If successful, you should see output resembling What if: Creating mailbox export request 'RequestGuid (3c3d9543-5afc-4ed0-8ba2-ca4e7090fade), RequestQueue: (752c503f-a0d1-4cc0-9e64-b26e81cb2727)'. for each mailbox in the database.
Seems like that worked.  I got the mock output as you said it would provide.

Now with this command, can I do every Database? There are only 3 on the server.
Yep, just specify the database name in the first line of my code: $Export = Get-Mailbox -Database <name of database>
Sounds great!  

Thank you VB and EE.

It's people like you and EE that allow professionals to excel their knowledge through research. Great community!!
Not a problem MacGyver80, glad I could help!