Powershell Script to Delete Exchange Mailboxes in Mass

By Request: How to delete a large number of mailboxes at once.

First, and I can not stress this enough, this script has the potential to delete production data, namely user and Exchange mailboxes. Please carefully consider the impact of this script before you use it. Make sure you have good backups of your User Accounts and Exchange Mailboxes before use. If it doubt, test with a single account before hand and/or use the -whatif flag. (More about this below) Ok now then, on to the good stuff.

There are a few ways you might approach the task of deleting mailboxes. Much of that comes in the form of how you come up with the list of mailboxes and/or users to delete.

This example assumes the following approach:

  • You are creating a text file with a list of accounts to remove.
  • You want to delete both the user and the mailbox.

So then to create a list of user and their mailboxes you want to delete, simply place a list of users in a text file one user per line. You might fetch the list using a Get-QADuser or Get-Mailbox as a filter, more on this later.

Example text file:

jsmith
msmith
jlittle

etc

Call the file MailboxesToDelete.txt and we’ll assume its on the C:\ drive.  Then create a script to run, in this example I’ll call it Delete_Mailboxes.ps1

#Add Exchanage snapin
add-pssnapin Microsoft.Exchange.Management.PowerShell.Admin

#Get list of mailboxes to delete
$users=Get-Content C:\MailboxesToDelete.txt

#For Loop to delete them
foreach ($user in $users)
{
#Print to screen user mailbox to delete
$user
#Delete AD user and Mailbox
Remove-Mailbox -Identity $user -Permanent $true -whatif

#Remove the -whatif if you want to really delete some users.
}

That is pretty much it.

You should then be able to type [PS]C:> Delete_Mailboxes.ps1 and delete users and their mailboxes based on the text file.

You might also, assuming you have some search criteria, use the Get-QADuser or Get-Mailbox command to filter out the list of users. Say all of those in a specific OU and turn this into a single one liner.

Example:

Get-QADUser -SearchRoot 'OU=INTERNATIONAL OFFICE USERS,DC=contoso,DC=com' | Remove-Mailbox -Identity $user -Permanent $true

Or you could use my script and simply Get-QADUser -SearchRoot ‘OU=INTERNATIONAL OFFICE USERS,DC=contoso,DC=com’ >> C:\MailboxesToDelete.txt and then run the above script. Again there are many ways to approach the actual search/list creation. This is just a few ways you might do it.

Be warned:
The -Permanent $true will not only delete the mailbox, it will also delete the user. If you don’t want the user account deleted and just the mailbox just remove -Permanet from the above or set it to $false.

If you just want to test at the end of the Remove-Mailbox statement put a -whatif at the end of the line.

Example:
Remove-Mailbox -id jsmith -whatif

I added “-whatif” to the script to hopefully save someone some pain while testing.  Remove it only when you are ready to actually delete some data.

Please reference: Technet if you have questions about the Remove-Mailbox command, it is a delete command so use with care.


Advertisements

, , ,

  1. #1 by Sleek Suzy on May 4, 2012 - 12:04 pm

    OK, I still get errors using your 1 liner above:

    PS C:\> Get-ADUser -Filter * -SearchBase “OU=IT,OU=Employees,DC=OBERONMEDIA,DC=LOCAL”

    Get-ADUser : Directory object not found
    At line:1 char:11+ Get-ADUser <<< Get-ADUser -Filter * -SearchBase “OU=IT,DC=OBERONMEDIA,DC=LOCAL”

    But that gives every object, including service accounts that I don’t want to delete.

    When I try it my way with get-mailbox instead of get-aduser:

    [PS] C:\>Get-Mailbox -Database qt-mbx-cls.oberonmedia.local\china | select Alias

    Alias
    —–
    feng.hao
    hrch
    crystal.yan
    shi.songhua
    gong.lida
    natasha.zhu
    li.min

    That part works… but then when I try with the remove-mailbox -WhatIf:

    [PS] C:\>$mb = Get-Mailbox -Database qt-mbx-cls.oberonmedia.local\china | select
    Alias | Remove-Mailbox -Identity Alias -Permanent $true -Confirm:$false -whatif

    Remove-Mailbox : The input object cannot be bound to any parameters for the com
    mand either because the command does not take pipeline input or the input and i
    ts properties do not match any of the parameters that take pipeline input.
    At line:1 char:95
    + $mb = Get-Mailbox -Database qt-mbx-cls.oberonmedia.local\china | select Alias
    | Remove-Mailbox <<<< -Identity Alias -Permanent $true -Confirm:$false -whati
    f
    + CategoryInfo : InvalidArgument: (@{Alias=olive.fan}:PSObject) [
    Remove-Mailbox], ParameterBindingException
    + FullyQualifiedErrorId : InputObjectNotBound,Microsoft.Exchange.Managemen
    t.RecipientTasks.RemoveMailbox

    Although, I get that error repeatedly for the correct number of mailboxes (and you can see see the user names in the errors returned)…

    I is Exchange 2007 on Server 2003 R2. I am using PowerShell v 2.0

    We have 157 employees, and 1388 mailboxes (we closed down over a half dozen global offices in the past year).

    Any thoughts?

    • #2 by Robert on May 4, 2012 - 6:31 pm

      Do you have some common way to distinguish the service account? LIke putting a label in the description field and calling them “Service Accounts”? We can change the search filter to ignore them if that or something similar is true. I do that where I work for that exact reason, that and I have service accounts in their own OU. You just need a way to lump them together with a attribute we can search and filter on. So that would be one method.

      What method are you using to determine which accounts to delete? IE, are they disabled or is there something else you can filter on? Or do you have a list, or are they contained in a OU?

      Ok so back to what you have tried to do with the one liner.

      I think I see why the Get-QADUser with Remove-Mailbox didn’t work as well. Give me a little more detail and I can likely create a filter for you or suggest one anyway.

    • #3 by Robert on May 4, 2012 - 6:43 pm

      PS C:\> Get-ADUser -Filter * -SearchBase “OU=IT,OU=Employees,DC=OBERONMEDIA,DC=LOCAL”

      Get-ADUser : Directory object not found
      At line:1 char:11+ Get-ADUser <<< Get-ADUser -Filter * -SearchBase “OU=IT,DC=OBERONMEDIA,DC=LOCAL”

      Get-ADUser should be Get-QADuser
      -SearchBase should be -SearchRoot

      Hope that helps!

      • #4 by Robert on May 4, 2012 - 6:44 pm

        Also with Get-QADUser you need to pipe and select LogonName in order for it to work with Remove-Mailbox.

  2. #5 by Sleek Suzy on May 4, 2012 - 12:06 pm

    Weird, it truncated my post, but in the middle.

    I get no errors with Get-ADUser -Filter * -SearchBase “OU=IT,DC=OBERONMEDIA,DC=LOCAL

    But that gives every object in the OU, including service accounts that I don’t want to delete.

    • #6 by Robert on May 4, 2012 - 6:41 pm

      Shouldn’t it be -SearchRoot and not Base?

      We need to have a common item to sort out undesirables. Something like:

      Get-QADUser -SearchRoot “OU=IT,DC=OBERONMEDIA,DC=LOCAL” | where {($_.AccountIsDisabled -eq $true)} | select LogonName

      So this would give you a list of all accounts in that OU that were disabled. You should be able to pipe this onto Remove-Mailboxes and it work. Assuming you can use disabled accounts as a search filter.

      Hope that helps?

      • #7 by Robert on May 4, 2012 - 6:54 pm

        One other thing, testing here: Do this | ft -hidetableheaders at the end of the above Get-QADUser string to hide that table header.

  3. #8 by Sleek Suzy on May 4, 2012 - 2:53 pm

    All right, got it working with the text file import. Thanks!

    Still had a problem with white space in the text file I had to delete manually. Is that because I choose to filter on alias, or is there a switch I am missing with Out-File? The mailbox DB I grabbed the aliases from had only 20 users, but we have over 20 mailbox DBs and many have hundreds of users. Would not like to have to manually delete white space in each text file. Thanks again!

    • #9 by Robert on May 6, 2012 - 5:19 pm

      What are you using as your search filter? Give me an example, I typically use >> rather than Out-File and can’t think of a instance I’ve run into a white space issue but I can’t say for sure without seeing your search syntax.

  4. #10 by jimpowershell on May 9, 2012 - 1:35 am

    Nice post, useful to me at work – I’ll check it out! As sleek Suzy points out, white space in the txt file where the data is pulled from is a problem I’ve encounted – empty lines cause problems.

    • #11 by Robert on May 9, 2012 - 9:49 am

      I can see where both empty lines and white spaces could cause problems. This could be overcome in different ways depending on the data and what you are doing with it. Using a Search and dumping that into a text file, and then trimming white spaces and lines from the text file might be one way.

      If you are just trying to delete leading and ending white spaces you might use the .trim() method something like get-qaduser | Foreach {$_.LogonName.Trim()} The foreach { $_.Attribute.trim()} will work for many searches but if you had a white space in the middle of a value it wouldn’t help you. IE ” John Smith ” would become “John Smith”.

      So depending on what you are trying to accomplish that might or might not work for you. Happy to help if you can throw a example at me.

  5. #12 by Kittu on March 18, 2013 - 11:08 pm

    Thank you.. I made slight modifications (My motto is to disable the mailbox not removing the AD account) to this and it went well

    #Get list of mailboxes to delete
    $users=Get-Content C:\MailboxesToDelete.txt

    #For Loop to delete them
    foreach ($user in $users)
    {
    #Print to screen user mailbox to delete
    $user
    #Disable User Mailbox
    Disable-Mailbox -Identity $user -confirm:$false
    }

  6. #13 by Daniel on May 26, 2013 - 6:50 am

    Hi,
    Get-mailbox -OrganizationalUnit “ou=OU,dc=domain” | select Alias | remove-mailbox -Identity Alias -Permanent $true -Whatif

    Gives:

    + CategoryInfo : InvalidArgument: (@{Alias=AliasName}:PSObject) [
    Remove-Mailbox], ParameterBindingException
    + FullyQualifiedErrorId : InputObjectNotBound, Remove-Mailbox

    Without the remove-mailbox it works
    Via the file it works (after removing whitespaces and empty lines) but I wonder why the one-liner is not working

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: