Exchange 2010 : Search and Delete Items by MessageClass [ EWS method ]

At Times There is requirement to search and delete items by MessageClass in one mailbox or in all the mailboxes. Exchange 2010 has limited set of options to achieve this type of task. I have listed some of the options below.

A. MRM 1.0 can be used to search messages based on Messageclass and take appropriate action .

B. MRM 2.0 ES Method can be used to search items for a specific messageClass and Tag’ em for appropriate action. Akash has a blogPost Detailing on How to apply Retention Tag ( recommended for personal Tag) using EWS Method.

C. Here is another method , using EWS Script you can Search for specific type of message class and Delete them. This is a sample script only .

Details on How to configure Impersonation Can be found here :
Exchange 2010:
Configuring Exchange Impersonation (Exchange Web Services)
https://msdn.microsoft.com/en-us/library/bb204095.aspx
Using Exchange Impersonation XML Request/Response
https://msdn.microsoft.com/en-us/library/bb204088.aspx

Using Impersonation in EWS Managed API
https://msdn.microsoft.com/en-us/library/dd633680(EXCHG.80).aspx

* Default script runs in Search mode only , to Delete the the items you need uncomment the the Delete statement [ # UNCOMMENT THE LINE BELOW TO DELETE THE ITEMS ] In The Script..

** This posting is provided "AS IS" with no warranties, and confers no rights.

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

#NOTE - Disclaimer
#By using the following materials or sample code you agree to be bound by the license terms below
#and the Microsoft Partner Program Agreement the terms of which are incorporated herein by this reference.
#These license terms are an agreement between Microsoft Corporation (or, if applicable based on where you
#are located, one of its affiliates) and you. Any materials (other than sample code) we provide to you
#are for your internal use only. Any sample code is provided for the purpose of illustration only and is
#not intended to be used in a production environment. We grant you a nonexclusive, royalty-free right to
#use and modify the sample code and to reproduce and distribute the object code form of the sample code,
#provided that you agree: (i) to not use Microsoft’s name, logo, or trademarks to market your software product
#in which the sample code is embedded; (ii) to include a valid copyright notice on your software product in
#which the sample code is embedded; (iii) to provide on behalf of and for the benefit of your subcontractors
#a disclaimer of warranties, exclusion of liability for indirect and consequential damages and a reasonable
#limitation of liability; and (iv) to indemnify, hold harmless, and defend Microsoft, its affiliates and
#suppliers from and against any third party claims or lawsuits, including attorneys’ fees, that arise or result
#from the use or distribution of the sample code.

# The script requires the EWS managed API, which can be downloaded here:
# https://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=c3342fb3-fbcc-4127-becf-872c746840e1
# This also requires PowerShell 2.0
# Make sure the Import-Module command below matches the DLL location of the API.
# This path must match the install location of the EWS managed API. Change it if needed.

[string]$info = "White" # Color for informational messages
[string]$warning = "Yellow" # Color for warning messages
[string]$error = "Red" # Color for error messages
[string]$LogFile = "C:\Temp\Log.txt" # Path of the Log File

function SearchFolders($MailboxName)
{
Write-host "Searching folders in Mailbox Name:" $MailboxName -foregroundcolor $info
Add-Content $LogFile ("Searching folders in Mailbox Name:" + $MailboxName)

    #Change the user to Impersonate
$service.ImpersonatedUserId = new-object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress,$MailboxName);

        #Number of Items to Get
$FpageSize =50
$FOffset = 0
$MoreFolders =$true

    while ($MoreFolders)
{

      #Setup the View to get a limited number of Items at one time
$folderView = new-object Microsoft.Exchange.WebServices.Data.FolderView($FpageSize,$FOffset,[Microsoft.Exchange.WebServices.Data.OffsetBasePoint]::Beginning)
$folderView.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Deep
$folderView.PropertySet = new-object Microsoft.Exchange.WebServices.Data.PropertySet(
[Microsoft.Exchange.WebServices.Data.BasePropertySet]::IdOnly,
[Microsoft.Exchange.WebServices.Data.FolderSchema]::DisplayName,
[Microsoft.Exchange.WebServices.Data.FolderSchema]::FolderClass);

        #Create the Search Filter.
$FoSearchFilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.FolderSchema]::FolderClass, "IPF.Note")

        $oFindFolders = $service.FindFolders([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$FoSearchFilter,$folderView)

foreach ($folder in $oFindFolders.Folders)
{

                Write-host "Begining to delete Items from folder:" $folder.DisplayName -foregroundcolor $info;
Add-Content $LogFile ("Begining to delete Items from folder:" + $folder.DisplayName);

            &{
DeleteItems($folder.Id.UniqueId)
Write-host "Deleted Items from folder:" $folder.DisplayName -foregroundcolor $info
Add-Content $LogFile ("Deleted Items from folder:" + $folder.DisplayName)

            }
trap [System.Exception]
{
$IsFailure = $true;
Write-host ("Error in DeleteItems: " + $_.Exception.Message) -foregroundcolor $error;
Add-Content $LogFile ("Error in DeleteItems: " + $_.Exception.Message);
Write-host "Failure in deleting Items from folder:" $folder.DisplayName -foregroundcolor $info
Add-Content $LogFile ("Failure in deleting Items from folder:" + $folder.DisplayName)

                continue;
}

        }
       

         if ($oFindFolders.MoreAvailable -eq $false)
{$MoreFolders = $false}

             if ($MoreFolders)
{$FOffset += $FpageSize}

}

    Write-host "Finished with Mailbox Name:" $MailboxName "Done!" -foregroundcolor $info
Write-host "-------------------------------------------------" -foregroundcolor $info

    Add-Content $LogFile ("Done!")
Add-Content $LogFile ("-------------------------------------------------" )   

    $service.ImpersonatedUserId = $null
}

function DeleteItems($fId)
{

        #Number of Items to Get
$pageSize =50
$Offset = 0
$MoreItems =$true
$ItemCount=0

    while ($MoreItems)
{
#Setup the View to get a limited number of Items at one time
$itemView = new-object Microsoft.Exchange.WebServices.Data.ItemView($pageSize,$Offset,[Microsoft.Exchange.WebServices.Data.OffsetBasePoint]::Beginning)
$itemView.Traversal = [Microsoft.Exchange.WebServices.Data.ItemTraversal]::Shallow
$itemView.PropertySet = new-object Microsoft.Exchange.WebServices.Data.PropertySet(
[Microsoft.Exchange.WebServices.Data.BasePropertySet]::IdOnly,
[Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::ItemClass,
[Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::Subject);

        #Create the Search Filter.

        $oSearchFilterEA1 = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::ItemClass, "IPM.Note")

       #Create the Search Filter.
$oSearchFilters = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollection(
[Microsoft.Exchange.WebServices.Data.LogicalOperator]::Or)

        $oSearchFilterEA1 = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::ItemClass, "IPM.Note.PamMessage")
$oSearchFilterEA2 = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::ItemClass, "IPM.Note.PamMessage.Forwarded")
$oSearchFilterEA3 = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::ItemClass, "IPM.Note.PamMessage.Replied")

        $oSearchFilters.add($oSearchFilterEA1)
$oSearchFilters.add($oSearchFilterEA2)
$oSearchFilters.add($oSearchFilterEA3)

$uniqueId = new-object Microsoft.Exchange.WebServices.Data.FolderId($fId);

        $oFindItems = $service.FindItems($uniqueId,$oSearchFilters,$itemView)
        

        Add-Content $LogFile ("No of Items Found:" + $oFindItems.Items.Count)

        foreach ($Item in $oFindItems.Items)
{
#uncomment the line below to delete the item
#$Item.Delete([Microsoft.Exchange.WebServices.Data.DeleteMode]::HardDelete)

        }
       

     if ($oFindItems.MoreAvailable -eq $false)
{$MoreItems = $false}

}

}

[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}

Import-Module -Name "C:\Program Files\Microsoft\Exchange\Web Services\1.1\Microsoft.Exchange.WebServices.dll"

$service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP1)

# Set the Credentials
$service.Credentials = new-object Microsoft.Exchange.WebServices.Data.WebCredentials("serviceAccount","PSSLab!","bhargava")

# Change the URL to point to your CAS server
$service.Url= new-object Uri("https://EX-2010-CAS/EWS/Exchange.asmx")

# Set $UseAutoDiscover to $true if you want to use AutoDiscover else it will use the URL set above
$UseAutoDiscover = $false

#Read data from the UserAccounts.txt
import-csv UserAccounts.txt | foreach-object {
$WindowsEmailAddress = $_.WindowsEmailAddress.ToString()

    if ($UseAutoDiscover -eq $true) {
Write-host "Autodiscovering.." -foregroundcolor $info
$UseAutoDiscover = $false
$service.AutodiscoverUrl($WindowsEmailAddress)
Write-host "Autodiscovering Done!" -foregroundcolor $info
Write-host "EWS URL set to :" $service.Url -foregroundcolor $info

    }
#To catch the Exceptions generated
trap [System.Exception]
{
Write-host ("Error: " + $_.Exception.Message) -foregroundcolor $error;
Add-Content $LogFile ("Error: " + $_.Exception.Message);
continue;
}
SearchFolders($WindowsEmailAddress)
}   

# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

-Manju