Have you ever had the situation where you had to quickly remove an email from all mailboxes in an organisation? Maybe it was an accidental email by an assistant to the whole company, or worse, inappropriate content sent by a disgruntled employee? I have not yet been put in this position but i wanted to be prepared for the gloomy day. This will help you if you are in the same position.
Well here are some steps that i have tested in an Exchange 2010 SP1 environment.
Note: there is a different method for Exchange 2007/2010 RTM versions that has not been documented here.
Prerequisites
Make sure the account running the PS command has the appropriate permissions; you need to specifically have access to the New-MailboxImportRequest cmdlet. By default, no-one has permissions to the cmdlet. If you don’t have the correct permissions you will get an error “The term ‘New-MailboxImportRequest’ is not recognized as the name of a cmdlet”.
To add the permission follow these simple steps:
- Create a Universal Security group in ADUC.
- Run the following command
[code language=”vb”]New-ManagementRoleAssignment -Name "Import Export Mailbox Admins" -SecurityGroup "*SecurityGroupName*" -Role "Mailbox Import Export"[/code]
Notes:
- Change *SecurityGroupName* in the above cmdlet to the actual name of your group
- The group needs to be a universal security group for the role assignment to work
- The New-MailboxImportRequest cmdlet only works with UNC shares, not local drives
- The “Exchange Trusted Subsystem” group should be granted read/write permission to the shared location
Use the Shell to search for messages and log the search results
The task uses a powerful/dangerous cmdlet that can do nasty things if incorrect, so i highly recommend running a test beforehand. Below is an example to test what you are going to delete. It will run a scan (based on what and where you searched) and give you a report of the output, along with the locations of the items and where they are located.
[code language=”ps”]Get-Mailbox -Server "*Server*" | Search-Mailbox -SearchQuery ‘Subject:"*Subject*" and Body:"*Body*"’ -targetmailbox "*SearchMailbox*" -targetfolder "*SearchFolder*" -logonly -loglevel full[/code]
The above code searches a particular server (and all the databases on it) for a query that meets a particular subject and body. It then sends the logs to the particular mailbox and folder.
Preview of the output:
Notes:
- the output mailbox will not be included as part of the search
- the search can be changed to search more detailed searches – refer to the technet article Understanding Multi-Mailbox Search – http://technet.microsoft.com/en-us/library/dd335072.aspx
Use the Shell to search for and delete messages
All that is left to do now is run the command that will commit the process. There are many variations in what you can do so i will include several examples to suit the most common scenarios:
- Delete all emails that meet the search query
[code language=”ps”]Get-Mailbox -Server "*Server*" | Search-Mailbox -SearchQuery ‘Subject:"*Subject*" and Body:"*Body*"’ -deletecontent[/code] - Copy all emails to a single mailbox, then delete the emails[code language=”ps”]Get-Mailbox -Server "*Server*" | Search-Mailbox -SearchQuery ‘Subject:"*Subject*" and Body:"*Body*"’ -targetmailbox "*SearchMailbox*" -targetfolder "*SearchFolder*" -loglevel full -deletecontent[/code]
Resources that i helped me get here
- Need to delete email from all users mailboxes – http://www.experts-exchange.com/Software/Server_Software/Email_Servers/Exchange/Q_26939299.html
- Search-Mailbox – http://technet.microsoft.com/en-us/library/dd298173.aspx
- Use Mailbox Search to Delete Messages – http://technet.microsoft.com/en-us/library/ff459253.aspx
- Export and Import mailboxes in Exchange 2010 SP1 – http://www.zerohoursleep.com/2010/11/export-and-import-mailboxes-in-exchange-2010-sp1/
I have also used Exchange 2010 version which contained attachments with mailbox database. I tried to remove selective attachment from Exchange server mailbox but I failed. Then I found a better solution for remove attachment from exchange mailbox database by this blog https://www.systoolsgroup.com/updates/remove-attachments-exchange-mailbox-database/ which was really useful.
Thanks Sandra, apologies i missed this. Thanks for the link. 🙂
this is not a solution, it’s just for exporting, i guess the intention is to gain visits for publicity
This is a solution. The -deletecontent flag is what does the work of deleting. All the other steps help make sure that is what you want to do.
Note there are more reliable methods to do this in Exchange Online.
Thank you for your post! I had a user that sent 37 MB of pictures out to 200 users! 7 GB of space occupied by pictures! Your post allowed me to get rid of the email(s).
I’m glad it worked for you. 🙂
Thanks Ivan – great post as usual! I often read your blog, always good info, well detailed.
Thanks Enrico! Lets hope i get some time to put some more articles online. I feel it has been a little neglected.
(Requests on articles welcome)
Hi all,
I could really use some help with a couple of commands to help me search and destroy specific emails. I need a way to get at the emails.In the past I have been able to create the syntax – but I seem to be hitting a wall. In short order I would like help in getting the correct exchange 2010 syntax for the following lines:
Thanks in Advance
Lance
Export-Mailbox -identity user -StartDate ’01/01/2000′ -EndDate ’08/10/2013′ -SenderKeywords “[email protected]” -DeleteContent -allowDuplicates -Confirm:$false
Hi Lance,
Im not sure if you have actually read my blog post. The command Export-Mailbox was used in Exchange 2007, and possibly Exchange 2010 RTM.
If you are using Exchange 2010 SP1 or higher, the command should be similar to the following:
Get-Mailbox -Server “*Server*” | Search-Mailbox -SearchQuery ‘Subject:”*Subject*” and Body:”*Body*”‘ -targetmailbox “*SearchMailbox*” -targetfolder “*SearchFolder*” -loglevel full -deletecontent
Now there are additional -SearchQuery parameters that allow you to search for the sender and recipient, as well as date ranges.
Hope that helps,
Ivan
I really want to search a mailbox, forward all messages in that mailbox to an external email and then delete all emails in the mailbox. Any tips? I can’t just forward.
Hi Jason,
No there is no way to just forward it. You will need to do it in a couple of stages using PowerShell.
Ivan
Can you summarize those stages? Thanks
Thanks Ivan, what if you want to delete messages from a specific date range, is that possible?
Hi Lance,
Yes this is absolutely possible. Note there are differences between EX2010 and EX2013 commands on doing this. I will write a separate post with many examples including date rages soon. Keep an eye out (hopefully in the next week or two).
Cheers,
Ivan
I wanted to drop in some commands that I use daily to do this type of thing..to search for attachment type, subject and from.
Get-Mailbox -ResultSize Unlimited | Search-Mailbox -SearchQuery ‘Attachment:”filename.zip”‘ -TargetMailbox UserName -TargetFolder Discovery -LogOnly -LogLevel Full
Get-Mailbox -ResultSize Unlimited | Search-Mailbox -SearchQuery ‘Subject:”Vacation Trip (Help Needed)”‘ -TargetMailbox UserName -TargetFolder Discovery -LogOnly -LogLevel Full
Get-Mailbox -ResultSize Unlimited | Search-Mailbox -SearchQuery ‘From:”[email protected]”‘ -TargetMailbox UserName -TargetFolder Discovery -LogOnly -LogLevel Full
Few specifics:
– Username – replace with your login\name for Exchange
– Discovery – This makes a folder and drops everything in it on MY Inbox
– LogOnly – This scans for it only. I then go into the Discovery folder and have a .zip file with the results. I open it to make sure I have the results I want and THEN change LogOnly to DeleteContent. I want to be 100% sure each time I mass delete that the info is what I expect. Its worth it to wait a few minutes to scan then delete then deal with a mass delete catastrophe.
WARNING: In my experience using wildcards * is very dangerous and one wrong typo could mass delete emails. I always run the scan first, then delete. We have about 700 users and each scan takes a few minutes.
Hi Keith,
Thanks for this – i wil be creating a new post with many variations for others to use – ill include the ones you have created there as well (once i get around to writing it).
Cheers,
Ivan
Thanks Ivan, this has helped lots.
Is it possible to search for multiple subject lines? I’ve tried subject:”bah” -and “blahblah”‘ which didn’t work and also without the – in front of the -and but no luck.
Hi Mark,
Your mentioned search query would not work, and based on the comments I have received I will write a separate article with many examples to help explain Advanced Query Syntax (AQS). For now try the following:
Search-Mailbox -SearchQuery ‘(subject:”the sky is blue”) OR (subject:”they sky is red”)’
This would return you all messages with either of the two subjects lines. If you want to search subject lines with specific words you could try the following:
Search-Mailbox -SearchQuery ‘subject:(sky blue red)’
This will return all emails that contain any of the words. So your search results may be higher than the first string.
Cheers,
Ivan
is there a way to do this but use a message ID instead of Subject and body strings?
Hi Jason,
Sorry it is not possible to use MessageID in the search parameters. The list of search criteria you can use is:
More information can be found here: http://technet.microsoft.com/en-us/library/bb232132(v=exchg.141).aspx
If you are wanting to use a messageID as a reference point, then you can easily include a search to include FROM, SENT, SUBJECT and it will pick up the email.
Cheers,
Ivan
Hello Ivan,
I was wondering if one of the -SearchQuery parameters could be MessageID? Ive used this procedure but found it would be easier after identifying the messages to delete it from all datatbases via MessageID.
Hi Bill,
I have never done it this way but if memory serves me correctly you can. Ill look into it and let you know.
Cheers,
Ivan
can the -SearchQuery parameter search on multiple properties? Like can I search for an email with a specific subject received or sent on a certain date or date range at the same time. So far I’ve not figured out how to do that
Hi Johnathan,
Yes it can do that. You can have very granular queries that include sender, recipient, subject, body, attachment etc. The trick is to get the syntax right. I will put some more examples on the search queries that you might be interested in and post them up in the coming days.
Lastly sorry for the very long delay in replying – is very rude of me and i apologise.
Ivan
Is it working in Exchange 2010 without service pack?
Hi Mik,
I suspect it may not work with Exchange 2010 without SP1. To validate it, try to use it.
Also make sure the following cmdlets are available in PowerShell:
– Search-Mailbox
– New-ManagementRoleAssignment
Please reply back if it works. Would love to know.
Cheers,
Ivan
I also had the ‘The term ‘Search-Mailbox’ is not recognized as the name of a cmdlet, function, script file, or operable program’ error.
I found the solution on Stack Overflow, but will summarize here:
This problem happens because your account is not a member of the Discovery Management role. Since your account does not have permission to perform searches, Powershell does not import the Search-Mailbox cmdlet.
In Active Directory, add the account to the Discovery Management group, then close and restart your Powershell session.
Hi KC, thanks for that. I will update the article to include that useful information.
Cheers,
Ivan
Very awesome. Saved me big time. Thank you for this!!!
Glad it worked for you!
This works great, thank you!
How can you count how many mailboxes have that specific message?
Hi Val, it produces a csv when in logging mode, which you can easily then count the number of rows of the csv or similar. Let me know if you get stuck.
I also updated the PowerShell script to display in colour coding – may help understand it better for users learning PowerShell.
Cheers,
Ivan
What am i doing Wrong??
[PS] C:\Windows\system32>Get-Mailbox -Server “TITAN” -ResultSize unlimited | Search-Mailbox -SearchQuery ‘subject:”Re: [#63] IT NOTIFICATION :- Network Outage – 21-22 December 2012″‘ -DeleteContent
The term ‘Search-Mailbox’ is not recognized as the name of a cmdlet, function, script file, or operable program. 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:67
+ Get-Mailbox -Server “TITAN” -ResultSize unlimited | Search-Mailbox <<<< -SearchQuery 'subject:"Re: [#63] IT NOTIFICA
TION :- Network Outage – 21-22 December 2012"' -DeleteContent
+ CategoryInfo : ObjectNotFound: (Search-Mailbox:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
What version of Exchange are you running, and what machine are you running the script from?
Edward …
you are missing the ending single quote character.
Thanks – I missed this.
Ivan
I received the same error as Susan. the commands I had run was the create new group, give them permissions, ran the create log, which all worked as expected. Then when I ran
Get-Mailbox -Server “Mail” -resultsize unlimited | Search-Mailbox -SearchQuery ‘Subject:”Meeting-Confidential” -targetmailbox “edward” -targetfolder “inbox” -loglevel full -DeleteContent
I got the error
The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input.
+ CategoryInfo : InvalidArgument: (.:PSObject) [Search-Mailbox], ParameterBindingException
+ FullyQualifiedErrorId : InputObjectNotBound,Search-Mailbox
for every mailbox in the organization.
Hi Edward,
Its hard to diagnose why it doesn’t work from my end so I suggest you try the following:
– Create new mailbox and add some emails to it. Re-Run the script above but target the above mailbox to make sure the searching works. eg:
Get-Mailbox -identity ‘testuser’ | Search-Mailbox -SearchQuery ‘Subject:”*” -targetmailbox “edward” -targetfolder “inbox” -loglevel full
The above should report EVERYTHING in that mailbox into your mailbox.
-Test the targetfolder to be other than “inbox”
I have never tried to go directly to the inbox – I always used a descriptive name.
-Exchange – what version are you running? I have only tested this (from memory) on Exchange 2010 SP1 Update Rollup 2, and Exchange 2010 SP2.
Let me know how that goes, and if its still a prob ill look into it some more for you.
Cheers,
Ivan
Thanks Ivan, this helped us get rid of an email a naughty student sent around school. We had to enable the command first, we referenced http ://www .techieshelp .com/delete-mail- from-multiple-mailboxes/ for anyone who has the same issue
Hi Ben,
Not sure if you noticed but my article specifies how to enable the command as well. Its the first bit of code in the article under Prerequisites.
The difference between the two articles is that I recommend using AD security groups to manage the permissions. I feel it gives you more flexibility and uniformity.
Either way, hope the article was useful for you.
Cheers,
Ivan
Found this post after a Google search. Very clear and sorted the issue we had after a user sent a rather large email to over 400 staff!
Very good write up i also found it useful to use the attachment command as well?
Get-Mailbox -Server “ws-vafb-mbx01” | Search-Mailbox -SearchQuery ‘attachment:”*FileName.pdf*”‘ -targetmailbox “MailBox.Name” -targetfolder “FolderName” -loglevel full -deletecontent
Hi Markus,
Thanks for the tip. That will come in handy!
Ivan
Very good article. I will be experiencing a few of these
issues as well..
Very cool. And a little scary too. Thanks!
I used this command to limit the scope for a trial run:
Get-Mailbox -Database “DatabaseName” | Search-Mailbox -SearchQuery ‘Subject:”*Subject*”‘ -targetmailbox “*SearchMailbox*” -targetfolder “*SearchFolder*” -loglevel full -deletecontent
Worked great.
This is exactly what we need! Unfortunately, only the search and log command works. When running the commands to delete all emails or copy all emails to mailbox then delete, I get the error “The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input.
+ CategoryInfo : InvalidArgument: (.:PSObject) [Search-Mailbox], ParameterBindingException
+ FullyQualifiedErrorId : InputObjectNotBound,Search-Mailbox”
Help!
Thanks in advance 🙂
Thanks Susan,
What command are you running?
Awesome tip, thank you. Easy to use. Finally got rid of a SPAM email that was driving me crazy (as all of the staff were forwarding it to me).