PowerShell: Script to recover all deleted items in a mailbox


UPDATE 6/2/2015: I’ve rewritten the script and have tested it against Exchange 2013 and Office 365.

We had a request recently for a sample PowerShell script that shows how to recover deleted items from and Exchange 2010 mailbox.  While not possible (as far as I am aware) using any standard Exchange cmdlets, it is certainly possible using the EWS Managed API.

The script has been written so that it can be automated quite easily.  The scenario that the script was originally requested for was to be able to run such a script against a large number of mailboxes where items had been mistakenly deleted.  The script parameters are:

RecoverDeletedItems [-Mailbox <string>]
                   [-Credentials <PSCredential>]
                   [-Username <string> -Password <string> [-Domain <string>]]
                   [-Impersonate <bool>]
                   [-EwsUrl <string>]
                   [-EWSManagedApiPath <string>]
                   [-IgnoreSSLCertificate]
                   [-AllowInsecureRedirection]

 -Mailbox : Mailbox SMTP email address
 -Credentials: can be used to pass credentials into the script (as obtained using Get-Credential)
 -Username : Username for the account being used to connect to EWS (if not specified, current user is assumed)
 -Password : Password for the specified user (required if username specified)
 -Domain : If specified, used for authentication (not required even if username specified)
 -Impersonate : Include this switch to use impersonation.
 -EwsUrl : Forces a particular EWS URl (otherwise autodiscover is used, which is recommended)
 -EWSManagedApiPath : Full path to the EWS Managed API (if not specified, default paths are searched – any version should work)
 -IgnoreSSLCertificate: If present, invalid (e.g. self-certified) certificates will be accepted
 -AllowInsecureRedirection: this affects autodiscover only

 

To run this against many mailboxes, you can used an impersonation account and then list all the mailboxes in a file that can be used by PowerShell to pipe the data into the script.  Script is attached to this post.

The deleted items will be restored to standard folders depending upon their item type.  When an item is deleted (sent to the dumpster), there is no information kept as to which folder the item was in before it was deleted, so (as far as I am aware) it is not possible to restore to the same folder.  Emails are restored to Inbox (unless they have the IsFromMe flag set, in which case they are restored to Sent Items), appointments to Calendar folder, and so on.

RecoverDeletedItems.ps1

Comments (26)

  1. Will Overstreet says:

    Is there a way to target the deleted on date in the recoverable items folder? We need to recover only calendar items and tasks that were automatically purged.

    1. Jan Vana says:

      yes, try to operate with sth like this
      if (($item.LastModifiedTime -ge $startDate) -and ($item.LastModifiedTime -le $endDate))

  2. Charles Huber says:

    Amen to Will Overstreet's request, just finally did this ourselves – inadvertently applied sp2ru4 without doing pre-requisite exclusions, deleted tons of calendar/tasks.  This script works GREAT (we rem'd out all but calendar/task lines) – but it would be nice to specify only the deleted-on dates if possible.  Anyone?

  3. Nick says:

    Great script, it covers a serious hole in the cmdlets. In fact I think a MASSIVE hole.

    What it can't do and I'd love to see, is to place recovered items into one specific folder, which could be either specified or created at runtime.

    Also the dumpster should be a parameter and those items should go into specific folders under the root of your recovery folder.

    Sounds like a big ask but there should be a Recover-DeletedItems cmdlet in the suite, it's missing!!

  4. Robert says:

    Hello.

    I am using exchange server 2013 to which I am connected via PowerShell.

    I am trying to execute your script but there are some errors that I can't handle with

    1. The Autodiscover service couldn't be located…    – I have added parameter to funciton $service.AutodiscoverUrl($Mailbox,{$true});

    After that

    2. The Autodiscover service couldn't be located – So I have put additional parameter to execute script -EwsUrl outlook.office365.com/…/exchange.asmx

    And now I dont know what to do next

    3. Unable to bind to RecoverableItemsDeletions folder

    Could you please give me some hints which will allow me to solve this issue ?

    Thanks in advance

    Best reagrds Robert

  5. Twon of An says:

    I couldn't get this script to work. At line 60, $FindResults never received any value and I got no errors whatsoever.

    I'll try troubleshooting, but if you've got any suggestions, they would be appreciated!

  6. Dempsey Dunkin says:

    This script is nice, but has some flaws.

    1. The offset needs to be the page size minus the number of recovered items or some items will be skipped. A variable should be created and set to 0 and incremented for each item that is recovered. Just after the $Offset+=$PageSize; the variable should be set back to 0.

    2. The isFromMe attribute is only True if the email is sent to the sender. As a work around, I bound to the items and checked the ReceivedBy attribute. It is null for Sent Items. Binding to an item is slows down the script.

    1. As Dempsey noted I’ve found that even with the new script the IsFromMe attribute check is not valid for detecting Sent Items, at least not in the way it is being used here. I’ve instead added Sender to the properties in the view and have added a check to see if the $item.Sender.Address is one of the users legacyExchangeDns (current or old from x500 proxy addresses).

  7. Will says:

    Would this work in exchange 2013, and how would you say only recover items in the archive mailbox?

  8. Øyvind says:

    Hello.

    I have tried your script, but get into some problems because we use a SBS 2011 server, and the autodiscover detect our external mail site instead of the internal exchange server.

    Have tried to put in the local server as EwsUrl, but get error message on mounting "Unable to bind to RecoverableItemsDeletions folder"

    Any help would be much appreciated…..

    1. F. Albers says:

      Hello,

      did you solve the problem with the message ‘Failed to open Recoverable Items folder’?

      Best regards,
      Florian

  9. Øyvind Johannessen says:

    I have tried to use your script but ran into a problem.

    We are running a SBS 2011 server with an external mail server where we use pop3 connection down to our exchange server.

    When I try to run the script it start with autodiscover, and find the external server instead of the internal.

    Have tried to set the EwsUrl to the local server, but then I'm get this error message "Unable to bind to RecoverableItemsDeletions folder"

    Any idea how to solve?

    I have a user that have deleted the complete inbox content…..

  10. Michael McNally says:

    Anyone have an answer to the first question posted? I tried :

    Search-Mailbox -identity mailboxuser -SearchDumpsterOnly -SearchQuery{}

    But deletion date is not available for SearchQuery. Being able to recover all items deleted on an exact date would be ideal for cases when a users deletes a very large folder and mixes that in with a years worth of gunk in the Recoverable items.

  11. Vikram Solanki says:

    How do you verify if recoverable items are available in INBOX? I ran the script as stated and also saw that it is processing..

    Processing IPM.Schedule.Meeting.Request :  AAMkAGE2YjgzODg2LTc5MzAtNGNiZi05YzgzLTYyY2M1YTllYTQ5NQBGAAAAAABcIGjUEc7sQ44Mr

    k9GjeKFBwDXEjECeVbOTq24F4Qav6S/AAAAmUa9AADAc8TdSKLkSImNX7FJGpNhAAAmW/5qAAA=

    Processing IPM.Schedule.Meeting.Request :  AAMkAGE2YjgzODg2LTc5MzAtNGNiZi05YzgzLTYyY2M1YTllYTQ5NQBGAAAAAABcIGjUEc7sQ44Mr

    k9GjeKFBwDXEjECeVbOTq24F4Qav6S/AAAAmUa9AADAc8TdSKLkSImNX7FJGpNhAAAmW/5nAAA=

    But when I do folder item count search

    $folders = 'RecoverableItems','Inbox' | %{get-mailboxfolderstatistics -identity $userid -FolderScope $_ | select-object Identity,itemsinfolder,@{Name="FolderSize MB";expression={$_.folderSize.toMB()}}};$folders

    I see the same item count as I had it before.. also when I do export-mailbox export all the recoverable items to pst and try to open I still find those messages to be there in the pst.. then my question here is.. is the $item.move method working as we expected?

    Is there an other way of doing so?

  12. Greg Tate says:

    I know this is a bit dated but thought I'd reply to Michael for anyone who comes across this. The cmdlet posted is very close, its just in need of search query definition KQL syntax and where to store the items. I would expect something like this would meet the requirement to retrieve items on a specific day. This assumes you have the necessary exchange permissions.

    First Set Query to variable to simplify working with the search cmdlet

    $Query = "Received:01/01/2015"

    Search-Mailbox -Identity <Mailbox> -SearchQuery $Query -TargetMailbox <Different Mailbox> -TargetFolder <Folder To Place Results> -LogLevel Full -SearchDumpsterOnly

    Here are two great references to help tweak your query.

    technet.microsoft.com/…/dn774955%28v=exchg.150%29.aspx

    msdn.microsoft.com/…/ee558911.aspx

  13. Lee says:

    I tried this script in an Exchange 2010 environment. It did SOMETHING to the deleted items (using the GUI I can see the emails have disappeared from 'recover deleted items'), but the emails were not recovered. I did a search of the mailbox for several of the emails that were in 'recover deleted items', with no results found.

  14. Bill G. Wright says:

    Tried the script, but no luck 🙁 Not working for Ex2007. Can you recommend stellar Ex. recover software for recover deleted mailbox items. I've found this tool through technet forum, and seems it does the same job. http://www.stellarservertools.com/recover-exchange-mailbox.php

    I'm working on an old server. Is it worth to have this tool? Can you please create a powershell for Exchange 2007 as it is urgent!!! Do you have any other reference?

    Any help will be appreciated!

    Bill,

  15. Martin says:

    Nice script, but please can you provide an example for the EWS api path ? Many thank

    Martin

  16. You don't need to specify the path assuming you've installed it to the default folder.  If not, just specify the full path to the Microsoft.Exchange.WebServices.dll file on your system [include the filename]).

  17. Ethan Wilson says:

    Hey David. I'm trying to edit the file so it goes into a different folder than the default.

    "IPM.Note*"

    {

    # Message; need to determine if sent or not

    Write-Verbose "Message is from me: $($Item.IsFromMe)"

    if ($Item.IsFromMe -eq $true)

    {

    # This is a sent message

    [void]$Item.Move([Microsoft.Exchange.WebServices.Data.FolderId]::Restore2016)

    }

    else

    {

    # This is a received message

    [void]$Item.Move([Microsoft.Exchange.WebServices.Data.FolderId]::Restore2016)

    }

    }

    I get:

    Exception calling "Move" with "1" argument(s): "Value cannot be null.

    Parameter name: destinationFolderId"

    At C:PSScriptsRecoverDeletedItemsM.ps1:258 char:7

    + …             [void]$Item.Move([Microsoft.Exchange.WebServices.Data.Fol …

    +                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

       + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

       + FullyQualifiedErrorId : ArgumentNullException

    It's a new folder in the inboxes named Restore2016

    So I guess technically it's InboxRestore2016

    Since that's not a well Known folder I didn't want to keep Microsoft.Exchange.WebServices.Data.WellKnownFolderName

    Since that didn't seem right. Any help?

    I can't use your new version of the script because it keeps failing on me. So this older version works great, but I can't refill user's inboxes.

  18. Ethan Wilson says:

    Now I just need to edit the script so it doesn't look in RecoverableDeletedItems Folder but a different folder to sort what I recovered with your other script!

  19. T_e_x says:

    Script works great, but I am having issues getting the CSV Input to work.  I assume its looking for the SMTP address in the csv file, any specific formatting needed?

  20. This totally saved my butt, thanks!

    1. I should add that I used this with Office 365 using the following command:
      RecoverDeletedItems -Mailbox problemaccount@domain.com -Credentials (Get-Credential) -AllowInsecureRedirection

  21. Baptiste ETOURNEAU says:

    Hi, is there a possible to recover items in a selected folder ? Something like RecoverItem.

    Best Regards,

    1. Baptiste ETOURNEAU says:

      Aditionnal question : Is it possible to restore mail deleted from the Archive online folder ?

Skip to main content