≡ Menu

Managing Disconnected Exchange Mailboxes with PowerShell

Having worked with Exchange 2007/2010 and PowerShell for some time now, I’ve developed a number of functions that I use to simplify particular “hard to type” commands. This has made for some good scripting exercises, but more importantly, it has served as a great time saver when performing certain routine tasks. In this post, I am going to share some code that I use to manage disconnected Exchange mailboxes.

Finding Disconnected Mailboxes

The first function is called Get-DisconnectedMailbox and the name is pretty much self explanitory. This function will give you a list of all disconnected mailboxes on each of your mailbox servers. Take a look at the following code:

function Get-DisconnectedMailbox {
    [CmdletBinding()]
    param(
        [Parameter(Position=0, Mandatory=$false)]
        [System.String]
        $Name = '*'
    )
    
    $mailboxes = Get-MailboxServer
    $mailboxes | %{
        $disconn = Get-Mailboxstatistics -Server $_.name | ?{ $_.DisconnectDate -ne $null }
        $disconn | ?{$_.displayname -like $Name} | 
            Select DisplayName,
            @{n="StoreMailboxIdentity";e={$_.MailboxGuid}},
            Database
    }
}

Note: If you’ve recently deleted a mailbox, but it’s not showing up when running Get-DisconnectedMailbox, you may need to force Exchange to recognize this by running the Clean-MailboxDatabase cmdlet.

Running the function without specifying a user name will return all disconnected mailboxes:

To find a particular disconnected mailbox, just type the function name, followed by the users display name. For example, to determine the disconnected mailbox information for a user named Blanca Jacobs you could would run this command:

Get-DisconnectedMailbox “Blanca Jacobs”

The name parameter will accept wildcards. For example: Get-DisconnectedMailbox M* would give you all disconnected mailboxes starting with the letter “M”.

Purging Disconnected Mailboxes

You purge mailboxes using the Remove-Mailbox cmdlet, specifying the StoreMailboxIdentity and Database for the disconnected mailbox in question. For a good example of this, check out Nitin Gupta’s post on removing disconnected mailboxes.

In an effort to simplify the purging of disconnected mailboxes, I wrote the Remove-DisconnectedMailbox function that is designed to work with Get-DisconnectedMailbox. Here is the code:

function Remove-DisconnectedMailbox {
    [CmdletBinding(SupportsShouldProcess=$true)]
    param(
        [Parameter(Position=0, ValueFromPipelineByPropertyName=$true, Mandatory=$true)]
        [System.String]
        $StoreMailboxIdentity,
        [Parameter(Position=1, ValueFromPipelineByPropertyName=$true, Mandatory=$true)]
        [System.String]
        $Database
        )
    
    process {
        Remove-Mailbox @PSBoundParameters
    }
}

This allows you to easily purge all disconnected mailboxes returned from Get-DisconnectedMailbox by piping the output to Remove-DisconnectedMailbox. You can also purge one disconnected mailbox at time, as shown here:

Get-DisconnectedMailbox “Bill Jones” | Remove-DisconnectedMailbox -Confirm:$false

Notice the use of -Confirm:$false in the above command. Since this is an advanced function, we can take advantage of ShouldProcess, which allows functions to use common cmdlet parameters such as -Confirm and -WhatIf.

If you look at the code closely, you’ll notice that this function is essentially a specialized wrapper for the Remove-Mailbox cmdlet. I use splatting with the $PSBoundParameters variable to automatically bind all of the function parameter values to Remove-Mailbox.

Connecting Disconnected Mailboxes

Of course, you can also use the Get-DisconnectedMailbox cmdlet in conjunction with the built-in Connect-Mailbox cmdlet to reconnect a mailbox to a user account.

For example, here’s how you would connect a disconnected mailbox for a user named Bradford Boyer:

Get-DisconnectedMailbox “Bradford Boyer” | %{Connect-Mailbox -Identity $_.StoreMailboxIdentity -Database ‘DB1′ -User ‘contoso\bboyer’ -Alias ‘bboyer’}

As you can see in the above example, you provide the StoreMailboxIdentity, Database, User and Alias to the Connect-Mailbox cmdlet. If you’d like to do this manually, you can determine the StoreMailboxIdentity of the disconnected mailbox using the Get-MailboxStatistics cmdlet.

Update: This post was written before SP1, if you want to purge a disconnected mailboxes in SP1 use the Remove-StoreMailbox cmdlet.

37 comments… add one

  • Zer0 July 3, 2010, 5:23 am

    Sorry for being a compleate PS noob, but when i save the get-dicsconnectedmailbox script to a ps1 file and run that file in Exchange Management Shell, the get-disconnectedmailbox cmdlet doesnt come up, yet pasting the code to the window works fine, what am it doing wrong?

  • Zer0 July 3, 2010, 5:43 am

    My Documents\WindowsPowerShell\Profile.ps1

    I Put the code into that file and it works

  • Mike Pfeiffer July 3, 2010, 7:24 am

    Hi Zer0,

    Since you saved the function to a .ps1 you need to dot source that file. You do that by typing a period, then a space and then the path to the file. For example:

    [PS:1] . C:\functions.ps1

    After that, the function will be available to you and you can call it like a cmdlet using the name: Get-DisconnectedMailbox.

  • Mick July 20, 2010, 8:02 pm

    Great post, but this only seems to work with Exchange 2010. I’ve tried it in our lab (Exchange 2007) and get the following error regardless of which way I run it (console or scripted).

    [PS] C:\Scripts>. c:\scripts\get-disconnectedmailboxes.ps1
    Missing closing ‘)’ in expression.
    At C:\scripts\get-disconnectedmailboxes.ps1:5 char:9
    + [ <<<< System.String]

    Any thoughts on what needs to be done to get it to run on Exchange 2007?

    Mick

  • Mike Pfeiffer July 20, 2010, 8:30 pm

    Hi Mick, thanks. Are you running PowerShell v1 in your lab? You would need PowerShell v2 to run this code since it uses the “Advanced Function” syntax. Exchange 2007 SP2 and higher supports PowerShell v2.

  • Jeremy Schuller July 21, 2010, 12:01 pm

    I really like your post on managing disconnected mailboxes.
    Something I’ve been struggling to get right is a PS script that would export the disconnected mailboxes on a server then remove them. Any tips?

  • Mike Pfeiffer July 21, 2010, 9:23 pm

    Hi Jeremy, that sounds like a good idea for a script :) I don’t think there is a way to export a disconnected mailbox natively. You should be able to script the entire process; connect the mailbox to a temporary account, export it, and then delete it. When I get some time, I’ll post an example (it may be a couple weeks I’m extremely busy this month). Thanks for your comment.

  • Yasser July 30, 2010, 5:51 am

    I tried to run that function and got the same error as Mick

    [PS] C:\Scripts>. c:\scripts\get-disconnectedmailboxes.ps1
    Missing closing ‘)’ in expression.
    At C:\scripts\get-disconnectedmailboxes.ps1:5 char:9
    + [ <<<< System.String]

    any ideas?

  • Mike Pfeiffer August 5, 2010, 1:08 pm

    Well, Mick said it was only working for him on Exchange 2010, so my guess is that he was running PowerShell v1 on Exchange 2007. Is that the case for you as well? If so, you’ll need v2 for this code.

  • BobMaria August 5, 2010, 4:57 am

    I like your post for disconnected mailboxes.
    Can you tell me some other way to recover mailbox, i used Kernal for exchange mailbox recovery software from http://www.exchangemailboxrecovery.com to recover my lost data.

  • Mike Pfeiffer August 5, 2010, 1:07 pm

    I’m not familiar with that program. What format is your recovered data in now?

  • Dennis September 28, 2010, 11:38 am

    Mike, I am new to Powershell and seems that I have a long way to go with this.
    I savefdthe file as Disconn.ps1 at the C:\temp\ location and here is the error I get:
    Unexpected token ‘{‘ in expression or statement.
    At C:\temp\disconn.ps1:12 char:20
    + $disconn { <<<< $_.displayname -like $Name}
    + CategoryInfo : ParserError: ({:String) [], ParseException
    + FullyQualifiedErrorId : UnexpectedToken

    I am sorry if this is a simple fix..but I could not figure the problem. All help will be appreciated.

  • Mike Pfeiffer October 3, 2010, 3:32 pm

    Dennis, what Exchange version (including SP) are you running?

  • Dennis October 7, 2010, 2:05 pm

    Exchange 2010 without any SP.

    The above error did get fixed and the script Ran without giving an error. After it has been executed the Command gives the following error:

    The term ‘Get-DisconnectedMailbox’ is not recognized as the name of a cmdlet, function, script file, or operable progra
    m. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
    At line:1 char:24
    + Get-DisconnectedMailbox <<<<
    + CategoryInfo : ObjectNotFound: (Get-DisconnectedMailbox:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

  • Mike Pfeiffer October 7, 2010, 2:14 pm

    take a look at my previous post on adding functions into your PowerShell session:

    http://www.mikepfeiffer.net/2010/06/how-to-add-functions-to-your-powershell-session/

  • Johan Yusoff Abu Bakar October 27, 2010, 10:05 pm

    Mike,

    Thanks for the Get-DisconnectedMailbox however it doesn’t work nicely for me on cluster configuration as the command still trying to query passive mailbox servers that don’t have the storage mounted on it. So I tweaked it a bit to use get-mailboxdatabase instead. Sharing my tweak here :)

    function Get-DisconnectedMailbox {
    [CmdletBinding()]
    param(
    [Parameter(Position=0, Mandatory=$false)]
    [System.String]
    $Name = ‘*’
    )

    $mailboxes = Get-MailboxDatabase | Get-Mailboxstatistics | ?{ $_.DisconnectDate -ne $null }
    $mailboxes | ?{$_.displayname -like $Name} |
    Select DisplayName,
    @{n=”StoreMailboxIdentity”;e={$_.MailboxGuid}},
    Database

    }

  • Mike Pfeiffer October 28, 2010, 7:13 am

    Good point Johan, thanks for sharing :)

  • Serge Nikalaichyk October 28, 2010, 7:34 am

    Quick and dirty one-liner:
    MailboxDatabase | MailboxStatistics | ? {$_.DisconnectDate} | select DisplayName, DisconnectReason, MailboxGuid, DatabaseName, ServerName

  • Chris Miller November 11, 2010, 2:16 pm

    Mike just use this your my hero

  • Mike Pfeiffer November 11, 2010, 2:30 pm

    Awesome!

  • Justin November 11, 2010, 4:54 pm

    I’m not sure if I’m having a script issue or an Exchange issue.

    I can run Get-DisconnectedMailbox and it shows me three mailboxes all with the same name. I’ve been having an issue moving this user from 2003 to our new 2010 box. One of them is in the system mailbox database and other two are in the database I created for my users.

    Then when I run – Get-DisconnectedMailbox | Remove-DisconnectedMailbox -Confirm:$false

    I get three separate errors each of them telling me “Mailbox (StoreMailboxIdentity) doesn’t exist on database (DB name).

    If it doesn’t exist then why was the value returned? Plus, I can see it in the list of disconnected mailboxes.

    Any ideas? Thanks for your info here I learned a lot as a new PS user by your article alone!

  • Justin November 11, 2010, 5:26 pm

    I just created a new account and removed it. I was then able to see FOUR mailboxes and when running the remove command it removed the new one and failed to remove the original three.

    So…looks like an Exchange issue. Any ideas anyway? Thanks for your time!

  • Mike Pfeiffer November 15, 2010, 5:23 pm

    Hi Justin,

    Are you running SP1? This post was written before then and SP1 introduces some new functionality. My guess is that you are running SP1 and those are SoftDeleted mailboxes. Try using the Remove-StroreMailbox cmdlet to purge them, more details here:

    http://technet.microsoft.com/en-us/library/ff829913.aspx

    Here’s an example:

    Get-MailboxStatistics -Database MBD01 | where {$_.DisconnectReason -eq “SoftDeleted”} | foreach {Remove-StoreMailbox -Database $_.database -Identity $_.mailboxguid -MailboxState SoftDeleted}

  • Justin November 17, 2010, 2:44 pm

    Yes, I am on SP1 and you where exactly right! Because the mailboxes where moved back to Exch 2003 the mailboxes were in a state of soft deleted instead of disabled.

    Thanks a million!

  • Mike Pfeiffer November 17, 2010, 4:51 pm

    Excellent! Thanks for letting us know :)

  • Bo April 14, 2011, 2:48 am

    Hi,

    Is there a command to connect all disconnected mailboxes in a database using som kind of “matching user” variable?

    /Bo

  • Steve June 9, 2011, 7:49 pm

    Hi,
    I was wondering if there was a way to tie the Import-CSV to this handy little script? That’s about the only thing that would put this completely over the top. :)

    Steve

  • Mike Pfeiffer June 13, 2011, 11:05 am

    Yeah, that’s possible…what is it that you’re looking to do from the CSV? Purge, Reconnect?

    As a side note, I need to update this post as it was written before SP1. The way to purge disconnected mailboxes in SP1 is using the Remove-StoreMailbox cmdlet.

  • Duane November 1, 2011, 8:30 am

    Awesome Script.

    Is there a way to filter it down to specific group of servers and/or databases instead of it going out and trying to get servers overseas and so on?

    Thanks
    Duane

  • Mike Pfeiffer November 3, 2011, 10:44 pm

    Yeah, there are a bunch of ways you could filter. For example, you could change this line in the Get-DisconnectedMailbox function:

    $mailboxes = Get-MailboxServer

    To something like this:

    $mailboxes = Get-MailboxServer | Get-ExchangeServer | Where-Object {$_.site -like ‘*Default-First-Site-Name’}

    That would just give you mailbox servers in the default AD site.

  • Empty Hand January 11, 2012, 3:18 pm

    I am running Exchange 2010 sp2 and have about 2500 disconnected mailboxes on Exchange 2007 sp3. The goal is to keep these mailboxes for 1 year from them being disconnected. Is there a way to connect them to a temp account, move them to 2010, disable them again and repeat the process?

  • Duane January 13, 2012, 10:15 am

    One last question regarding this….is there anyway to get the disconnected mailbox size??

    In a bit of jam here and this is something I could really use!

    thanks a bunch

    Duane

  • Chris June 5, 2012, 11:29 am

    Duane, don’t know if you figured it out. Here’s what I came up with….

    Get-MailboxStatistics -Database <> | where {$_.DisconnectReason -eq “SoftDeleted”} | ft Disp*, Totali*, Server*, Database

  • Simon Juul Larsen August 30, 2012, 1:57 am

    Thank you, this is just what the doctor ordered. ;)
    Cheers from Denmark!
    /Simon

  • ITVision August 14, 2013, 8:45 am

    Greetings Mike,

    I am looking to disable a multiple mailboxes and reconnect them to new user account IDs. This is part of a cross forest mailbox move and the users have new user IDs. Are you able to provide some assistance as to what information I can read in from a .csv file for the disconnect and reconnect process? I have been manually disconnecting them and reconnecting them and pointing to the users new domain account and that has been working out well, however a scripted process would be preferred.

    Much appreciated.

  • Mike Pfeiffer September 2, 2013, 9:10 pm

    Which Exchange version and SP?

  • dameluthas April 7, 2014, 12:38 pm

    Hi Mike..

    I’m looking for a script that will find the Disconnected Mailboxes in Exchange 2010 sp3.. connect them to temporary accounts and possibly export them to a location..

    A bonus would be.. being able to find the old email alias of the mailbox :-)

    Any thoughts would be appreciated..

Leave a Comment