Stamping Retention Policy Tag using EWS Managed API 1.1 from PowerShell(Exchange 2010)

Exchange Web Services with PowerShell! In the last few days I have written quite a few scripts that use Exchange Web Services Managed API 1.1 with PowerShell, you will agree that it is not as easy as writing Exchange Web Services Managed API 1.1 with C# and it takes a bit of getting used to it. One of my customer wanted to stamp a Retention Policy Tag on a folder in the Archived mailbox in Exchange 2010. What is a Retention Policy Tag?

Messaging records management (MRM) is the records management technology in Microsoft Exchange Server 2010 that helps organizations reduce the legal risks associated with e-mail. MRM makes it easier to keep the messages needed to comply with company policy, government regulations, or legal needs, and to remove content that has no legal or business value. This is accomplished through the use of retention policies or managed folders.

Retention policies, use retention tags to apply retention settings. You create retention tags, and link them to a retention policy. Mailboxes that have a retention policy applied to them are processed by the Managed Folder Assistant, a mailbox assistant that runs on a schedule and provisions retention tags in mailboxes. More details about understanding and creating retention policies and tags can be found in the following articles on MSDN:

Now that you understand what a Retention Policy Tag is, when applied to a folder stamps it with three important properties:

  • PR_POLICY_TAG – The data type for this property is binary . The value that it contains is the GUID of the retention tag that you create. Do a Get-RetentionPolicyTag YourTagName |fl and copy the value in the GUID property. This value will be uses in the script later on.
  • PR_RETENTION_FLAGS – The data type for this property is Integer. The easiest would be to get the values using MFCMAPI once the policy is applied to the Mailbox and the policy tag to the folder(screenshot below). “Test Policy” is the folder where this retention policy tag is applied. If you don’t see these properties that means that there is no policy tag on the folder.
  • PR_RETENTION_PERIOD – The data type for this property is Integer. This is the same value that you specify for the AgeLimitForRetention while creating or updating the retention policy tag.

MFCMAPI

We will stamp the same properties using Exchange Web Services Managed API 1.1 in PowerShell and this is how it is done:

 # 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 Filefunction StampPolicyOnFolder($MailboxName)
{
    Write-host "Stamping Policy on folder for Mailbox Name:" $MailboxName -foregroundcolor  $info
    Add-Content $LogFile ("Stamping Policy on folder 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);    #Search for the folder you want to stamp the property on
    $oFolderView = new-object Microsoft.Exchange.WebServices.Data.FolderView(1)
    $oSearchFilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.FolderSchema]::DisplayName,$FolderName)    #Uncomment the line below if the folder is in the regular mailbox
    #$oFindFolderResults = $service.FindFolders([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$oSearchFilter,$oFolderView)    #Comment the line below and uncomment the line above if the folder is in the regular mailbox
    $oFindFolderResults = $service.FindFolders([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::ArchiveMsgFolderRoot,$oSearchFilter,$oFolderView)    if ($oFindFolderResults.TotalCount -eq 0)
    {
         Write-host "Folder does not exist in Mailbox:" $MailboxName -foregroundcolor  $warning
         Add-Content $LogFile ("Folder does not exist in Mailbox:" + $MailboxName)
    }
    else
    {
        Write-host "Folder found in Mailbox:" $MailboxName -foregroundcolor  $info        #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);        #Bind to the folder found
        $oFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$oFindFolderResults.Folders[0].Id)
       
        #Same as the value in the PR_RETENTION_FLAGS property
        $oFolder.SetExtendedProperty($RetentionFlags, 137)        #Same as the value in the PR_RETENTION_PERIOD property
        $oFolder.SetExtendedProperty($RetentionPeriod, 1095)        #Change the GUID based on your policy tag
        $PolicyTagGUID = new-Object Guid("{92186ff7-7f4d-4efa-a09b-bbdc5aee3908}");

        $oFolder.SetExtendedProperty($PolicyTag, $PolicyTagGUID.ToByteArray())        $oFolder.Update()

        Write-host "Retention policy stamped!" -foregroundcolor $info
        Add-Content $LogFile ("Retention policy stamped!")
    
    }    

    $service.ImpersonatedUserId = $null
}#Change the name of the folder. This is the folder the properties will be stamped on.
$FolderName = "My Folder"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("UserName","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#Read data from the UserAccounts.txt.
#This file must exist in the same location as the script.

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;
    }
    StampPolicyOnFolder($WindowsEmailAddress)
} 

UserAccounts.txt contains the list of the users mailboxes that contain the folder that is set in the $FolderName variable in the script above.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 and the UserAccounts.txt file is.
3)Type in .\ScriptName.PS1 and hit enter to execute the script

 

Thank you Vikas Soundade(Exchange) for helping me with the MRM piece!

 

Enjoy!