Access contacts as a delegate by using EWS in Exchange

Learn how to access contacts as a delegate by using the EWS Managed API or EWS in Exchange.

You can use the EWS Managed API or EWS to give a user access to a mailbox owner's Contacts folder. The delegate can then create contacts on behalf of the mailbox owner, and retrieve, update, and delete contacts from the mailbox owner's Contacts folder, depending on their permissions.

As a delegate, you use the same methods and operations to access a mailbox owner's Contacts folder that you use to access your own Contacts folder. The main difference is that you have to use explicit access to find or create a contact item, and then after you identify the item ID, you can use implicit access to get, update, or delete the item.

Table 1. EWS Managed API methods and EWS operations for accessing a contact as a delegate

If you want to… Use this EWS Managed API method… Use this EWS operation…
Create a contact as a delegate
Item.Save where the FolderId parameter provides explicit access to the mailbox owner's Contacts folder
CreateItem where the Mailbox element specifies the EmailAddress of the mailbox owner
Create multiple contacts as a delegate
ExchangeService.CreateItems where the FolderId parameter provides explicit access to the mailbox owner's Contacts folder
CreateItem where the Mailbox element specifies the EmailAddress of the mailbox owner
Resolve a contact as a delegate
ExchangeService.ResolveName where the FolderId parameter provides explicit access to the mailbox owner's Contacts folder
ResolveNames where the Mailbox element specifies the EmailAddress of the mailbox owner
Search for or find a contact as a delegate
ExchangeService.FindItems where the FolderId parameter provides explicit access to the mailbox owner's Contacts folder
FindItem where the Mailbox element specifies the EmailAddress of the mailbox owner
Get a contact as a delegate
Contact.Bind
GetItem
Update a contact as a delegate
Contact.Bind followed by Contact.Update
GetItem followed by UpdateItem
Delete a contact as a delegate
Contact.Bind followed by Contact.Delete
GetItem followed by DeleteItem

Note

In the code examples in this article, primary@contoso.com is the mailbox owner.

Prerequisite tasks

Before a user can access the mailbox owner's Contacts folder as a delegate, the user must be added as a delegate with permissions to the mailbox owner's Contacts folder.

Create a contact as a delegate by using the EWS Managed API

The EWS Managed API enables you to use the service object for the delegate user to create contacts for the mailbox owner. This example shows how to use the Save method to create a meeting and send meeting requests to the attendees.

This example assumes that service is a valid ExchangeService object for the delegate and that the delegate has been granted the appropriate permissions for the mailbox owner's Contacts folder.

 public static void DelegateAccessCreateContact(ExchangeService service)
{
    // Create the contact.
    Contact contact = new Contact(service);
    // Specify the name and how the contact should be filed.
    contact.GivenName = "Brian";
    contact.MiddleName = "David";
    contact.Surname = "Johnson";
    contact.FileAsMapping = FileAsMapping.SurnameCommaGivenName;
    // Specify the company name.
    contact.CompanyName = "Contoso";
    // Specify the business, home, and car phone numbers.
    contact.PhoneNumbers[PhoneNumberKey.BusinessPhone] = "425-555-0110";
    contact.PhoneNumbers[PhoneNumberKey.HomePhone] = "425-555-0120";
    contact.PhoneNumbers[PhoneNumberKey.CarPhone] = "425-555-0130";
    // Specify two email addresses.
    contact.EmailAddresses[EmailAddressKey.EmailAddress1] = 
        new EmailAddress("brian_1@contoso.com");
    contact.EmailAddresses[EmailAddressKey.EmailAddress2] = 
        new EmailAddress("brian_2@contoso.com");
    // Save the contact in the mailbox owner's Contacts folder.
    // This method call results in a CreateItem call to EWS. 
    // The contact identifier contains the context for the mailbox owner's 
    // Contact folder. Any additional actions take on this contact will 
    // be performed in the mailbox owner's mailbox. 
    contact.Save(new FolderId(WellKnownFolderName.Contacts, 
        "primary@contoso.com"));
    // Verify that the contact was created.
    // This method call results in a GetItem call to EWS
    // to load the display name property on the contact. 
    contact.Load(new PropertySet (ContactSchema.DisplayName));
    Console.WriteLine("\nContact created: " + contact.DisplayName + "\n");
}

Note that when you save the item, the Save method call must identify the mailbox owner's Contacts folder. If the mailbox owner's Contacts folder is not specified, the meeting request gets saved to the delegate's Contacts folder and not the mailbox owner's Contacts folder. You can include the mailbox owner's Contacts folder in the Save method call in two way. We recommend that you instantiate a new instance of the FolderId object by using the WellKnownFolderName and the SMTP address of the mailbox owner.

contact.Save(new FolderId(WellKnownFolderName.Contacts, "primary@contoso.com"));

However, you can also Bind to the Contacts folder first, and then use the ID of the folder in the Save method call. Be aware, however, that this creates an extra EWS call.

    // Identify the mailbox owner's SMTP address 
    // and bind to their Contacts folder.
    Mailbox primary = new Mailbox("primary@contoso.com"); 
    Folder primaryContacts = Folder.Bind(service, new FolderId(WellKnownFolderName.Contacts, primary)); 
…
    // Save the contact to the mailbox owner's Contacts folder.
    meeting.Save(primaryContacts.Id);

Create a contact as a delegate by using EWS

EWS enables you to use the service object for the delegate user to create contact items for the mailbox owner. This example shows how to use the CreateItem operation to create a contact.

This is also the XML request that the EWS Managed API sends when you use the Save method to create a contact.

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"
               xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"
               xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <t:RequestServerVersion Version="Exchange2007_SP1" />
  </soap:Header>
  <soap:Body>
    <m:CreateItem MessageDisposition="SaveOnly">
      <m:SavedItemFolderId>
        <t:DistinguishedFolderId Id="contacts">
          <t:Mailbox>
            <t:EmailAddress>primary@contoso.com</t:EmailAddress>
          </t:Mailbox>
        </t:DistinguishedFolderId>
      </m:SavedItemFolderId>
      <m:Items>
        <t:Contact>
          <t:FileAsMapping>LastCommaFirst</t:FileAsMapping>
          <t:GivenName>Brian</t:GivenName>
          <t:MiddleName>David</t:MiddleName>
          <t:CompanyName>Contoso</t:CompanyName>
          <t:EmailAddresses>
            <t:Entry Key="EmailAddress1">brian_1@contoso.com</t:Entry>
            <t:Entry Key="EmailAddress2">brian_2@contoso.com</t:Entry>
          </t:EmailAddresses>
          <t:PhoneNumbers>
            <t:Entry Key="BusinessPhone">425-555-0110</t:Entry>
            <t:Entry Key="HomePhone">425-555-0120</t:Entry>
            <t:Entry Key="CarPhone">425-555-0130</t:Entry>
          </t:PhoneNumbers>
          <t:Surname>Johnson</t:Surname>
        </t:Contact>
      </m:Items>
    </m:CreateItem>
  </soap:Body>
</soap:Envelope>

The server responds to the CreateItem request with a CreateItemResponse message that includes a ResponseCode element value of NoError, which indicates that the contact was created successfully. The response also contains the item ID of the newly created contact.

Resolve a contact as a delegate by using the EWS Managed API

To find a contact based on a possibly ambiguous name or term, you must use one of the ExchangeService.ResolveName methods that includes a FolderId parameter, so that you can specify the mailbox owner's Contacts folder.

private static void DelegateAccessResolveContacts(ExchangeService service)
{
    // Create a list to store folders to search.
    List<FolderId> folders = new List<FolderId>();
   
    // Add the mailbox owner's folder to the list.
    folders.Add(new FolderId(WellKnownFolderName.Contacts, 
        "primary@contoso.com"));
    
    // Resolve the ambiguous name "Johnson".
    // This method call results in a ResolveNames call to EWS.
    NameResolutionCollection resolvedNames = service.ResolveName(
        "johnson", folders, ResolveNameSearchLocation.ContactsOnly, true);
    // Output the list of candidate email addresses and contact names.
    foreach (NameResolution nameRes in resolvedNames)
    {
        Console.WriteLine("Contact e-mail address: " + nameRes.Mailbox.Address);
        Console.WriteLine("Contact ID: " + nameRes.Mailbox.Id);
    }
}

After the ResolveNames method call returns a response with an ID, you can get, update or delete the contact using the ID and implicit access—and you do not need to specify the mailbox owner's SMTP address.

Resolve a contact as a delegate by using EWS

EWS enables you to use the service object for the delegate user to resolve partial names in the mailbox owner's Contacts folder. This example shows how to use the ResolveNames operation to find meetings in the mailbox owner's Contacts folder that contain the word "johnson".

This is also the XML request that the EWS Managed API sends when you use the ResolveName method to resolve a contact.

 <?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"
               xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types"
               xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <t:RequestServerVersion Version="Exchange2007_SP1" />
  </soap:Header>
  <soap:Body>
    <m:ResolveNames ReturnFullContactData="true"
                    SearchScope="Contacts">
      <m:ParentFolderIds>
        <t:DistinguishedFolderId Id="contacts">
          <t:Mailbox>
            <t:EmailAddress>primary@contoso.com</t:EmailAddress>
          </t:Mailbox>
        </t:DistinguishedFolderId>
      </m:ParentFolderIds>
      <m:UnresolvedEntry>johnson</m:UnresolvedEntry>
    </m:ResolveNames>
  </soap:Body>
</soap:Envelope>

The server responds to the ResolveNames request with a ResolveNamesResponse message that includes a ResponseCode element value of NoError, which indicates that the operation completed successfully and found only one result, or ErrorNameResolutionMultipleResults if multiple results were found - which is what's shown in third code example based on the contact Create a contact as a delegate by using the EWS Managed API. The response also contains the ItemId of each result.

The value of the ItemId element has been shortened for readability.

 <?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <h:ServerVersionInfo MajorVersion="15"
                         MinorVersion="0"
                         MajorBuildNumber="893"
                         MinorBuildNumber="17"
                         Version="V2_10"
                         xmlns:h="https://schemas.microsoft.com/exchange/services/2006/types"
                         xmlns="https://schemas.microsoft.com/exchange/services/2006/types"
                         xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
  </s:Header>
  <s:Body>
    <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="Warning">
          <m:MessageText>Multiple results were found.</m:MessageText>
          <m:ResponseCode>ErrorNameResolutionMultipleResults</m:ResponseCode>
          <m:DescriptiveLinkKey>0</m:DescriptiveLinkKey>
          <m:ResolutionSet TotalItemsInView="2"
                           IncludesLastItemInRange="true">
            <t:Resolution>
              <t:Mailbox>
                <t:Name>brian_1@contoso.com</t:Name>
                <t:EmailAddress>brian_1@contoso.com</t:EmailAddress>
                <t:RoutingType>SMTP</t:RoutingType>
                <t:MailboxType>Contact</t:MailboxType>
                <t:ItemId Id="iMihAAA="
                          ChangeKey="EQAAABYAAADOilbYa8KaT7ZgMoTz2P+hAAABiPQo" />
              </t:Mailbox>
            </t:Resolution>
            <t:Resolution>
              <t:Mailbox>
                <t:Name>brian_2@contoso.com</t:Name>
                <t:EmailAddress>brian_2@contoso.com</t:EmailAddress>
                <t:RoutingType>SMTP</t:RoutingType>
                <t:MailboxType>Contact</t:MailboxType>
                <t:ItemId Id="iMihAAA="
                          ChangeKey="EQAAABYAAADOilbYa8KaT7ZgMoTz2P+hAAABiPQo" />
              </t:Mailbox>
            </t:Resolution>
          </m:ResolutionSet>
        </m:ResolveNamesResponseMessage>
      </m:ResponseMessages>
    </m:ResolveNamesResponse>
  </s:Body>
</s:Envelope>

Now that you have the ItemId for the contacts that match the ambiguous name, you can Get, update, or delete contact items as a delegate by using EWS by using the ItemId and implicit access—and you do not need to specify the mailbox owner's SMTP address.

Get, update, or delete contact items as a delegate by using the EWS Managed API

You can use the EWS Managed API to get, update, or delete a contact in the same way that you perform these actions when you're not using delegate access. The only difference is that the service object is for the delegate user. The item ID included in the Bind method call uniquely identifies the item in the mailbox store, in the mailbox owner's Contacts folder.

Table 2. EWS Managed API methods working with a contact as a delegate

Task EWS Managed API method Code example
Get a contact
Bind
Get an item by using the EWS Managed API
Update a contact
Bind followed by Update
Update an item by using the EWS Managed API
Delete a contact
Bind followed by Delete
Delete an item by using the EWS Managed API

Get, update, or delete contact items as a delegate by using EWS

You can use EWS to get, update, or delete a meeting or appointment contact in the same way that you perform these actions when you're not using delegate access. The only difference is that the service object is for the delegate user. The item ID included in the GetItem request uniquely identifies the item in the mailbox store, in the mailbox owner's Contacts folder.

Table 3. EWS operations for working with a contact as a delegate

Task EWS operation Sample
Get a contact
GetItem
Get an item by using EWS
Update a contact
GetItem followed by UpdateItem
Update an item by using EWS
Delete a contact
GetItem followed by DeleteItem
Delete an item by using EWS

See also