Obter fotos do usuário usando o EWS no Exchange

Saiba como obter fotos de usuário associadas a uma caixa de correio ou contato usando a API Gerenciada do EWS ou o EWS no Exchange.

É bom colocar um rosto em um nome. Se os usuários gostarem de colocar nomes nos rostos, seu aplicativo poderá solicitar uma imagem, normalmente uma foto, do Exchange que representa uma conta de email. Você pode obter uma foto de usuário armazenada em um servidor do Exchange para uma caixa de correio ou obter uma foto de contato de contatos armazenados em sua caixa de correio.

Você pode usar várias tecnologias diferentes para obter fotos de caixas de correio ou Active Directory Domain Services (AD DS). A melhor maneira de obter uma foto depende do tipo de contato do qual você deseja obter uma foto.

Tabela 1. Tecnologias a serem usadas para obter fotos do usuário com base no tipo de contato

Tipo de contato Tecnologias a serem usadas
Foto do usuário da caixa de correio
Obter uma foto de usuário de caixa de correio usando REST

Obter uma foto de usuário usando o EWS
Entrar em contato com a foto do usuário
Obter uma foto do usuário de contato usando a API Gerenciada do EWS

Obter uma foto de usuário usando o EWS

Obter uma foto de usuário de caixa de correio usando REST

Você pode solicitar fotos de usuário de um servidor exchange usando uma solicitação HTTPS GET padrão. Na solicitação, especifique o endereço da conta de email e um código de tamanho para a imagem, conforme mostrado no exemplo a seguir.

https://Exchange Server/ews/Exchange.asmx/s/GetUserPhoto?email=email address&size=size code

Use a operação GetUserSettings do serviço Autodiscover para recuperar a configuração ExternalEwsUrl , que contém a URL do ponto de extremidade do Exchange Web Services (EWS) e o local do manipulador HTTP do Exchange.asmx que retorna as fotos do usuário.

Cada código de tamanho indica a altura e a largura da imagem em pixels. Por exemplo, o código de tamanho HR48x48 retorna uma imagem de 48 pixels de altura por 48 pixels de largura. Os valores possíveis para o parâmetro de código de tamanho são os mesmos que os valores possíveis para o elemento SizeRequested . Se a solicitação especificar um tamanho que não está disponível, a maior foto disponível será retornada. Se nenhuma foto for armazenada no servidor exchange, a imagem da miniatura armazenada no AD DS para a conta será retornada.

Observação

O código de tamanho HR48x48 sempre retorna a imagem da miniatura do AD DS se estiver disponível.

O exemplo a seguir mostra como você pode usar a solicitação GET para recuperar a foto do usuário para Sadie e salvá-la no computador local.

// 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");
}

A solicitação retornará uma resposta HTTP.

Tabela 2. Códigos de resposta para uma solicitação GetUserPhoto

Código de resposta Descrição
200
Uma imagem está disponível para a conta de email especificada e a imagem binária está contida na resposta.
304
A imagem não foi alterada desde a última vez que o ETag foi retornado ao aplicativo.
404
Nenhuma imagem está disponível para a conta de email especificada.

Cache fotos do usuário

O Exchange retorna os dados com um tipo de conteúdo de imagem/jpeg, juntamente com uma coleção de valores de cabeçalho. O cabeçalho ETag é semelhante a uma chave de alteração. O valor é uma cadeia de caracteres que representa a última vez que a foto foi atualizada. A ETag permanece a mesma para a foto do usuário até que a foto seja alterada. Você pode enviar esse valor ETag para o servidor na solicitação HTTPS GET em um cabeçalho If-None-Match . Se a foto não tiver sido alterada desde a última solicitação, o servidor responderá com uma resposta HTTP 304 que indica como tal. Isso significa que você pode usar a foto de usuário que você solicitou e salvo anteriormente em vez de processar uma nova.

Obter uma foto do usuário de contato usando a API Gerenciada do EWS

Seu aplicativo pode usar a API Gerenciada do EWS para recuperar fotos para contatos, se o contato for armazenado em uma pasta de contato na caixa de correio do usuário. Para fazer isso, primeiro, localize o ItemId para o contato que você deseja usar. Em seguida, depois de associar a esse contato, carregue-o para a coleção de anexos. Se o contato tiver uma foto, a foto será um dos anexos. Faça loop pela coleção de anexos, verificando o valor da propriedade IsContactPhoto . Ao encontrar a foto de contato, você pode salvá-la no computador local e seu aplicativo pode acessá-la.

O exemplo a seguir mostra esse processo. Esse exemplo pressupõe que serviço seja um objeto ExchangeService válido e que o usuário tenha sido autenticado em um servidor 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);
   }
}

Obter uma foto de usuário usando o EWS

Se você estiver recebendo uma foto de usuário do AD DS, poderá usar a operação GetUserPhoto (se você souber o endereço de email) ou a operação ResolveNames (se não souber o endereço de email). Se você estiver recebendo uma foto de usuário de uma pasta de contatos na caixa de correio, use a operação GetItem seguida pela operação GetAttachment . Em ambos os casos, a foto é retornada como uma cadeia de caracteres codificada por Base64 na resposta XML.

Obter uma foto do usuário da caixa de correio usando a operação GetUserPhoto

Usar a operação GetUserPhoto é simples. Na solicitação XML, especifique o endereço de email do usuário e o tamanho da foto a ser retornada (no elemento SizeRequested ). O exemplo de solicitação XML a seguir mostra como obter uma foto para Sadie Daniels com 360 pixels de largura por 360 pixels de altura.

<?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="https://schemas.microsoft.com/exchange/services/2006/types"
               xmlns:m="https://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>

A seguir está a resposta XML. A foto codificada base64 está contida no elemento PictureData (o conteúdo foi abreviado para legibilidade).

<?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="https://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>

Obter uma foto do usuário da caixa de correio usando a operação ResolveNames

Se você não souber o endereço de email do usuário para quem está recebendo uma foto, poderá usar a operação ResolveNames para obter candidatos para uma possível correspondência. Se você especificar "AllProperties" para o atributo ContactDataShape do elemento ResolveNames , muitos dados, incluindo fotos de usuário, serão retornados para cada candidato. O exemplo a seguir mostra a solicitação XML para resolver o nome "Sadie" e retornar todas as propriedades para cada candidato.

<?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="https://schemas.microsoft.com/exchange/services/2006/messages"
               xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/"
               xmlns:t="https://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>

Muitos dados serão retornados na resposta. O exemplo a seguir mostra apenas os dados relevantes para a foto do usuário. O elemento Foto contém a foto do usuário codificada pelo Base64 (o conteúdo foi abreviado para legibilidade).

<?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="https://schemas.microsoft.com/exchange/services/2006/messages" 
         xmlns:t="https://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>

Obter uma foto do usuário de contato usando a operação GetAttachment

Você pode usar o EWS para obter fotos de contatos armazenados em sua caixa de correio. Primeiro, você usa a operação GetItem para retornar todas as propriedades para procurar fotos. O exemplo a seguir mostra uma solicitação XML para obter um item de contato. A ID do item foi encurtada para legibilidade.

<?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="https://schemas.microsoft.com/exchange/services/2006/types">
  <soap:Body>
    <GetItem xmlns='https://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>

Procure o elemento HasPicture para verificar se o contato tem uma foto associada. Em seguida, examine a coleção de anexos para um que tenha um valor de true para o elemento IsContactPhoto . O exemplo de resposta a seguir mostra apenas os dados relevantes. Os valores de ID são abreviados para legibilidade.

<?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="https://schemas.microsoft.com/exchange/services/2006/messages" 
         xmlns:t="https://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>

Em seguida, use a operação GetAttachment com o AttachmentId para solicitar o anexo que tem a foto de contato. O exemplo a seguir mostra a solicitação XML para obter o anexo. A ID é abreviada para legibilidade.

<?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="https://schemas.microsoft.com/exchange/services/2006/types">
  <soap:Body>
    <GetAttachment xmlns="https://schemas.microsoft.com/exchange/services/2006/messages"
    xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">
      <AttachmentShape/>
      <AttachmentIds>
         <t:AttachmentId Id="1LGlhgpgoA="/>
      </AttachmentIds>
    </GetAttachment>
  </soap:Body>
</soap:Envelope>

O exemplo a seguir mostra a resposta XML com as informações sobre o anexo solicitado. O elemento Content contém a cadeia de caracteres codificada base64 para a foto do usuário, abreviada neste exemplo para legibilidade.

<?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="https://schemas.microsoft.com/exchange/services/2006/messages" 
         xmlns:t="https://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>

Decodificar uma cadeia de caracteres codificada por Base64

Independentemente da operação que você usa para obter uma foto de usuário, você precisará decodificar essa cadeia de caracteres para poder usá-la em seu aplicativo. O exemplo a seguir mostra como decodificar a cadeia de caracteres e salvá-la no computador local para que o aplicativo possa acessá-la posteriormente.

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

Confira também