Resolver nomes ambíguos usando o EWS no Exchange 2013

Saiba como usar a API Gerenciada do EWS ou o EWS para resolver nomes ambíguos obtendo possíveis correspondências de Active Directory Domain Services (AD DS) ou uma pasta de contatos na caixa de correio do usuário.

Um usuário em sua organização recebe uma lista escrita à mão de nomes e endereços para funcionários que participaram de uma sessão de treinamento. Eles querem enviar um email com algumas informações adicionais para as pessoas da lista, mas não podem ler o endereço de email de todos. Se você quiser resolver esse problema para seus usuários em seu aplicativo, o EWS poderá ajudar. Você pode usar o método de API Gerenciada do ExchangeService.ResolveName EWS ou a operação ResolveNames EWS para retornar uma lista de possíveis correspondências para uma seleção de texto, como parte de um sobrenome. Os itens retornados podem ser caixas de correio de usuários públicos, grupos de distribuição e contatos.

Observe que o Exchange salva endereços de email com tipos de roteamento prefixados, como smtp ou sip, em uma matriz multivalue. O método ResolveName e a operação ResolveNames executam uma correspondência parcial em relação a cada valor dessa matriz quando você adiciona o tipo de roteamento no início do nome não resolvido, como "sip:User1". Se você não especificar um tipo de roteamento, o método ou operação será padrão para smtp, corresponda-o a uma propriedade de endereço smtp primário e não pesquise a matriz multivalue. Por exemplo, se você pesquisar o User1 e não incluir o prefixo sip, não receberá sip:User1@Contoso.com como resultado, mesmo que seja uma caixa de correio válida.

Você só pode especificar um nome ambíguo em uma única solicitação. Se você tiver uma lista de nomes ambíguos a serem resolvidos, precisará passar por loop pela lista e chamar o método ou a operação para cada entrada. Os candidatos da pasta Contatos de um usuário terão um valor de ID de item não nulo, que pode ser usado em uma chamada de método Contact.Bind ou na solicitação de operação GetItem para recuperar informações adicionais. Se o candidato for um grupo de distribuição, você poderá usar o método de API Gerenciada do EWS ExpandGroup(ItemId) ou a operação ExpandDL EWS para obter a lista de membros. Se o parâmetro returnContactDetails ou o atributo ReturnFullContactData EWS for definido como true, as entradas do Active Directory retornadas por meio de um método ResolveName ou da operação ResolveNames incluirão propriedades adicionais que descrevem o contato. O parâmetro returnContactDetails ou o atributo ReturnFullContactData não afeta os dados retornados para contatos e grupos de contatos.

Resolver nomes ambíguos usando a API Gerenciada do EWS

Você pode usar o método ResolveName para encontrar candidatos que correspondam ao nome ambíguo que você passa. Você pode usar sobrecargas do método ResolveName para pesquisar candidatos de cinco maneiras diferentes.

Tabela 1. Métodos ResolveName sobrecarregados

Method Como funciona
ResolveName(String) Localiza contatos na pasta Contatos do usuário e na GAL (Lista de Endereços Global) – nessa ordem. A variável de cadeia de caracteres é o nome ambíguo que você está tentando resolver.
ResolveName(String, ResolveNameSearchLocation, Boolean) Localiza contatos na pasta contatos padrão e/ou na GAL (Lista de Endereços Global). O valor da cadeia de caracteres é o nome ambíguo, o local de pesquisa especifica a pasta Contatos e/ou o GAL e o valor booliano indica se deve retornar as informações de contato completas.
ResolveName(String, ResolveNameSearchLocation, Boolean, PropertySet) Localiza contatos na pasta contatos padrão e/ou na GAL (Lista de Endereços Global). Esse método permite que você defina as propriedades retornadas.
ResolveName(String, IEnumerable<FolderId>, ResolveNameSearchLocation, Boolean) Localiza contatos em pastas de contato especificadas e/ou na GAL (Lista de Endereços Global). Você pode usar esse método para passar uma coleção de pastas para pesquisar. Isso permite que você procure em pastas de contato diferentes da pasta Contatos padrão.
ResolveName(String, IEnumerable<FolderId>, ResolveNameSearchLocation, Boolean, PropertySet) Localiza contatos na GAL (Lista de Endereços Global) e/ou em pastas de contato específicas. Esse método permite que você defina as propriedades retornadas.

Vamos começar com um exemplo simples. O exemplo a seguir mostra como resolver a cadeia de caracteres de texto "dan" e gerar o nome e o endereço de email de cada candidato encontrado. 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.

// Resolve the ambiguous name "dan".
   NameResolutionCollection resolvedNames = service.ResolveName("dan");
   // Output the list of candidates.
   foreach (NameResolution nameRes in resolvedNames)
   {
      Console.WriteLine("Contact name: " + nameRes.Mailbox.Name);
      Console.WriteLine("Contact e-mail address: " + nameRes.Mailbox.Address);
      Console.WriteLine("Mailbox type: " + nameRes.Mailbox.MailboxType);
   }

A resposta retorna um máximo de 100 candidatos, embora possa haver mais de 100 candidatos em potencial. Para determinar se apenas os primeiros 100 candidatos de um número maior de candidatos foram retornados, verifique o valor de IncludesAllResolutions no objeto NameResolutionCollection . Se o valor for verdadeiro, não haverá mais candidatos possíveis; se o valor for falso, o método só retornará os primeiros 100 de um número maior de candidatos em potencial.

Se você trabalha em uma organização grande, é provável que um nome como "dan" retorne o número máximo de 100 candidatos. Para reduzir o número de candidatos retornados, limite onde você pesquisa. O próximo exemplo usa a enumeração ResolveNameSearchLocation para especificar onde pesquisar para resolver o nome ambíguo.

// Resolve the ambiguous name "dan".
// Only use the Contacts folder.
   NameResolutionCollection resolvedNames = service.ResolveName("dan", ResolveNameSearchLocation.ContactsOnly, false);
   // Output the list of candidates.   
   foreach (NameResolution nameRes in resolvedNames)
   {
      Console.WriteLine("Contact name: " + nameRes.Mailbox.Name);
      Console.WriteLine("Contact e-mail address: " + nameRes.Mailbox.Address);
      Console.WriteLine("Mailbox type: " + nameRes.Mailbox.MailboxType);
   }

Se você armazenar seus contatos em uma pasta diferente da conhecida pasta Contatos, use um dos métodos sobrecarregados para especificar onde procurar candidatos. O exemplo a seguir cria uma lista de pastas para o método ResolveName com base na ID da pasta. O FolderId foi abreviado para legibilidade.

// Create a list to store folders to search.
List<FolderId> folders = new List<FolderId>();
// Add a folder to the list based on the FolderId.
folders.Add(new FolderId("AABR8mboAAA="));
// Resolve the ambiguous name "dan".
// Only use the folders specified.
NameResolutionCollection resolvedNames = service.ResolveName("dan", folders, ResolveNameSearchLocation.ContactsOnly, false);
   foreach (NameResolution nameRes in resolvedNames)
   {
      Console.WriteLine("Contact name: " + nameRes.Mailbox.Name);
      Console.WriteLine("Contact e-mail address: " + nameRes.Mailbox.Address);
      Console.WriteLine("Mailbox type: " + nameRes.Mailbox.MailboxType);
   }

Se você aplicar filtros e nenhum candidato for retornado, o NameResolutionCollection conterá zero entradas. Você pode verificar isso examinando a propriedade Count da coleção.

Resolver nomes ambíguos usando o EWS

Você pode usar a operação ResolveNames EWS para identificar possíveis candidatos para um nome ambíguo. O elemento UnresolvedEntry contém o nome ambíguo que você deseja resolver. O exemplo a seguir mostra como resolver o nome Sadie. Essa também é a solicitação XML que a API Gerenciada do EWS usa quando você usa o método ResolveName, exceto que ele usa um nome diferente para exemplos de saída válidos.

<?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>
    <ResolveNames xmlns="https://schemas.microsoft.com/exchange/services/2006/messages"
                  xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"
                  ReturnFullContactData="true">
      <UnresolvedEntry>Sadie</UnresolvedEntry>
    </ResolveNames>
  </soap:Body>
</soap:Envelope>

A resposta retorna um máximo de 100 candidatos, embora possa haver mais de 100 potenciais candidatos Para determinar se apenas os primeiros 100 candidatos de um número maior de candidatos foram retornados, verifique o valor do atributo IncludesLastItemInRange do elemento ResolutionSet . Se o valor for verdadeiro, não haverá mais candidatos possíveis; se o valor for falso, a operação só retornará os primeiros 100 de um número maior de candidatos em potencial.

O exemplo a seguir mostra a resposta XML quando um candidato é encontrado. Lembre-se de que o ResolutionSet pode conter até 100 candidatos, cada um representado pelo elemento Resolution e seus elementos filho.

<?xml version="1.0" encoding="utf-8" ?>
<soap:Envelope xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/" 
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
               xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <soap:Body>
    <ResolveNamesResponse xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages" 
                          xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types" 
                          xmlns="https://schemas.microsoft.com/exchange/services/2006/messages">
      <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:EmailAddresses>
                  <t:Entry Key="EmailAddress1">SMTP:Sadie@Contoso.com</t:Entry>
                </t:EmailAddresses>
                <t:ContactSource>ActiveDirectory</t:ContactSource>
              </t:Contact>
            </t:Resolution>
          </m:ResolutionSet>
        </m:ResolveNamesResponseMessage>
      </m:ResponseMessages>
    </ResolveNamesResponse>
  </soap:Body>
</soap:Envelope>

Você nem sempre vai encontrar candidatos para seu nome ambíguo. O exemplo a seguir mostra a resposta XML, como um erro, quando nenhum candidato é encontrado.

<?xml version="1.0" encoding="utf-8" ?>
<soap:Envelope xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/" 
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
               xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <soap:Body>
    <ResolveNamesResponse xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages" 
                          xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types" 
                          xmlns="https://schemas.microsoft.com/exchange/services/2006/messages">
      <m:ResponseMessages>
        <m:ResolveNamesResponseMessage ResponseClass="Error">
          <m:MessageText>No results were found.</m:MessageText>
          <m:ResponseCode>ErrorNameResolutionNoResults</m:ResponseCode>
          <m:DescriptiveLinkKey>0</m:DescriptiveLinkKey>
        </m:ResolveNamesResponseMessage>
      </m:ResponseMessages>
    </ResolveNamesResponse>
  </soap:Body>
</soap:Envelope>

Confira também