Another example of using EWS Managed API 1.1 from PowerShell (Impersonation, SearchFilter, FindItems, Paging)

In this case the customer wanted to know the Item count, size of all the item in the Inbox that were older than 5 years. As usual, the requirement was to run the script against multiple mailboxes. I could have easily written this in C# in no time but preferred to do this in PowerShell as:

  • I would not have to compile the code every time I make change
  • It would also be easier for the Administrator who don’t have access to Development Environment
  • Getting the list of mailboxes is easy in Exchange PowerShell

The downside is that you do not get the IntelliSense that you get with Visual Studio. With all that said lets get down straight to code. This example shows the use of Impersonation, SearchFilter, FindItems, Paging in Exchange Web Services. Create a .PS1 as below:

 # 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]$errorMessage = "Red"          # Color for error messages
[string]$LogFile = "C:\Temp\Log.txt"   # Path of the Log Filefunction GetItemCount($MailboxName)
{
    Add-Content $LogFile ("-------------------------------------------------" )    
    Write-host "Searching Inbox for Mailbox Name:" $MailboxName -foregroundcolor  $info
    Add-Content $LogFile ("Searching Inbox for 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
    $pageSize =50
    $Offset = 0
    $MoreItems =$true
    $ItemCount=0
    $ItemSize=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        #Get the Size of the Items
        $itemView.PropertySet = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.ItemSchema]::Size);
        

        #Create the Search Filter - Subtract 5 Years from todays date.
        $oSearchFilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsLessThanOrEqualTo([Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeReceived,
                                                                                                                                               ([System.Datetime]::now).AddMonths(-60))

        $oFindItems = $service.FindItems([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox,$oSearchFilter,$itemView)


        $ItemCount += $oFindItems.Items.Count 
        
        $i=0
        #Loop through the items returned and add up the size
        foreach ($Item in $oFindItems.Items)
        {
            $i++
            $ItemSize += $Item.Size
            Write-Progress -activity "Adding Item Sizes" -status "Percent added: " -PercentComplete (($i /$oFindItems.Items.Count)  * 100)

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

        
        if ($MoreItems)
        {$Offset += $pageSize}
        
     }    Write-host "Items Found in Inbox:" $ItemCount -foregroundcolor  $info
    Add-Content $LogFile ("Items Found in Inbox:" + $ItemCount )

    Write-host "Size of Items:" ($ItemSize / 1Mb) "MB" -foregroundcolor  $info
    Add-Content $LogFile ("Size of Items:" + ($ItemSize / 1Mb) + " MB" )
    Add-Content $LogFile ("-------------------------------------------------" )    

    $service.ImpersonatedUserId = $null
}#Change the path if needed
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","Password","Domain")# Change the URL to point to your cas server
$service.Url= new-object Uri(“https://CAS-SERVER/EWS/Exchange.asmx”)# Set $UseAutoDiscover to $true if you want to use AutoDiscover else it will use the URL set above
$UseAutoDiscover = $falseGet-Mailbox | 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 $errorMessage;
        Add-Content $LogFile ("Error: " + $_.Exception.Message);
        continue;
    }
    GetItemCount($WindowsEmailAddress)
}

To Run the script:
1)Open the Exchange Management Shell
2)Navigate to the location where the script file is.
3)Type in .\ScriptName.PS1 and hit enter to execute the script

Enjoy!