December, 2011

  • Akash Blogging......

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

    • 0 Comments

    This post deals with a scenario where we need to stamp Retention Policy on specific items. In this case we wanted to stamp a policy on items with a specific message class. In my previous post I had explained about Messaging records management and how to stamp the policy on a folder. Please do read my previous post if you have not yet done so.

    The process of stamping Retention Policy on items is not much different, when applying the Retention Policy to an item, we need to stamp it with two 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_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.

    Before you begin:
    You will need to download and install the EWS Managed API on the box you run this script on from the link below:
    Exchange Web Services Managed API
    http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=c3342fb3-fbcc-4127-becf-872c746840e1

    Read about setting up Impersonation in Exchange 2010 as the code below uses it.
    Configuring Exchange Impersonation (Exchange Web Services)
    http://msdn.microsoft.com/en-us/library/bb204095.aspx

    Using Exchange Impersonation XML Request/Response
    http://msdn.microsoft.com/en-us/library/bb204088.aspx

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

    We will stamp the properties using Exchange Web Services Managed API 1.1 in PowerShell 2.0 and below is how it is done. Create a .PS1 file with the code below:

    # This script 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 StampPolicyOnItems($MailboxName)
    {
    Write-host "Stamping Policy on Items for Mailbox Name:" $MailboxName -foregroundcolor $info
    Add-Content $LogFile ("Stamping Policy on Items for Mailbox Name:" + $MailboxName)

    #Change the user to Impersonate. Comment the line below if impersonation is not needed
    $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

    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 and look for items with the message class IPM.My-ARCHIVE
    $oSearchFilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::ItemClass, "IPM.My-ARCHIVE")

    #Look for items in the Inbox


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

    foreach ($Item in $oFindItems.Items)
    {
    $ItemCount++

    Write-host "Item Number:" $ItemCount
    Write-host "Message Class:" $Item.ItemClass
    Write-host "Subject:" $Item.Subject

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

    #PR_RETENTION_PERIOD 0x301A
    $RetentionPeriod = New-Object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(0x301A,[Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Integer)

    #Same as that on the policy
    $Item.SetExtendedProperty($RetentionPeriod, 1095)

    #Change the GUID based on your policy tag
    $PolicyTagGUID = new-Object Guid("{92186ff7-7f4d-4efa-a09b-bbdc5aee3908}")

    $Item.SetExtendedProperty($PolicyTag, $PolicyTagGUID.ToByteArray())

    $Item.Update([Microsoft.Exchange.WebServices.Data.ConflictResolutionMode]::AlwaysOverwrite)

    Write-host "Retention policy stamped on " $Item.ID -foregroundcolor $info
    Add-Content $LogFile ("Retention policy stamped on " + $Item.ID)

    }


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

    if ($MoreItems)
    {$Offset += $pageSize}

    }

    Write-host "Stamping Policy on Items for Mailbox Name:" $MailboxName "Done!" -foregroundcolor $info
    Add-Content $LogFile ("Done!")
    Add-Content $LogFile ("-------------------------------------------------" )

    #Comment the line below if impersonation is not needed

    $service.ImpersonatedUserId = $null
    }

    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,Use the account that has been granted Impersonation rights
    # If impersonation is not used, use the credentials required to access the mailbox
    $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(“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
    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;
    }
    StampPolicyOnItems($WindowsEmailAddress)
    }


    UserAccounts.txt contains the list of the users mailboxes in which the items needs to be stamped. 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.

    Enjoy!

  • Akash Blogging......

    Searching contacts using EWS Managed API 1.1 from PowerShell (Impersonation, SearchFilterCollection, ContainsSubstring)

    • 0 Comments

    Here is another example of using EWS Managed API with PowerShell 2.0. In this case the requirement was to be able to find out all contacts that have Hotmail email address in any of the Email Address fields. This provided me to opportunity to demonstrate the use SearchFilterCollection and ContainsSubstring search filter from a PowerShell script. In addition to SearchFilterCollection and ContainsSubstring, this sample also shows the use of Impersonation. The use of Impersonation is necessary because the requirement was to search in multiple mailboxes.

    Details on how to configure Exchange Impersonation can be found in the links below:
    Exchange 2010:
    Configuring Exchange Impersonation (Exchange Web Services)
    http://msdn.microsoft.com/en-us/library/bb204095.aspx

    Using Exchange Impersonation XML Request/Response
    http://msdn.microsoft.com/en-us/library/bb204088.aspx

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

    Exchange 2007:
    Configuring Exchange Impersonation (Exchange Web Services)
    http://msdn.microsoft.com/en-us/library/bb204095(EXCHG.80).aspx

    Using Exchange Impersonation (Exchange Web Services)
    http://msdn.microsoft.com/en-us/library/bb204088(EXCHG.80).aspx

    You will also need to download and install the EWS Managed API on the box you run this script on from the link below:

    Exchange Web Services Managed API
    http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=c3342fb3-fbcc-4127-becf-872c746840e1

    Now for the code. Create a .PS1 file with the code below:

    # This script 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 SearchContacts($MailboxName)
    {
    Write-host "Searching Contacts in Mailbox :" $MailboxName -foregroundcolor $info
    Add-Content $LogFile ("Searching Contacts in Mailbox :" + $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 =40
    $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.ContactSchema]::GivenName,
    [Microsoft.Exchange.WebServices.Data.ContactSchema]::Surname,
    [Microsoft.Exchange.WebServices.Data.ContactSchema]::EmailAddress1,
    [Microsoft.Exchange.WebServices.Data.ContactSchema]::EmailAddress2,
    [Microsoft.Exchange.WebServices.Data.ContactSchema]::EmailAddress3)

    #Create the Search Filter.
    $searchFilterEA1 = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+ContainsSubstring(
    [Microsoft.Exchange.WebServices.Data.ContactSchema]::EmailAddress1,"@hotmail.com")

    $searchFilterEA2 = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+ContainsSubstring(
    [Microsoft.Exchange.WebServices.Data.ContactSchema]::EmailAddress2,"@hotmail.com")

    $searchFilterEA3 = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+ContainsSubstring(
    [Microsoft.Exchange.WebServices.Data.ContactSchema]::EmailAddress3,"@hotmail.com")

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

    $oSearchFilters.add($searchFilterEA1)
    $oSearchFilters.add($searchFilterEA2)
    $oSearchFilters.add($searchFilterEA3)

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

    foreach ($Item in $oFindItems.Items)
    {

    if ($Item.GetType().FullName -eq "Microsoft.Exchange.WebServices.Data.Contact")
    {
    Write-host "Given Name:" $Item.GivenName
    Write-host "Surname:" $Item.Surname
    Write-host "Email Address 1:" $Item.EmailAddresses[[Microsoft.Exchange.WebServices.Data.EmailAddressKey]::EmailAddress1]
    Write-host "Email Address 2:" $Item.EmailAddresses[[Microsoft.Exchange.WebServices.Data.EmailAddressKey]::EmailAddress2]
    Write-host "Email Address 3:" $Item.EmailAddresses[[Microsoft.Exchange.WebServices.Data.EmailAddressKey]::EmailAddress3]

    Add-Content $LogFile("Given Name :" + $Item.GivenName)
    Add-Content $LogFile("Surname :" + $Item.Surname)
    Add-Content $LogFile("Email Address 1:" + $Item.EmailAddresses[[Microsoft.Exchange.WebServices.Data.EmailAddressKey]::EmailAddress1])
    Add-Content $LogFile("Email Address 2:" + $Item.EmailAddresses[[Microsoft.Exchange.WebServices.Data.EmailAddressKey]::EmailAddress2])
    Add-Content $LogFile("Email Address 3:" + $Item.EmailAddresses[[Microsoft.Exchange.WebServices.Data.EmailAddressKey]::EmailAddress3])

    }
    }

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

    if ($MoreItems)
    {$Offset += $pageSize}

    }

    Write-host "Searching Contacts in Mailbox :" $MailboxName "Done!" -foregroundcolor $info
    Add-Content $LogFile ("Done!")
    Add-Content $LogFile ("-------------------------------------------------" )

    $service.ImpersonatedUserId = $null
    }

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

    # This script also works on Exchange 2007. Just change the Version Header to Exchange2007_SP1
    $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(“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
    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;
    }
    SearchContacts($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.

    Enjoy!

Page 1 of 1 (2 items)