Generating a report - Which folders have a Personal Tag applied to it (using EWS Managed API from PowerShell - Exchange 2010)

It’s time to do a bit of reporting!

In my previous posts I have talked about Stamping Archive Policy Tag, Retention Policy Tag on Items, Retention Policy Tag on Folders but this time the requirement was different! In this case we wanted to scan the entire mailbox and find out the folders that have a Personal Tag applied to it.

To summarize what the script below does:

  • We search the entire mailbox and look for folders that have a Folder class of IPF.Note
  • Loop through the folders and write out the Folder Path, Retention Policy Tag GUID and the Retention Period
  • The log can then be opened in Excel and manipulated in any way you like!

Straight to code now. Create a .PS1 file with the code below:

 # The script requires the EWS managed API, which can be downloaded here:
# https://www.microsoft.com/en-us/download/details.aspx?id=35371
# 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.csv" # Path of the Log Filefunction SearchFolders($MailboxName)
{
    Write-host "Searching folders in Mailbox Name:" $MailboxName -foregroundcolor  $info
    
    #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
        
        # Folder Path
        $PR_FOLDER_PATH = new-object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(26293, [Microsoft.Exchange.WebServices.Data.MapiPropertyType]::String);        #PR_POLICY_TAG 0x3019
        $PolicyTag = New-Object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(0x3019,[Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Binary);        #PR_RETENTION_FLAGS 0x301D    
        $RetentionFlags = New-Object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(0x301D,[Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Integer);
        
        #PR_RETENTION_PERIOD 0x301A
        $RetentionPeriod = New-Object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(0x301A,[Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Integer);

        $FPropertySet = 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);
                            
        $FPropertySet.Add($PR_FOLDER_PATH);  
        $FPropertySet.Add($PolicyTag);
        $FPropertySet.Add($RetentionPeriod);
        
        $folderView.PropertySet = $FPropertySet;
        
        #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)
        
        $PolicyTagString = $null;
        
        foreach ($folder in $oFindFolders.Folders)
        {
            Write-host "Looking at Folder:" $folder.ExtendedProperties[0].Value  -foregroundcolor $info;
      
            &{
                if ($folder.ExtendedProperties[1].Value -ne $null)
                {
                    $byteA =[byte[]]($folder.ExtendedProperties[1].Value)
                    $PolicyTagGUID = new-Object Guid(,$byteA);
                    $PolicyTagString = $PolicyTagGUID.ToString();
                }
                Add-Content $LogFile ($MailboxName + "," +$folder.ExtendedProperties[0].Value +"," +$PolicyTagString+"," +$folder.ExtendedProperties[2].Value);
            }
            trap [System.Exception] 
            {
                Write-host ("Error: " + $_.Exception.Message) -foregroundcolor $error;
                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

    $service.ImpersonatedUserId = $null
}Import-Module -Name "C:\Program Files\Microsoft\Exchange\Web Services\2.0\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://Your-CAS-Server/EWS/Exchange.asmx")# Set $UseAutoDiscover to $true if you want to use AutoDiscover else it will use the URL set above
$UseAutoDiscover = $false# Add headers to the log file
Add-Content $LogFile ("Mailbox" + "," +"Folder Path" +"," +" Retention Tag GUID" +"," +"Retention Period");#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)
}    

UserAccounts.txt contains the list of the users mailboxes that need to be searched. This file should exist in the same directory as the .PS1 file.The First row denotes the Field Names. Format of the text file is as below:

 WindowsEmailAddress
akasha@contoso.com
akashb@contoso.com
akashc@contoso.com
 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 
Note: This script creates a log file in C:\Temp. Make sure that directory exists.
 Below is what the log file will look like:
 Mailbox,Folder Path, Retension Tag GUID,Retension Period
akasha@contoso.com,\Deleted Items,,
akasha@contoso.com,\Drafts,,
akasha@contoso.com,\Inbox,,
akasha@contoso.com,\Inbox\Inbox1,4528ac9a-35b6-454d-96cb-c6801795bbce,300
akasha@contoso.com,\Inbox\Inbox1\Inbox2,4528ac9a-35b6-454d-96cb-c6801795bbce,300
akasha@contoso.com,\Junk E-Mail,,
akasha@contoso.com,\Outbox,,
akasha@contoso.com,\Sent Items,,
akasha@contoso.com,\Test,4528ac9a-35b6-454d-96cb-c6801795bbce,300
akashb@contoso.com,\Deleted Items,,
akashb@contoso.com,\Drafts,,
akashb@contoso.com,\Inbox,,
akashb@contoso.com,\Inbox\1,,
akashb@contoso.com,\Junk E-Mail,,
akashb@contoso.com,\Outbox,,
akashb@contoso.com,\Sent Items,,
 Note the Folder Path and the GUID. What is this GUID? This is the Retention Policy Tag GUID!
 Where can I get it from?
 Open up Exchange Management Shell and run the command below:
 [PS] C:\>Get-RetentionPolicyTag | FL Name,GUID
 Output:
 Name : Personal 1 Year move to archive
Guid : 797921d5-5c63-4a7b-b5d0-31e57a48f71b
Name : 1 Year Delete
Guid : 82139a14-cbf8-4467-9324-1c95c91bc12a
Name : Corp-BusinessCritical
Guid : 92186ff7-7f4d-4efa-a09b-bbdc5aee3908
Name : 100 Days - Delete
Guid : 3b7f5e7a-9016-4f87-a829-83f84c5adc62
Name : 300 Days Delete
Guid : 4528ac9a-35b6-454d-96cb-c6801795bbce

Now you know which Policy Tag was applied to the folder. Enjoy!