Determining the Id of a Sent Message by Using Extended Properties with the EWS Managed API

Occasionally, an Exchange Web Services (EWS) development scenario requires that you attain the identifier of sent message. Although you may expect to find the identifier of the sent message in the XML response that’s returned from calling EmailMessage.SendAndSaveCopy() , no such information exists in the response. The following example shows the CreateItemResponse that’s returned from calling EmailMessage.SendAndSaveCopy() by using the EWS Managed API.

<m:CreateItemResponse
      xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"
      xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">
   <m:ResponseMessages>
      <m:CreateItemResponseMessage ResponseClass="Success">
         <m:ResponseCode>NoError</m:ResponseCode>
         <m:Items />
      </m:CreateItemResponseMessage>
   </m:ResponseMessages>
</m:CreateItemResponse>

Because EWS sends messages asynchronously, the identifier of the message that’s saved in the Sent Items folder when you call EmailMessage.SendAndSaveCopy() is not available immediately, and therefore is not included in the XML response.

So what’s a developer to do, if basic message properties like subject are not unique enough to identify the sent message? Well, have no fear, for extended properties are here! Simply stamp your e-mail message with a custom extended property when you create the message, and then use that extended property to find the message in the Sent Items folder after it has been sent.

The following code example shows you how to create a custom extended property on an e-mail message, send the message, and then find the message by searching the Sent Items folder for an item that has the specified extended property value.

// Create the message and set some basic properties.
EmailMessage message = new EmailMessage(service);
message.Subject = "Message Subject";
message.Body = "This message was sent by using the EWS Managed API.";
message.ToRecipients.Add("User1@example.com");

// Create a custom extended property and add it to the message.
Guid myPropertySetId = new Guid("{20B5C09F-7CAD-44c6-BDBF-8FCBEEA08544}");
ExtendedPropertyDefinition myExtendedPropertyDefinition = new ExtendedPropertyDefinition(myPropertySetId, "MyExtendedPropertyName", MapiPropertyType.String);
message.SetExtendedProperty(myExtendedPropertyDefinition, "MyExtendedPropertyValue");

// Send the message and save a copy.
message.SendAndSaveCopy();

// Wait one second (while EWS sends and saves the message).
System.Threading.Thread.Sleep(1000);

// Now, find the saved copy of the message by using the custom extended property.
ItemView view = new ItemView(5);
SearchFilter searchFilter = new SearchFilter.IsEqualTo(myExtendedPropertyDefinition, "MyExtendedPropertyValue");
view.PropertySet = new PropertySet(BasePropertySet.IdOnly, ItemSchema.Subject, myExtendedPropertyDefinition);
FindItemsResults<Item> findResults = service.FindItems(WellKnownFolderName.SentItems, searchFilter, view);

// Process results.
foreach (Item myItem in findResults.Items)
{
   if (myItem is EmailMessage)
   {
      EmailMessage em = myItem as EmailMessage;
      Console.WriteLine(em.Subject);
      Console.WriteLine(em.Id.UniqueId);
   }
}

Note: The string value that is used to instantiate the Guid in this example was generated by using guidgen.exe within Microsoft Visual Studio 2008, but you can also use other Guid generation tools.

The following is the XML request that is generated by calling FindItems in the above code example.

<m:FindItem Traversal="Shallow">
   <m:ItemShape>
      <t:BaseShape>IdOnly</t:BaseShape>
      <t:AdditionalProperties>
         <t:FieldURI FieldURI="item:Subject" />
         <t:ExtendedFieldURI PropertySetId="20b5c09f-7cad-44c6-bdbf-8fcbeea08544" PropertyName="MyExtendedPropertyName" PropertyType="String" />
      </t:AdditionalProperties>
   </m:ItemShape>
   <m:IndexedPageItemView MaxEntriesReturned="5" Offset="0" BasePoint="Beginning" />
   <m:Restriction>
      <t:IsEqualTo>
         <t:ExtendedFieldURI PropertySetId="20b5c09f-7cad-44c6-bdbf-8fcbeea08544" PropertyName="MyExtendedPropertyName" PropertyType="String" />
         <t:FieldURIOrConstant>
            <t:Constant Value="MyExtendedPropertyValue" />
         </t:FieldURIOrConstant>
      </t:IsEqualTo>
   </m:Restriction>
   <m:ParentFolderIds>
      <t:DistinguishedFolderId Id="sentitems" />
   </m:ParentFolderIds>
</m:FindItem>

As the following XML response shows, the e-mail message that was created in the code example above is successfully located by using the custom extended property that was set when the e-mail message was created.

<m:FindItemResponse
      xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"
      xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">
   <m:ResponseMessages>
      <m:FindItemResponseMessage ResponseClass="Success">
         <m:ResponseCode>NoError</m:ResponseCode>
         <m:RootFolder IndexedPagingOffset="1" TotalItemsInView="1" IncludesLastItemInRange="true">
            <t:Items>
               <t:Message>
                  <t:ItemId Id="aeBAAA=" ChangeKey="CQAAA+s" />
                  <t:Subject>Message Subject</t:Subject>
                  <t:ExtendedProperty>
                     <t:ExtendedFieldURI PropertySetId="20b5c09f-7cad-44c6-bdbf-8fcbeea08544" PropertyName="MyExtendedPropertyName" PropertyType="String" />
                     <t:Value>MyExtendedPropertyValue</t:Value>
                  </t:ExtendedProperty>
               </t:Message>
            </t:Items>
         </m:RootFolder>
      </m:FindItemResponseMessage>
   </m:ResponseMessages>
</m:FindItemResponse>

Want to learn more about working with extended properties and search in the EWS Managed API? Check out the code examples that are available in the Working with Extended Properties and Working with Search sections of the Microsoft Exchange Web Services Managed API 1.0 SDK.