Remove Specific E-Mail or E-Mails From All Exchange Mailboxes

Have you ever been asked to remove an unwanted e-mail from all mailboxes in your Exchange environment? Did someone send out an e-mail to the whole company and then tried to retract it? Or perhaps a new virus made its way to all mailboxes by way of an attachment. This scenario tends to be brought to my plate quite often so I will walk you through the steps of scanning all mailboxes and removing an unwanted e-mail. There are different strategies to accomplish this but the following should work for your needs.

All highlighted examples use a ForEach loop with the mailbox databases as large environments will often run out of memory retrieving all the mailboxes. This assumes you have less than 1000 mailboxes per database. The power of this command revolves around the Search Query and being able to include only the e-mails that fit your criteria for action. All examples assume you are connected to the Exchange Management Shell.

Step #1: The first thing that is required is a user account with the proper access role to search and delete. I use a secure service account to perform these tasks so that they are not being completed by my own account. The two roles that are required are Mailbox Import Export and Mailbox Search. By default, the Mailbox Import Export management role isn’t included in any of the built-in role groups. As a result this shows you how to create a role group with the required 2 roles.

Step #2a: At this point we can either search for an e-mail and log the results, search and delete the results, or both. This example searches all mailboxes and deletes the e-mail according to your search query. The search query can be adjusted according to your needs and more information can be found on the syntax here.

Step #2b: The following will simply log the results of your search in case you want to test the search and delete first.

Step #2c: The following searches all mailboxes and both removes the e-mail and logs the results. I changed the Search Query to highlight the searching of an attachment named ‘ILoveYou*’. This will look for any attachment with ILoveYou at the prefix of the file name.

Step #2d: The following will delete all e-mails matching your search query but will prompt you before each deletion takes place. This is accomplished by removing the -Force from the Search-Mailbox command.

Step #2e: The following highlights a simpler method for environments with a smaller footprint of mailboxes without the need to loop through the databases. By default the result size for the Get-Mailbox command is 1000 mailboxes. Setting -ResultSize to Unlimited allows us to search all mailboxes.

Step #2f: The following highlights utilizing server names instead of the mailboxes as per request. I prefer to use mailbox databases since they usually contain less users. If servers work better in your environment you could use the following method:

As always, leave a comment with your scenario and I will update the blog post with the solution.

Print Friendly, PDF & Email

12 Comments

  1. Dustin

    Excellent information! thanks! What about larger environments where multiple mailbox servers are used, can we recurse each server too, by looping it with get-mailboxserver?

  2. Pingback: Delete Specific E-Mail or E-Mails From All Exchange Mailboxes » PowerShell.org

  3. Pingback: Exchange 2010 Searching Mailbox's

  4. Joshua McAlister

    For my usage, we needed to quickly find which mailboxes received an e-mail from a sender recently, so that it may be removed. Searching 7000+ mailboxes takes way too much time, so we use Get-MessageTrackingLogs.

    THIS ONLY WORKS WHEN THE INFORMATION IS STILL IN THE MESSAGE TRACKING LOGS

    #

    # Enable Exchange Management Powershell from standard PowerShell
    Add-PSSnapin Microsoft.Exchange.Management.PowerShell.SnapIn;

    $mySender = “malware@contoso.com”

    # Fast Search Recent E-mails using the Message Tracking Log
    $myMailboxServers = Get-MailboxServer
    ForEach ($Server in $myMailboxServers)
    {
    $Server = $Server.Name
    $mySearchResults = Get-MessageTrackingLog -Server $Server -Sender $mySender
    # Include the -MessageSubject in the line above if known and you want to filter by Subject:
    # $mySubject = “secure document”
    # $mySearchResults = Get-MessageTrackingLog -Server $Server -MessageSubject $mySubject
    # Optionally filter by Event: ( -EventId “RECEIVE” )
    $mySearchResults
    }

    Then the $mySearchResults can be used to search only those mailboxes.

    Good Luck!
    Josh

  5. Patrick Smythe

    How can this be done by Message ID instead of subject? Search and destroy by subject also gets communications to end users which needs to remain, and since we don’t always know if Security sends out the notices with non-matching subject lines, this approach does not work for us. Our Security department has a use case for search/delete via Message ID specifically, however I’m not finding that this works with the search-mailbox cmdlet.

Leave a Reply

Your email address will not be published. Required fields are marked *