在 Exchange 中使用 EWS 获取用户照片
了解如何使用 Exchange 中的 EWS 托管 API 或 EWS 获取与邮箱或联系人关联的用户照片。
把脸贴在名字上真好。 如果用户希望将姓名写在人脸上,应用程序可以从 Exchange 请求一张表示电子邮件帐户的图像(通常是照片)。 您可以获取邮箱的 Exchange 服务器上存储的用户照片,也可以从邮箱中存储的联系人中获取联系人照片。
可以使用多种不同的技术从邮箱获取照片,或Active Directory 域服务 (AD DS) 。 获取照片的最佳方式取决于要从中获取照片的联系人类型。
表 1. 用于根据联系人类型获取用户照片的技术
联系人类型 | 要使用的技术 |
---|---|
邮箱用户照片 |
使用 REST 获取邮箱用户照片 使用 EWS 获取用户照片 |
联系人用户照片 |
使用 EWS 托管 API 获取联系人用户照片 使用 EWS 获取用户照片 |
使用 REST 获取邮箱用户照片
可以使用标准 HTTPS GET 请求从 Exchange 服务器请求用户照片。 在请求中,指定图像的电子邮件帐户地址和大小代码,如以下示例所示。
https://Exchange Server/ews/Exchange.asmx/s/GetUserPhoto?email=email address&size=size code
使用自动发现服务 GetUserSettings 操作检索 ExternalEwsUrl 设置,该设置包含 Exchange Web Services (EWS) 终结点的 URL 以及返回用户照片的 Exchange.asmx HTTP 处理程序的位置。
每个大小代码指示图像的高度和宽度(以像素为单位)。 例如,大小代码 HR48x48 返回高 48 像素 x 48 像素宽的图像。 大小代码参数的可能值与 SizeRequested 元素的可能值相同。 如果请求指定的大小不可用,则将返回最大的可用照片。 如果 Exchange 服务器上未存储任何照片,则会返回帐户 AD DS 中存储的缩略图图像。
注意
HR48x48 大小代码始终返回 AD DS 缩略图图像(如果可用)。
以下示例演示如何使用 GET 请求检索 Sadie 的用户照片并将其保存到本地计算机。
// Create the web request with the REST URL.
HttpWebRequest request =
WebRequest.Create("https://www.contoso.com/ews/exchange.asmx/s/GetUserPhoto?email=sadie@contoso.com&size=HR240x240")
as HttpWebRequest;
// Submit the request.
using (HttpWebResponse resp = request.GetResponse() as HttpWebResponse)
{
// Take the response and save it as an image.
Bitmap image = new Bitmap(resp.GetResponseStream());
image.Save("Sadie.jpg");
}
请求将返回 HTTP 响应。
表 2. GetUserPhoto 请求的响应代码
响应代码 | 说明 |
---|---|
200 |
图像可用于指定的电子邮件帐户,二进制图像包含在响应中。 |
304 |
自上次 将 ETag 返回到应用程序以来,映像未更改。 |
404 |
没有可用于指定电子邮件帐户的映像。 |
缓存用户照片
Exchange 返回内容类型为 image/jpeg 的数据,以及标头值的集合。 ETag 标头类似于更改键。 该值是一个字符串,表示上次更新照片的时间。 在更改照片之前,用户照片的 ETag 保持不变。 可以在 If-None-Match 标头中的 HTTPS GET 请求中将此 ETag 值发送到服务器。 如果照片自上次请求以来一直没有更改,则服务器将使用 HTTP 304 响应进行响应,以指示此类响应。 这意味着你可以使用之前请求和保存的用户照片,而不是处理新照片。
使用 EWS 托管 API 获取联系人用户照片
如果联系人存储在用户邮箱中的联系人文件夹中,则应用程序可以使用 EWS 托管 API 检索联系人的照片。 为此,请先找到要使用的联系人的 ItemId 。 然后,在绑定到该联系人后,将其加载到附件集合。 如果联系人有照片,则照片将是附件之一。 循环访问附件集合,检查 IsContactPhoto 属性的值。 找到联系人照片后,可以将其保存到本地计算机,应用程序可以访问它。
以下示例演示此过程。 此示例假定 service 是有效的 ExchangeService 对象,且用户已通过 Exchange 服务器的身份验证。
private static void GetContactPhoto(ExchangeService service, string ItemId)
{
// Bind to an existing contact by using the ItemId passed into this function.
Contact contact = Contact.Bind(service, ItemId);
// Load the contact to get access to the collection of attachments.
contact.Load(new PropertySet(ContactSchema.Attachments));
// Loop through the attachments looking for a contact photo.
foreach (Attachment attachment in contact.Attachments)
{
if ((attachment as FileAttachment).IsContactPhoto)
{
// Load the attachment to access the content.
attachment.Load();
}
}
FileAttachment photo = contact.GetContactPictureAttachment();
// Create a file stream and save the contact photo to your computer.
using (FileStream file = new FileStream(photo.Name, FileMode.Create, System.IO.FileAccess.Write))
{
photo.Load(file);
}
}
使用 EWS 获取用户照片
如果要从 AD DS 获取用户照片,则可以使用 GetUserPhoto 操作 ((如果知道电子邮件地址) )或 ResolveNames 操作 ((如果不知道电子邮件地址) )。 如果要从邮箱中的联系人文件夹获取用户照片,请使用 GetItem 操作,然后使用 GetAttachment 操作。 在任一情况下,照片将在 XML 响应中作为 Base64 编码字符串返回。
使用 GetUserPhoto 操作获取邮箱用户照片
使用 GetUserPhoto 操作非常简单。 在 XML 请求中,在 SizeRequested 元素) 中指定要返回 (的用户电子邮件地址和照片的大小。 下面的 XML 请求示例演示如何为 Sadie Daniels 获取 360 像素宽 x 360 像素高的照片。
<?xml version="1.0" encoding="utf-8" ?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/"
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"
xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages">
<soap:Header>
<t:RequestServerVersion Version="Exchange2013 "/>
</soap:Header>
<soap:Body>
<m:GetUserPhoto>
<m:Email>sadie@contoso.com</m:Email>
<m:SizeRequested>HR360x360</m:SizeRequested>
</m:GetUserPhoto>
</soap:Body>
</soap:Envelope>
下面是 XML 响应。 Base64 编码的照片包含在 PictureData 元素中, (内容已缩短,以便) 可读性。
<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<GetUserPhotoResponse ResponseClass="Success"
xmlns="http://schemas.microsoft.com/exchange/services/2006/messages">
<ResponseCode>NoError</ResponseCode>
<HasChanged>true</HasChanged>
<PictureData>/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAg... wATRRRSuB//2Q==</PictureData>
</GetUserPhotoResponse>
</s:Body>
</s:Envelope>
使用 ResolveNames 操作获取邮箱用户照片
如果不知道要为其获取照片的用户的电子邮件地址,可以使用 ResolveNames 操作 获取可能的匹配项。 如果为 ResolveNames 元素的 ContactDataShape 属性指定“AllProperties”,则会为每个候选项返回大量数据,包括用户照片。 以下示例演示解析名称“Sadie”并返回每个候选项的所有属性的 XML 请求。
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"
xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/"
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
<soap:Header>
<t:RequestServerVersion Version="Exchange2013" />
</soap:Header>
<soap:Body>
<m:ResolveNames ReturnFullContactData="true" ContactDataShape="AllProperties">
<m:UnresolvedEntry>sadie</m:UnresolvedEntry>
</m:ResolveNames>
</soap:Body>
</soap:Envelope>
响应中将返回大量数据。 以下示例仅显示与用户照片相关的数据。 Photo 元素包含 Base64 编码的用户照片, (内容已缩短,以便) 可读性。
<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<m:ResolveNamesResponse xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
<m:ResponseMessages>
<m:ResolveNamesResponseMessage ResponseClass="Success">
<m:ResponseCode>NoError</m:ResponseCode>
<m:ResolutionSet TotalItemsInView="1" IncludesLastItemInRange="true">
<t:Resolution>
<t:Mailbox>
<t:Name>Sadie Daniels</t:Name>
<t:EmailAddress>sadie@contoso.com</t:EmailAddress>
<t:RoutingType>SMTP</t:RoutingType>
<t:MailboxType>Mailbox</t:MailboxType>
</t:Mailbox>
<t:Contact>
<t:DisplayName>Sadie Daniels</t:DisplayName>
<t:GivenName>Sadie</t:GivenName>
<t:Initials/>
<t:CompanyName>CONTOSO</t:CompanyName>
......
<t:Photo>/9j/4AAQSkZJRgABAQE...qKKKAP/2Q==</t:Photo>
......
</t:Contact>
</t:Resolution>
</m:ResolutionSet>
</m:ResolveNamesResponseMessage>
</m:ResponseMessages>
</m:ResolveNamesResponse>
</s:Body>
</s:Envelope>
使用 GetAttachment 操作获取联系人用户照片
可以使用 EWS 从邮箱中存储的联系人获取照片。 首先,使用 GetItem 操作返回所有属性,以便查找照片。 以下示例演示获取联系人项的 XML 请求。 为了提高可读性,项目 ID 已缩短。
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/"
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
<soap:Body>
<GetItem xmlns='http://schemas.microsoft.com/exchange/services/2006/messages'>
<ItemShape>
<t:BaseShape>AllProperties</t:BaseShape>
</ItemShape>
<ItemIds>
<t:ItemId Id="AAAAGECXAAA=" ChangeKey="EQAAABYAAAD2WuN+TpqwSrNP9JCCMKC0AABLzXRv"/>
</ItemIds>
</GetItem>
</soap:Body>
</soap:Envelope>
查找 HasPicture 元素以验证联系人是否具有关联的照片。 然后浏览附件集合,了解 IsContactPhoto 元素的值为 true 的附件。 以下响应示例仅显示相关数据。 为了提高可读性,将缩短 ID 值。
<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<m:GetItemResponse xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
<m:ResponseMessages>
<m:GetItemResponseMessage ResponseClass="Success">
<m:ResponseCode>NoError</m:ResponseCode>
<m:Items>
<t:Contact>
<t:ItemId Id="AAAAGECXAAA=" ChangeKey="EQAAABYAAAD2WuN+TpqwSrNP9JCCMKC0AABLzXRv"/>
<t:ParentFolderId Id="nIxIAAA=" ChangeKey="AQAAAA=="/>
<t:ItemClass>IPM.Contact</t:ItemClass>
<t:Subject>Hope Gross</t:Subject>
<t:Sensitivity>Normal</t:Sensitivity>
......
<t:Attachments>
<t:FileAttachment>
<t:AttachmentId Id="1LGlhgpgoA="/>
<t:Name>ContactPicture.jpg</t:Name>
<t:Size>6260</t:Size>
<t:LastModifiedTime>2011-03-09T16:55:55</t:LastModifiedTime>
<t:IsInline>false</t:IsInline>
<t:IsContactPhoto>true</t:IsContactPhoto>
</t:FileAttachment>
</t:Attachments>
......
<t:HasPicture>true</t:HasPicture>
</t:Contact>
</m:Items>
</m:GetItemResponseMessage>
</m:ResponseMessages>
</m:GetItemResponse>
</s:Body>
</s:Envelope>
接下来,将 GetAttachment 操作与 AttachmentId 配合使用,请求具有联系人照片的附件。 以下示例演示获取附件的 XML 请求。 为了提高可读性,ID 会缩短。
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/"
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
<soap:Body>
<GetAttachment xmlns="http://schemas.microsoft.com/exchange/services/2006/messages"
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
<AttachmentShape/>
<AttachmentIds>
<t:AttachmentId Id="1LGlhgpgoA="/>
</AttachmentIds>
</GetAttachment>
</soap:Body>
</soap:Envelope>
以下示例显示包含所请求附件相关信息的 XML 响应。 Content 元素包含用户照片的 Base64 编码字符串,为了提高可读性,在本示例中进行了缩短。
<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<m:GetAttachmentResponse xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
<m:ResponseMessages>
<m:GetAttachmentResponseMessage ResponseClass="Success">
<m:ResponseCode>NoError</m:ResponseCode>
<m:Attachments>
<t:FileAttachment>
<t:AttachmentId Id="+KsDBEr1LGlhgpgoA="/>
<t:Name>ContactPicture.jpg</t:Name>
<t:Content>/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAg...D//2Q==</t:Content>
</t:FileAttachment>
</m:Attachments>
</m:GetAttachmentResponseMessage>
</m:ResponseMessages>
</m:GetAttachmentResponse>
</s:Body>
</s:Envelope>
解码 Base64 编码的字符串
无论使用何种操作获取用户照片,都需要解码该字符串,以便在应用程序中使用它。 以下示例演示如何解码字符串,然后将其保存到本地计算机,以便应用程序稍后可以访问它。
// Convert the encoded string into a byte array.
byte[] data = System.Convert.FromBase64String(Photo);
// Create a memory stream to read the data.
MemoryStream ms = new MemoryStream(data);
// Save the data on your local computer as a JPG image.
using (FileStream file = new FileStream(ContactName + ".jpg", FileMode.Create, System.IO.FileAccess.Write))
{
byte[] bytes = new byte[ms.Length];
ms.Read(bytes, 0, (int)ms.Length);
file.Write(bytes, 0, bytes.Length);
ms.Close();
}