Editor’s note: The following post was written by Exchange Server MVP Glen Scales
5 new lesser known operations in Exchange Web Services on Exchange 2013 and how to use them
In this blog post I’m going to look at 5 of the lesser known new Exchange Web Services Operations in Exchange 2013. As with most of the new features in 2013 these new operations build on top of the EWS foundation from 2007 and 2010 and allows the easier programmatic manipulation of the Mailbox data.
1. Getting the User Photo from Exchange via EWS
EWS in 2013 now has two methods you can use to Get User photos, there is a normal SOAP based EWS operation called GetUserPhoto and there is also a REST-based end point. The REST based operation can be useful for non EWS applications where you just want to make use of the user Photo. To use this REST-based end point to access the photo you just need the SMTP Address of the user and the size of the user photo you want. The sizes that can requested are
Size Code | Notes |
HR48x48 | If you request HR48x48 then the Active Directory thumbnail is returned |
HR64x64 |
|
HR96x96 |
|
HR120x120 |
|
HR240x240 |
|
HR360x360 |
|
HR432x432 |
|
HR504x504 |
|
HR648x648 |
|
If you request a size that is not available the largest available size will be returned if no picture is available the active directory thumbnail gets returned.
Managed API Sample – While there are no methods in the EWS Managed API to access the GetUserPhoto operation you can still use the Autodiscover Class to find the ExternalPhotoURL and then use any of the regualr.NET Web Request classes such as the WebClient Class to access the REST endpoint. The following is a PowerShell sample that shows how to do this
$MailboxName="fsmith@domain.onmicrosoft.com"
$PhotoSize="HR64x64"
Add-Type-Path"C:\Program Files\Microsoft\Exchange\Web Services\2.0\Microsoft.Exchange.WebServices.dll"
functionAutoDiscoverPhotoURL{
param (
$EmailAddress="$( throw 'Email is a mandatory Parameter' )",
$Credentials="$( throw 'Credentials is a mandatory Parameter' )"
)
process{
$version= [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2013
$adService=New-Object
Microsoft.Exchange.WebServices.Autodiscover.AutodiscoverService($version);
#This Example does an Autodiscover against Exchange Online
$uri=[system.URI] ("https://autodiscover-
s.outlook.com/autodiscover/autodiscover.svc")
$adService.Url =$uri
$creds=New-Object
System.Net.NetworkCredential($Credentials.UserName.ToString(),$Credentials.GetNetworkCredentia
l().password.ToString())
$adService.Credentials=$creds
$adService.EnableScpLookup=$false;
$adService.RedirectionUrlValidationCallback= {$true}
$adService.PreAuthenticate=$true;
$UserSettings=new-object
Microsoft.Exchange.WebServices.Autodiscover.UserSettingName[] 1
$UserSettings[0] =
[Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::ExternalPhotosUrl
$adResponse=$adService.GetUserSettings($MailboxName, $UserSettings)
$PhotoURI=
$adResponse.Settings[[Microsoft.Exchange.WebServices.Autodiscover.UserSettingName]::ExternalPh
otosUrl]
return$PhotoURI.ToString()
}
}
#Example Use
$pscreds= (Get-Credential)
$PhotoURL=AutoDiscoverPhotoURL-EmailAddress$MailboxName -Credentials $pscreds
$PhotoURL=$PhotoURL+"/GetUserPhoto?email="+$MailboxName+"&size="+$PhotoSize;
$wbClient=new-objectSystem.Net.WebClient
$wbClient.Credentials=New-ObjectSystem.Net.NetworkCredential($pscreds.UserName.ToString(),$pscreds.GetNetworkCredential().password.ToString())
#Download photo to a file
$wbClient.DownloadFile($PhotoURL,"c:\Temp\UsrPhoto.jpg");
#Get photo as a ByteArray
$photoBytes=$wbClient.DownloadData($PhotoURL);
2. – How to Archive an Item using the ArchiveItem Operation in EWS
Personal Archives is a feature that was introduced in Exchange 2010 and again improved on in Exchange 2013. The ArchiveItem Operation is aimed at giving you the ability to move items from your Primary Mailbox to your Personal Archive. For example this operation can be used to selectively Archive Messages from the Inbox folder based on a particular Search criteria. The following sample will Archive messages that are older than 1 year to the Archive Store while maintaining the folder hierarchy.
$queryTime= (Get-Date).AddYears(-1)
$AQSString= "System.Message.DateReceived:<"+$queryTime.ToString("MM/dd/yyyy")
# Bind to the Inbox Folder
$folderid=new-objectMicrosoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox,$MailboxName)
$Inbox=[Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)
$ivItemView= New-ObjectMicrosoft.Exchange.WebServices.Data.ItemView(1000)
$fiItems=$null
$type=("System.Collections.Generic.List"+'`'+"1")-as"Type"
$type=$type.MakeGenericType("Microsoft.Exchange.WebServices.Data.ItemId"-as"Type")
$archiveItems= [Activator]::CreateInstance($type)
do{
$fiItems=$service.FindItems($Inbox.Id,$AQSString,$ivItemView)
#[Void]$service.LoadPropertiesForItems($fiItems,$psPropset)
foreach($Itemin$fiItems.Items){
$archiveItems.Add($Item.Id)
}
$ivItemView.Offset+=$fiItems.Items.Count
}while($fiItems.MoreAvailable-eq$true)
$type= ("System.Collections.Generic.List"+'`'+"1") -as"Type"
$type=$type.MakeGenericType("Microsoft.Exchange.WebServices.Data.ItemId"-as"Type")
$batchArchive= [Activator]::CreateInstance($type)
foreach($itItemIDin$archiveItems){
$batchArchive.add($itItemID)
if($batchArchive.Count-eq 100){
$service.ArchiveItems($batchArchive,[Microsoft.Exchange.WebServices.Data.WellKnownFold
erName]::Inbox)
$batchArchive.clear()
}
}
if($batchArchive.Count-gt 0){
$service.ArchiveItems($batchArchive,[Microsoft.Exchange.WebServices.Data.WellKnownFold
erName]::Inbox)
$batchArchive.clear()
}
3. Mark all the messages in a folder Read using the MarkAllAsRead Operation in EWS
Everybody knows the pain of having to mark a lot of messages read after coming back from a holiday. This new operation in EWS makes it easy to do this for all messages within a particular folder (In previous versions you would have had to find the messages that where unread and then modify each message individually). In the EWS Managed API to use this operation you can take advantage of two new methods that have been added to the folder class MarkAllItemsAsRead and MarkAllItemsAsUnread. For example here is how you can mark all the Unread Messages in the Inbox folder as Read (the Boolean parameter in the method tells Exchange whether to suppress Read Recipients or not).
# Bind to the Inbox Folder
$folderid=new-objectMicrosoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox,$MailboxName)
$Inbox=[Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)
"Number of Messages Unread : "+$Inbox.UnreadCount
$Inbox.MarkAllItemsAsRead($false)
4. Marking messages as Junk Email
Another new Operation that has been added to EWS is the ability to Mark and UnMark messages as JunkEmail and move these messages to and from the Junk Email folder. This Operation does two separate things when you use it
· Moves a messages To or From the Junk Email Folder
· Add or Removes the sender of the Messages you’re marking or unmarking as Junk Email to the blocked sender list of that Mailbox.
To use this operation you first need to get the ItemIds of the Items you want to Mark or UnMark as Junk Email. This is typically done in EWS using the FindItem Operation and then filtering on a particular Item property. To control what the MarkAsJunk operation does in the EWS Managed API the MarkAsJunk method has two parameters IsJunk and MoveItem. The following table lists the combinations and actions for these parameters
Folder | IsJunk | MoveItem | Action |
Inbox/Any | True | True | Item will be moved to the Junk email folder and email sender added to Blocked Senders List of the Mailbox |
Inbox /Any | True | False | The Sender of the Email is added to the Blocked Senders List |
JunkEmail | False | True | Item will be moved to the Inbox folder and email Sender will be removed from the Blocked Senders List of the Mailbox |
JunkEmail/Any | False | False | The Sender of the Email will be removed from the Blocked Senders list of the Mailbox |
In this example Messages that have NewLetter in the Subject are marked as JunkEmail and moved to the JunkEmail Folder using the MarkAsJunk operation.
# Bind to the Inbox Folder
$folderid=new-objectMicrosoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox,$MailboxName)
$Inbox=[Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)
#Define ItemView to retrive just 1000 Items
$ivItemView= New-ObjectMicrosoft.Exchange.WebServices.Data.ItemView(1000)
$fiItems=$null
$type= ("System.Collections.Generic.List"+'`'+"1") -as"Type"
$type=$type.MakeGenericType("Microsoft.Exchange.WebServices.Data.ItemId"-as"Type")
$JunkItems= [Activator]::CreateInstance($type)
do{
$fiItems=$service.FindItems($Inbox.Id,$ivItemView)
#[Void]$service.LoadPropertiesForItems($fiItems,$psPropset)
foreach($Itemin$fiItems.Items){
if($Item.Subject-ne$null){
if($Item.Subject.Contains("newsletter")){
$JunkItems.Add($Item.Id)
}
}
}
$ivItemView.Offset+=$fiItems.Items.Count
}while($fiItems.MoreAvailable-eq$true)
$service.MarkAsJunk($JunkItems,$true,$true);
5. Using UserRetentionPolicyTags
While it is possible in Exchange 2010 to use UserRetentionPolicyTags in EWS it did require that you define and use the raw extended properties. In 2013 in the EWS using the UserRetentionPolicyTags is made easier through the integration of these tags into the FolderClass and also the GetUserRetentionPolicyTags operation which can be used to get all the user RetentionPolicyTags and their associated settings. For example here is how to create a new folder and set the RetentionPolicyTag on that Folder to a UserRetentionPolicyTag called “1 Month Delete”.
$getRTResp=$service.GetUserRetentionPolicyTags();
foreach ($rtTagin$getRTResp.RetentionPolicyTags) {
if ($rtTag.DisplayName-eq"1 Month Delete")
{
$NewFolder=new-objectMicrosoft.Exchange.WebServices.Data.Folder($service)
$NewFolder.DisplayName="My New Folder12345"
$NewFolder.FolderClass="IPF.Note"
$NewFolder.PolicyTag=New-Object
Microsoft.Exchange.WebServices.Data.PolicyTag($true,$rtTag.RetentionId)
$NewFolder.Save($folderid)
}
}
About the author
Glen Scales is a freelance software developer and engineer who specializes in Microsoft Exchange APIs used to create customized solutions for a range of clients and industries, particularly in the realm of cloud-based services within messaging environments. He has been an Exchange MVP since 2004, contributing regularly to the Exchange development forums on TechNet and creating and sharing open source code libraries and scripts on his blog (http://gsexdev.blogspot.com) and twitter @glenscales.
About MVP Mondays
The MVP Monday Series is created by Melissa Travers. In this series we work to provide readers with a guest post from an MVP every Monday. Melissa is a Community Program Manager, formerly known as MVP Lead, for Messaging and Collaboration (Exchange, Lync, Office 365 and SharePoint) and Microsoft Dynamics in the US. She began her career at Microsoft as an Exchange Support Engineer and has been working with the technical community in some capacity for almost a decade. In her spare time she enjoys going to the gym, shopping for handbags, watching period and fantasy dramas, and spending time with her children and miniature Dachshund. Melissa lives in North Carolina and works out of the Microsoft Charlotte office.