Exchange Server 2010 Windows PowerShell: Managing Mailboxes


Microsoft Exchange 2010 PowerShell Cookbook

Microsoft Exchange 2010 PowerShell Cookbook

Manage and maintain your Microsoft Exchange 2010 environment with the Exchange Management Shell and Windows PowerShell 2.0 using this book and eBook

        Read more about this book      

(For more resources on this subject, see here.)

The reader will benefit from referring two previous articles: Troubleshooting Mailboxes and Reporting on Mailbox

Performing some basic steps

To work with the code samples in this article, follow these steps to launch the Exchange Management Shell:

  1. Log onto a workstation or server with the Exchange Management Tools installed.
  2. Open the Exchange Management Shell by clicking on Start | All Programs | Exchange Server 2010.
  3. Click on the Exchange Management Shell shortcut.

Importing and exporting mailboxes

If you have worked with Exchange for a long time, you have probably used utilities such as ExMerge or the Exchange 2007 Management Shell to import and export data between mailboxes and PST files. While these tools were useful for their time, they had some limitations. For example, ExMerge was the main import and export utility starting with Exchange 5.5 and continuing on to Exchange 2003, but it was difficult to automate. Exchange 2007 included the Import-Mailbox and Export-Mailbox cmdlets th at made it easier to automate these tasks through PowerShell scripts. Unfortunately, the Export-Mailbox cmdlet required both a 32-bit workstation running the 32-bit version of the Exchange 2007 Management tools and Microsoft Outlook 2003 SP2 or later.

With the release of Exchange 2010 SP1, we have a new set of cmdlets that can be used to manage the import and export operations for Exchange mailboxes. These new cmdlets have no dependencies on a management workstation and there is no requirement to install Outlook to perform these tasks. The Mailbox Replication Service (MRS) that runs on the Client Access Server (CAS) role introduces a new concept called mailbox import and export requests that implements this functionality as a server-side process. In this recipe, you will learn how to configure your environment and use these cmdlets to automate mailbox import and export requests.

How to do it...

  1. Let's start off by exporting a mailbox to a PST ? le. First, you need to add an RBAC role assignment for your account. Assign the Mailbox Import Export role to your account using the following command. You will need to restart the shell after running this command in order for the assigned cmdlets to be visible:

    New-ManagementRoleAssignment -Role "Mailbox Import Export" `
    -User administrator

  2. Next, you will need to create a network share that can be used to store the PST file. When you create the share, make sure that the Exchange Trusted Subsystem group in Active Directory has at least read/write NTFS permissions on the folder, and also has at least modify share permissions.
  3. The last step is to use the New-MailboxExportRequest cmdlet to export the data for a mailbox, using the following syntax:

    New-MailboxExportRequest -Mailbox testuser `
    -Filepath \\contoso-ex01\export\testuser.pst

How it works...

By default, the built-in Mailbox Import Export role is not assigned to anyone, including the administrators. This means that, out of the box, you will not be able to run the *-MailboxExportRequest cmdlets, even if you are a member of the Organization Management role group. Therefore, the ? rst step in the process is to assign your account to this role using the New-ManagementRoleAssignment cmdlet. I n the previous example, you can see that we created a direct assignment to the administrator's user account. This can be your administrative account, or an actual role group that you are already a member of. If needed, you can specify that the role be assigned to a role group or an Active Directory security group using the -SecurityGroup parameter.

The location used for imported and exported PSTs must be a valid UNC path that the Exchange Trusted Subsystem group has access to. This is because the cmdlets that you execute are actually running under the security context of the Exchange servers in this group group. This is required to implement the new RBAC security model, and, therefore, the Share and NTFS permissions must be assigned to this group and not your user account specifically.

The syntax for the import and export commands is fairly straightforward. Looking at the command used in the previous example, you can see that we were able to easily create an export request for a specified mailbox using a specific file share on the network.

Using additional parameters, we can do other interesting things, such as only exporting specific folders of a mailbox to a PST:

New-MailboxExportRequest -Mailbox testuser `
-IncludeFolders "Sent Items" `
-FilePath \\contoso-ex01\export\testuser_sent.pst `

As you can see from the command, we are only exporting the Sent Items folder from the testuser mailbox and we are excluding the items in the dumpster.

Here is another example that exports data from an archive mailbox:

New-MailboxExportRequest -Mailbox testuser `
-ContentFilter {Received -lt "09/01/2010"} `
-FilePath \\contoso-ex01\export\testuser_archive.pst `
-ExcludeDumpster `

Here we are specifying that we want to only export data from the archive mailbox by using the -IsArchive switch parameter . In addition, we are limiting the amount of data exported from the mailbox using the -ContentFilter parameter . We are only including items that were received before 09/01/2010. In addition to the Received property, the -ContentFilter parameter allows you to highly customize the data that is exported.

You can create upto 10 mailbox export requests per mailbox without manually specifying a name for the export request. Once you have reached this limit, you either need to specify a unique name for the export request, or delete some of the previous export requests using the Remove-MailboxExportRequest cmdlet.

Using the -ContentFilter parameter, you can filter the recipient, types of attachments that were included in a message, text in the body, and more. For a complete list of available property names, check out the Filterable Properties for the -ContentFilter Parameter on TechNet at the following URL:

There's more...

You can use the Get-MailboxImportRequest and Get-MailboxExportRequest cmdlets to view the status of your import and export tasks. To view all requests, simply run the appropriate Get-* cmdlet . If you want to narrow your search, you can use the -Mailbox and -Status parameters:

Get-MailboxExportRequest -Mailbox testuser -Status Failed

This command will return all of the export requests made for the testuser mailbox that have a failed status. You can use the same syntax with the import version of this cmdlet to review similar information.


When it comes to advanced reporting of import or export requests, there are two cmdlets available that you can use. Get-MailboxExportRequestStatistics and Get-MailboxImportRequestStatistics can be used to provide detailed information about the tasks associated with a particular operation. For example, take a look at the following script:

foreach($i in Get-MailboxExportRequest) {
Get-MailboxExportRequestStatistics $i |
select-object SourceAlias,Status,PercentComplete

This will provide a brief report for each export request. This can be useful when you are performing multiple import or export operations and need to check the status of each one.

Importing data into mailboxes

The New-MailboxImportRequest cmdlet works similarly to the New-MailboxExportRequest cmdlet. Most of the parameters shown in the previous examples are available with both cmdlets. For example, we can import data into a specific folder in an inbox with the following command:

New-MailboxImportRequest -Mailbox sysadmin `
-IncludeFolders "Sent Items" `
-FilePath \\contoso-ex01\export\testuser_sent.pst

This command imports the testuser PST into the Sent Items folder of the sysadmin mailbox. In addition to exporting data from archive mailboxes, we can also import data into archive mailboxes with the -IsArchive switch parameter.

Taking it a step further

Let's create a script that will export all of the mailboxes in your organization to individual PST files stored in a central location. Create a new file called Export.ps1 and save it in the C:\ drive. Using a text editor, open the file and add the following code, and then save the file:

param($Path, $BatchName)
foreach($i in Get-Mailbox -ResultSize Unlimited) {
$filepath = Join-Path -Path $Path -ChildPath "$($_.alias).pst"
New-MailboxExportRequest -Mailbox $i `
-FilePath $filepath `
-BatchName $BatchName

This script provides a couple of parameters used to control the behavior of the mailbox export requests. First, the -Path parameter will allow us to specify a UNC share for our exported mailboxes. Secondly, the -BatchName parameter is used to logically group the export requests using a friendly common name.

As we loop through each mailbox, we are doing a few things. We are using the value of the -Path parameter as the root directory for the PST file, and we are using the alias of the mailbox for the base filename. This will ensure that each PST file is stored centrally in the required location using a unique filename that matches the mailbox alias. To execute the preceding script, the command might look something like this:

$batch = "Export for (Get-Date).ToShortDateString()"
.\Export.ps1 -Path \\contoso\ex01\export -BatchName$batch

This will create each mailbox export request using a batch name such as Export for 10/26/2010. Then you can easily check the status of all the mailbox export requests that are grouped into that batch name using the following command:

Get-MailboxExportRequestStatistics |
?{$_.BatchName -eq "Export for 10/26/2010"} |
select SourceAlias,Status,PercentComplete

This one-liner will give you a brief report on each of the export requests performed in the batch created on 10/26/2010 that can be reviewed in the shell, exported to a text or CSV file, or e-mailed to another user.

        Read more about this book      

(For more resources on this subject, see here.)

Deleting messages from mailboxes

At one point or another, you are bound to find yourself in a situation where you need to remove an e-mail message from one or more mailboxes. This may be due to a message being sent to one of your distribution lists or as a part of some kind of spam or virus-related outbreak. If you have worked with Exchange 2007, you may be familiar with the Export-Mailbox cmdlet that could previously be used to perform this task. With Exchange 2010 SP1, we now have a new cmdlet called Search-Mailbox that can be used to clean up the mailboxes in our environment. This cmdlet includes some new features as well, and in this recipe we will take a look at how to use it to delete messages from mailboxes.

How to do it...

  1. If you have not already done so, you will need to use the following command syntax to assign your account the Mailbox Import Export RBAC role. You will need to restart the shell after running this command in order for the assigned cmdlet to be visible:

    New-ManagementRoleAssignment -Role "Mailbox Import Export" `
    -User administrator

  2. Next, use the Search-Mailbox cmdlet to delete items from a mailbox. In this example, we will use a search query to delete items with a specific phrase in the subject line:

    Search-Mailbox -Identity testuser `
    -SearchQuery "Subject:'Your mailbox is full'" `
    -DeleteContent `

How it works...

The key to deleting items from a mailbox is the -DeleteContent switch parameter used with the Search-Mailbox cmdlet. When executing the command in the previous example, any message matching the subject specified in the search query will be deleted without confirmation and output similar to the following will be displayed:

Microsoft Exchange Server 2010 Windows PowerShell tutorial

As you can see, there is a lot of useful information returned that indicates whether or not the delete operation was successful, how many items were deleted, the total item size of the deleted messages, and so on.

Keep in mind that the Search-Mailbox cmdlet will include messages in a user's archive mailbox and the dumpster within their primary mailbox as part of the search. To exclude these, use the following syntax:

Search-Mailbox -Identity testuser `
-SearchQuery "Subject:'free ipad'" `
-DoNotIncludeArchive `
-SearchDumpster:$false `
-DeleteContent `

There's more...

The -SearchQuery parameter is used to specify the criteria of your search using Advanced Query Syntax (AQS), which is the same query syntax used with Windows Search, Exchange Search, and the Instant Search box in Outlook. When composing a command, you want to use the property name, followed by a colon, and then the text you want to query. There are several AQS properties that can be used, some of the more common properties are Subject, Body, Sent, To, From, and Attachment.

Running reports before deleting data

Of course, permanently deleting data from someone's mailbox is not something that should be done without total confidence. If you are unsure of the results, or you just want to cover your bases, you can use the following syntax to generate a report of the items that will be deleted:

Get-Mailbox |
Search-Mailbox -SearchQuery "" `
-EstimateResultOnly | Export-CSV C:\report.csv -NoType

This example uses the -EstimateResultsOnly parameter when executing the Search-Mailbox cmdlet. You can see here that we are executing a one-liner that will search each mailbox for messages sent from The estimate for the result is exported to a CSV file that you can use to determine how much data will be cleaned up out of each individual mailbox.

If you need a more detailed report, we can use the logging capabilities of the Search-Mailbox cmdlet. The following command performs a search on the testuser mailbox and generates some reports that we can use to determine exactly what will be deleted:

Search-Mailbox -Identity testuser `
-SearchQuery "Subject:'Accounting Reports'" `
-TargetMailbox sysadmin `
-TargetFolder "Delete Log" `
-LogOnly `
-LogLevel Full

This is made possible by the -LogOnly switch parameter. This will generate a message in a target mailbox folder that you specify. In this example, you can see that the target folder for the report is the Delete Log folder in the sysadmin mailbox. This report will provide a summary of the items that will be deleted in the search if you were to run this command with the -DeleteContent parameter. When setting the -LogLevel to parameter value to Full, a ZIP file, containing a CSV report listing each of the items returned by the search will be attached to this message.

Deleting messages in bulk

Most likely, you will need to delete items from several mailboxes in a bulk operation. The following one-liner can be used to delete messages from every mailbox in the organization:

Get-Mailbox -ResultSize Unlimited |
Search-Mailbox -SearchQuery '' `
-DeleteContent -Force

In this example, we are piping all the mailboxes in the organization to the Search-Mailbox cmdlet. Any messages sent from the e-mail address will be deleted.

        Read more about this book      

(For more resources on this subject, see here.)

Managing disconnected mailboxes

Exchange allows us to disassociate a mailbox from an Active Directory user account, and later reconnect that mailbox to an Active Directory account. For some organizations, a mailbox database has a low deleted mailbox retention setting, and once a mailbox has been removed from a user, it is forgotten about and purged from the database once the retention period elapses. However, if you maintain your deleted mailboxes for any amount of time, having the ability to retrieve these mailboxes after they have been removed from a user can be very helpful at times. In this recipe, we will take a look at how to manage disconnected mailboxes using the Exchange Management Shell.

How to do it...

To reconnect a disconnected mailbox to a user account, use the Connect-Mailbox cmdlet. The following example reconnects a disconnected mailbox to the tuser1009 account the Active Directory:

Connect-Mailbox -Identity ‘Test User’ `
-Database DB1 `
-User ‘contoso\tuser1009’ `
-Alias tuser1009

How it works...

When you use the Remove-Mailbox or Disable-Mailbox cmdlets to delete a mailbox for a user, that mailbox can actually be retained in its source database for a period of time. This is determined by the deleted mailbox retention setting of the database the mailbox resides in. For example, let's say that the deleted mailbox retention for the database hosting the testuser mailbox is set to 30 days. After the testuser mailbox has been deleted, this gives us 30 days to reconnect that mailbox to an Active Directory user account before the retention period is met and the mailbox is permanently purged.

The -Identity parameter, used with the Connect-Mailbox cmdlet, specifies the mailbox that should be connected to an Active Directory account and can accept the MailboxGuid, DisplayName, or LegacyExchangeDN values for input. Finding this information requires a little digging, as there is no Get cmdlet when it comes to searching for disconnected mailboxes. You can find this information with the Get-MailboxStatistics cmdlet:

Get-MailboxDatabase |
Get-MailboxStatistics |
?{$_.DisconnectDate} |
fl DisplayName,MailboxGuid,LegacyExchangeDN,DisconnectDate

This command will search each database for mailboxes that have a DisconnectDate defined. The values that can be used to identify a disconnected mailbox when running the Connect-Mailbox cmdlet will be displayed in the list format.

It is possible that there could be multiple disconnected mailboxes with the same DisplayName. In this case, you can use the MailboxGuid value to identify the disconnected mailbox that should be reconnected.

The previous command will return both disconnected mailboxes and also disconnected archive mailboxes, so you may need to filter those out if you have implemented personal archives in your environment. For example:

Get-MailboxDatabase |
Get-MailboxStatistics |
?{$_.DisconnectDate -and $_.IsArchiveMailbox -eq $false} |
fl DisplayName,MailboxGuid,LegacyExchangeDN,DisconnectDate

This one-liner will search for disconnected mailboxes in all databases that do not have their IsArchiveMailbox property set to $true.

All of these commands can be a little cumbersome to type, and if you use them often, it might make sense to write some custom code that makes this easier. Take a look at the following function that has been written to automate the process:

function Get-DisconnectedMailbox {
[String]$Name = '*',

$databases = Get-MailboxDatabase
$databases | %{
$db = Get-Mailboxstatistics -Database $_ |
?{$_.DisconnectDate -and $_.IsArchiveMailbox -eq $Archive}

$db | ?{$_.displayname -like $Name} |
Select DisplayName,

This function can be added to your PowerShell profile, and it will then be available every time you start the Exchange Management Shell. You can then run the function just like a regular cmdlet. By default, if you run the cmdlet without parameters all of the disconnected mailboxes in your environment will be returned. You can also narrow your search using wildcards, as shown in the following screenshot:

Microsoft Exchange Server 2010 Windows PowerShell tutorial

Here you can see that we have used a wildcard with the function to find all the disconnected mailboxes starting with the letter d. To use the function to find disconnected archive mailboxes, simply use the -Archive switch parameter.

There's more...

With the introduction of move requests in Exchange 2010 SP1, some new functionality has been added that you will need to be aware of when managing disconnected mailboxes. When you use the New-MoveRequest cmdlet t o move a mailbox from one database to another, the mailbox in the source database is not deleted, and instead, is disconnected and marked as Soft-Deleted. You can check the value of the DisconnectReason property when working with a disconnected mailbox using the Get-MailboxStatistics cmdlet. The Get-DisconnectedMailbox function included earlier in this recipe will also return the value for this property for each disconnected mailbox.

If you move or remove mailboxes frequently, you may end up with hundreds or even thousands of disconnected mailboxes at any given time. Disconnected mailboxes can be purged using the Remove-StoreMailbox cmdlet by specifying the identity of the mailbox, the database it is located in, and the disconnect state that it is in, as shown in the following example:

Remove-StoreMailbox -Identity 1c097bde-edec-47df-aa4e-535cbfaa13b4 `
-Database DB1 `
-MailboxState Disabled `

Keep in mind that, if you want to delete every single disconnected mailbox in your environment, you will need to run the Remove-StoreMailbox for mailboxes in both the Disabled and Soft-Deleted state. If you want to purge every disconnected mailbox from the organization, regardless of the location or disconnect reason, you can use the following code:

$mb = Get-MailboxDatabase |
Get-MailboxStatistics |

foreach($i in $mb) {
Remove-StoreMailbox -Identity $i.MailboxGuid `
-Database $i.Database `
-MailboxState $i.DisconnectReason.ToString() `

Mailboxes within a recovery database will be reported by the Get-MailboxStatistics cmdlet as disconnected and disabled. You cannot purge them with the Remove-StoreMailbox cmdlet; if you try to do so you will get an error.


Having covered Managing Mailboxes, in the next two articles we will cover Troubleshooting Mailboxes and Reporting on Mailbox.

Further resources on this subject:

You've been reading an excerpt of:

Microsoft Exchange 2010 PowerShell Cookbook

Explore Title