Friday, December 04, 2009

Using Contact photo's in EWS in Exchange 2010

Contact photo's where a feature first introduced in Outlook 2003 but up until the release on Exchange 2010 not something you could use in EWS. This should not be confused with another new feature in Exchange 2010 which is the ability to upload a picture to the Gal (or the directory to be more precise) if your interested in finding out more about that check out Ilse post .

So the Contact photo's I'm talking about are those that are associated with contact Items in your mailbox. About 4 years ago i posted this script (which was rubbish) for doing this with CDO 1.2 importantly in the heady stile of 2005 i pointed out that when using contact photos you need to set some extended properties on the attachment. Now while you still can't do this with EWS :( in 2010 they have added the ability to set the properties of a contact photo(just wish they hadn't stopped there). Further the EWS Managed API actually makes the process of adding a contact photo quite easy.

So a very simple piece of code to add a contact photo in C# would look like


ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010);
service.AutodiscoverUrl("emailaddres@domain.com");
Folder Contacts = Folder.Bind(service, WellKnownFolderName.Contacts);
Contact cn1 = new Contact(service);
cn1.GivenName = "Fred";
cn1.Surname = "Bloggs";
cn1.EmailAddresses[EmailAddressKey.EmailAddress1] = "fblogs@domain.com";
cn1.Subject = "Fred Bloggs";
FileAttachment atattach = cn1.Attachments.AddFileAttachment("c:\\contactphoto.jpg");
atattach.IsContactPhoto = true;
cn1.Save();

For those looking for a Powershell version that you can put to work I've got one of those as well the following is a script that allows you to specify the emailaddress of the contact you want update and the photo you want to use. The script will then search for this conact in the mailboxes contact folder and upload the picture to it (if found). I've put a download of this script here the code itself looks like.

$MailboxName = "user@mbmailbox.com"
$emEmailAdddrestoFind = "fred@fred.com"
$cntPhotoFile = "c:\ck1.jpg"

$dllpath = "C:\Program Files\Microsoft\Exchange\Web Services\1.0\Microsoft.Exchange.WebServices.dll"
[void][Reflection.Assembly]::LoadFile($dllpath)
$service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010)

$windowsIdentity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$sidbind = "LDAP://<SID=" + $windowsIdentity.user.Value.ToString() + ">"
$aceuser = [ADSI]$sidbind

$service.AutodiscoverUrl($mailboxname)

$folderid = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Contacts,$MailboxName)
$ContactsFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)
$Iview = new-object Microsoft.Exchange.WebServices.Data.ItemView(1000)
$SfSearchFilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.ContactSchema]::EmailAddress1,$emEmailAdddrestoFind)
$frContactResults = $ContactsFolder.FindItems($SfSearchFilter,$Iview)
foreach ($cnContacts in $frContactResults.Items){
$cnContacts.Subject
$atattach = $cnContacts.Attachments.AddFileAttachment($cntPhotoFile)
$atattach.IsContactPhoto = $true
$cnContacts.update([Microsoft.Exchange.WebServices.Data.ConflictResolutionMode]::AlwaysOverwrite)
}

13 comments:

Anonymous said...

Glen your blog is packed with useful information!!!

The only thing that could make it better would be a new template and some code highlighting to make it easier to read.

SeanMBennett said...

Excellent news Glen! Thanks for all the work you do.

sadık said...

hi Is the in sample your wrapper's lines???
I got 2010 exchange
and ExcgangeServerBinding has
ContactItemType.Attachments
which has no property such as IsContactPhot...

may you provide sample with ExchangeWebService proxy classes

thanks

Glen said...

I would suggest you use the EWS Managed API it will save you a lot of trouble and time when coding in Exchange. If your going to use Proxy code make sure you generate your own proxies against a Exchange 2010 server. Note this wont work on 2007

Cheers
Glen

hosted exchange server said...

Hi Glen:

I have been browsing your blog for a possible workaround to enable users to add notes. I simply can't wait for SP1 to come out. Would you happen to have that?

Glen said...

What do you mean by Add Notes ?

Marco said...

Anyone got a tip how to add a contact picture using EWS 2007?

Glen said...

You need to use Mapi so use either the OOM, CDO 1.2 or Redemption

Cheers
Glen

BadPirate said...

Hi Glen, Is there a way to retrieve these photos using ActiveSync? I've noticed that there is an ActiveSync parameter for photo in Contacts, however, it doesn't seem to be the same one that is used by EWS or AD :(

Glen Scales said...

I'm not really an ActiveSync person have you tried just getting the Attachments on the Contact. The contact picture should just be an attachment on the contact.

If your using Exchange 2013 then you could use the new Rest operation in EWS to get Gal Contact photo in a number of formats.

Cheers
Glen

Venkata Arun Kumar Maddu said...

Hello Glen,

I am trying to access the user profile picture for the user from ews 2010 server. I am getting 401 unauthorized error, can you please help me for this error.

https://msdn.microsoft.com/en-us/library/office/jj190905(v=exchg.150).aspx
I am trying this code, it's not working.

Glen Scales said...

UserPhotos are only supported on Exchange 2013 (they added a new operation for this in 2013. On 2010 you can only get a contact photo from the contacts folder.

RichMinichiello said...

Glen,
I'm pulling bits and pieces from around the web to get a specific service running. What I'm trying to do is update the contact photo in a Public Folder. I'm using the EWS Managed API v 2.2 and running it against Exchange Online. Once I connect to the contacts folder in the public folder, I'm running this bit of code to process the update:
$itemView = New-Object Microsoft.Exchange.WebServices.Data.ItemView(1000)
$searchFilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.ContactSchema]::EmailAddress1, $Mailbox)
$findItemResults = $ews.FindItems($folder.Id, $searchFilter, $itemView)
foreach ($item in $findItemResults.Items)
{
$item.DisplayName
$atattach = $item.Attachments.AddFileAttachment($UserPhoto)
$atattach.IsContactPhoto = $true
$item.update([Microsoft.Exchange.WebServices.Data.ConflictResolutionMode]::AlwaysOverwrite)
}
It works for some, but for others I get an error on the update line:
Exception calling "Update" with "1" argument(s): "At least one attachment couldn't be created."
I've searched everywhere for a reason, and I can't find it. Any ideas?