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.


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:
# 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 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)
Write-host "Folder found in Mailbox:" $MailboxName -foregroundcolor $info

$PolicyTag = New-Object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(0x3019,[Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Binary);

$RetentionFlags = New-Object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(0x301D,[Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Integer);

$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())


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(http://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
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);

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:


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!
Comments (9)

  1. Vojin Lekovic says:

    Excellent!!! Just what I was looking for.

  2. Jeff says:

    How will this behave when stamped on a folder in a mailbox that already has a retention policy assigned to it? Since mailboxes can only have one retention policy, I am curious whether this will overlay on such a mailbox with no issues. For example: 7-year email retention applied to entire mailbox. 2-year move to archive applied to a specific folder using this script. Also, would the subfolder of the specific folder inherit the tag applied by the script or the mailbox policy?

    Thanks for you guidance!


  3. akash says:

    I believe you can safely use a Personal Tag. The Specific folder policy should overide the mailbox policy.

    For the Subfolders, I dont think so, but it would be best to test.

  4. Marc says:

    Can this be run on a folder inside a well know folder ie "inbox3 year retention" ?

    Let me know when you have a chance.



  5. Carsten says:

    What would the syntac be to run this script for a custom subfolder, i.e. "Retention FoldersBudget"?

    The "Retention Folders" is a subfolder of the mailbox and "Budget is a subfolder of "Retention Folders".

    When I change the line to "$FolderName = "Retention FoldersBudget", I get "Folder does not exist in Mailbox."


  6. akash says:

    Carsten, unfortunately the script is not designed to parse the path. You would first have to find the "Retention Folders" and then find the "Budget" folder.

  7. Steve says:

    Has anyone been successful in running this script on their tenant in Office 365?  I've tried it many times and haven't been able to get it to work.  I'm able to connect successfully to my tenant, however, my policy tag doesn't tag the folder. I've verified I've got the right GUID,Retention Tag property and service Url.

  8. akash says:

    Yes, I have :-). The script is configured to run on the Archive Mailbox, did you change that in code? Search for MsgFolderRoot in code and uncomment that line and comment the line that has ArchiveMsgFolderRoot.

Skip to main content