Synchronize items by using EWS in Exchange
Find out how to use the EWS Managed API or EWS to get a list of all items in a folder, or a list of changes that have occurred in a folder, in order to synchronize your client.
EWS in Exchange uses item synchronization and folder synchronization to sync mailbox content between the client and server. Item synchronization gets the initial list of items in a folder and then, over time, gets changes that have been made to those items and gets new items as well.
Note that before you can sync items to a client, you first have to sync the folder hierarchy. After the folder hierarchy is in place on the client, if you're performing item synchronization by using the EWS Managed API, you first get the initial list of items in the Inbox by using the ExchangeService.SyncFolderItems method. You then update the value of the cSyncState parameter during subsequent calls to get the list of changed items in the Inbox.
To perform item synchronization by using EWS, after you sync the folder hierarchy, you request the initial list of items in the Inbox by using the SyncFolderItems operation, parse the response, and then at some point in the future get the changes to the items in the mailbox, and parse the response. After the client receives the list of initial or changed items, it makes updates locally. How and when you retrieve changes in the future depends on the synchronization design pattern your application is using.
Note
SyncFolderItems operation is not supported for use against Office 365 Group mailboxes or Public Folders.
Get the list of all items or changed items by using the EWS Managed API
The following code example shows how to get an initial list of all items in the Inbox folder and then get a list of changes to items in the Inbox folder that have occurred since the previous synchronization. During the initial call to the SyncFolderItems method, set the cSyncState value to null. When the method completes, save the cSyncState value locally to use in the next SyncFolderItems method call. In both the initial call and the subsequent calls, the items are retrieved in batches of ten, by using successive calls to the SyncFolderItems method, until no more changes remain.
This example sets the propertySet parameter to IdOnly to reduce calls to the Exchange database, which is a synchronization best practice. In this example, we assume that service is a valid ExchangeService object binding and that cSyncState represents the sync state that was returned by a prior call to SyncFolderItems.
// Track whether there are more items available for download on the server.
bool moreChangesAvailable = false;
do
{
// Get a list of all items in the Inbox by calling SyncFolderHierarchy repeatedly until no more changes are available.
// The folderId parameter must be set to the root folder to synchronize,
// and must be same folder ID as used in previous synchronization calls.
// The propertySet parameter is set to IdOnly to reduce calls to the Exchange database,
// because any additional properties result in additional calls to the Exchange database.
// The ignoredItemIds parameter is set to null, so that no items are ignored.
// The maxChangesReturned parameter is set to return a maximum of 10 items (512 is the maximum).
// The syncScope parameter is set to Normal items, so that associated items will not be returned.
// The syncState parameter is set to cSyncState, which should be null in the initial call,
// and should be set to the sync state returned by the
// previous SyncFolderItems call in subsequent calls.
ChangeCollection<ItemChange> icc = service.SyncFolderItems(new FolderId(WellKnownFolderName.Inbox), PropertySet.IdOnly, null, 10, SyncFolderItemsScope.NormalItems, cSyncState);
// If the count of changes is zero, there are no changes to synchronize.
if (icc.Count == 0)
{
Console.WriteLine("There are no item changes to synchronize.");
}
// Otherwise, write all the changes included in the response
// to the console.
else
{
foreach (ItemChange ic in icc)
{
Console.WriteLine("ChangeType: " + ic.ChangeType.ToString());
Console.WriteLine("ItemId: " + ic.ItemId);
Console.WriteLine("===========");
}
}
// Save the sync state for use in future SyncFolderContent requests.
// The sync state is used by the server to determine what changes to report
// to the client.
string sSyncState = icc.SyncState;
// Determine whether more changes are available on the server.
moreChangesAvailable = icc.MoreChangesAvailable;
}
while (moreChangesAvailable);
The SyncFolderItems method is similar to the FindItems method in that it cannot return properties such as Body or Attachments. If you need properties that cannot be returned by the SyncFolderItems method, specify the IdOnly property set when you call SyncFolderItems, and then use the ExchangeService.LoadPropertiesForItems method to get the properties you require for the items that were returned by the SyncFolderItems method.
After you retrieve the list of new or changed items on the server, create or update the items on the client.
Get the initial list of items by using EWS
The following example shows the XML request to get the initial list of items in the Inbox by using the SyncFolderItems operation. This is also the XML request that the EWS Managed API sends when retrieving the list of items by using the SyncFolderItems method. The SyncState element of the SyncFolderItems operation is not included because this is the initial synchronization. This example sets the BaseShape element to IdOnly to reduce calls to the Exchange database, which is a synchronization best practice.
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"
xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<t:RequestServerVersion Version="Exchange2013" />
</soap:Header>
<soap:Body>
<m:SyncFolderItems>
<m:ItemShape>
<t:BaseShape>IdOnly</t:BaseShape>
</m:ItemShape>
<m:SyncFolderId>
<t:DistinguishedFolderId Id="inbox" />
</m:SyncFolderId>
<m:MaxChangesReturned>10</m:MaxChangesReturned>
<m:SyncScope>NormalItems</m:SyncScope>
</m:SyncFolderItems>
</soap:Body>
</soap:Envelope>
Get the response by using the SyncFolderItems method
The following example shows the XML response that is returned by the server after it processes the SyncFolderItems operation request from the client. The initial response includes Create elements for five items because all items are considered new during an initial synchronization. The values of some attributes and elements have 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="785"
MinorBuildNumber="6"
Version="V2_6"
xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types"
xmlns="http://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 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<m:SyncFolderItemsResponse xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
<m:ResponseMessages>
<m:SyncFolderItemsResponseMessage ResponseClass="Success">
<m:ResponseCode>NoError</m:ResponseCode>
<m:SyncState>H4sIAAA==</m:SyncState>
<m:IncludesLastItemInRange>true</m:IncludesLastItemInRange>
<m:Changes>
<t:Create>
<t:Message>
<t:ItemId Id="q04QAAAA=="
ChangeKey="CQAAABYAAABhFfgM7MNwSYx0VZ0GoBMJAAAATVdC"/>
</t:Message>
</t:Create>
<t:Create>
<t:Message>
<t:ItemId Id="q07AAAAA=="
ChangeKey="CQAAABYAAABhFfgM7MNwSYx0VZ0GoBMJAAAATVdB"/>
</t:Message>
</t:Create>
<t:Create>
<t:Message>
<t:ItemId Id="q1AwAAAA=="
ChangeKey="CQAAABYAAABhFfgM7MNwSYx0VZ0GoBMJAAAATVdA"/>
</t:Message>
</t:Create>
<t:Create>
<t:Message>
<t:ItemId Id="AAMkADBh=="
ChangeKey="CQAAABYAAABhFfgM7MNwSYx0VZ0GoBMJAAAATVc5"/>
</t:Message>
</t:Create>
<t:Create>
<t:Message>
<t:ItemId Id="AAMkADBh=="
ChangeKey="CQAAABYAAABhFfgM7MNwSYx0VZ0GoBMJAAAATVc4"/>
</t:Message>
</t:Create>
</m:Changes>
</m:SyncFolderItemsResponseMessage>
</m:ResponseMessages>
</m:SyncFolderItemsResponse>
</s:Body>
</s:Envelope>
After you retrieve the list of new items on the server, create the items on the client.
Get the changes since the last sync by using EWS
The following example shows the XML request to get the list of changes to items in the Inbox by using the SyncFolderItems operation. This is also the XML request that the EWS Managed API sends when retrieving the list of changes to the Inbox. This example sets the SyncState element value to the value returned in the previous response. And for demonstration purposes, this example sets the BaseShape element to AllProperties instead of IdOnly to show the additional properties returned. Setting the BaseShape element to IdOnly is a synchronization best practice. The value of SyncState has been shortened for readability.
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"
xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<t:RequestServerVersion Version="Exchange2010_SP2" />
</soap:Header>
<soap:Body>
<m:SyncFolderItems>
<m:ItemShape>
<t:BaseShape>AllProperties</t:BaseShape>
</m:ItemShape>
<m:SyncFolderId>
<t:DistinguishedFolderId Id="inbox" />
</m:SyncFolderId>
<m:SyncState>H4sIAAA==</m:SyncState>
<m:MaxChangesReturned>10</m:MaxChangesReturned>
<m:SyncScope>NormalItems</m:SyncScope>
</m:SyncFolderItems>
</soap:Body>
</soap:Envelope>
The following example shows the XML response that is returned by the server after it processes the SyncFolderItems operation request from the client. This response indicates that one item was updated, two items were created, the read flag of one item was changed, and one item was deleted since the prior synchronization. The values of some attributes and elements have 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="731" MinorBuildNumber="10" Version="V2_3"
xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types"
xmlns="http://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 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<m:SyncFolderItemsResponse xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
<m:ResponseMessages>
<m:SyncFolderItemsResponseMessage ResponseClass="Success">
<m:ResponseCode>NoError</m:ResponseCode>
<m:SyncState>H4sIAAAAAAAEAO29B2AcSZY==</m:SyncState>
<m:IncludesLastItemInRange>true</m:IncludesLastItemInRange>
<m:Changes>
<t:Update>
<t:Message>
<t:ItemId Id="q04QAAAA==" ChangeKey="CQAAABYAAADZGACZQpSgSpyNkexYe2b7AAAAird/" />
<t:ParentFolderId Id=" AgENAAAA" ChangeKey="AQAAAA==" />
<t:ItemClass>IPM.Note</t:ItemClass>
<t:Subject>RE: Company Soccer Team</t:Subject>
<t:Sensitivity>Normal</t:Sensitivity>
<t:DateTimeReceived>2013-08-29T15:22:10Z</t:DateTimeReceived>
<t:Size>23110</t:Size>
<t:Importance>Normal</t:Importance>
<t:InReplyTo>&lt;8e084ea1a5b64f97b95fa8a863a5869d@CH1SR01MB001.namsdf01.sdf.contoso.com&gt;</t:InReplyTo>
<t:IsSubmitted>false</t:IsSubmitted>
<t:IsDraft>false</t:IsDraft>
<t:IsFromMe>false</t:IsFromMe>
<t:IsResend>false</t:IsResend>
<t:IsUnmodified>false</t:IsUnmodified>
<t:DateTimeSent>2013-08-29T15:22:10Z</t:DateTimeSent>
<t:DateTimeCreated>2013-08-28T04:07:38Z</t:DateTimeCreated>
<t:DisplayCc />
<t:DisplayTo>All Employees</t:DisplayTo>
<t:HasAttachments>false</t:HasAttachments>
<t:Culture>en-US</t:Culture>
<t:EffectiveRights>
<t:CreateAssociated>false</t:CreateAssociated>
<t:CreateContents>false</t:CreateContents>
<t:CreateHierarchy>false</t:CreateHierarchy>
<t:Delete>true</t:Delete>
<t:Modify>true</t:Modify>
<t:Read>true</t:Read>
<t:ViewPrivateItems>true</t:ViewPrivateItems>
</t:EffectiveRights>
<t:LastModifiedName>Mara Whitley</t:LastModifiedName>
<t:LastModifiedTime>2013-08-28T16:53:35Z</t:LastModifiedTime>
<t:IsAssociated>false</t:IsAssociated>
<t:WebClientReadFormQueryString>?ae=Item&amp;a=Open&amp;t=IPM.Note&amp;id=&amp;exvsurl=1</t:WebClientReadFormQueryString>
<t:ConversationId Id="AAQkADkzNjJjODUzLWZhMDMtNDVkMS05ZDdjLWVmMDlkYjQ1Zjc4MwAQACAi+NTh0F5Eg5YDwpJsXPE=" />
<t:Sender>
<t:Mailbox>
<t:Name>Alfred Welker </t:Name>
<t:EmailAddress>Alfred.Welker@contoso.com</t:EmailAddress>
<t:RoutingType>SMTP</t:RoutingType>
<t:MailboxType>Mailbox</t:MailboxType>
</t:Mailbox>
</t:Sender>
<t:IsReadReceiptRequested>false</t:IsReadReceiptRequested>
<t:ConversationIndex>AQHM5V/ZICL41OHQXkSDlgPCkmxc8ZYxA3I4gAAP5UeAANHpbIAAEE+0gAABYhSAACGYTIAAA2+vgAAE81qAkhv0Eg==</t:ConversationIndex>
<t:ConversationTopic>Company Soccer Team</t:ConversationTopic>
<t:From>
<t:Mailbox>
<t:Name>Alfred Welker </t:Name>
<t:EmailAddress>Alfred.Welker@contoso.com</t:EmailAddress>
<t:RoutingType>SMTP</t:RoutingType>
<t:MailboxType>Mailbox</t:MailboxType>
</t:Mailbox>
</t:From>
<t:InternetMessageId>&lt;e5919a09c8fc4d64b6ffd3542e194fc3@BY2SR01MB609.contoso.com&gt;</t:InternetMessageId>
<t:IsRead>true</t:IsRead>
<t:References>namsdf01.sdf.contoso.com&gt;</t:References>
</t:Message>
</t:Update>
<t:Create>
<t:Message>
<t:ItemId Id="AQMkAD+" />
<t:ParentFolderId Id="AQMkA==" ChangeKey="AQAAAA==" />
<t:ItemClass>IPM.Note</t:ItemClass>
<t:Subject>RE: Review Proposal for Contoso</t:Subject>
<t:Sensitivity>Normal</t:Sensitivity>
<t:DateTimeReceived>2013-08-29T16:20:10Z</t:DateTimeReceived>
<t:Size>32515</t:Size>
<t:Importance>Normal</t:Importance>
<t:InReplyTo>&lt;e52a4de6b98d484887e141da094a2ce6@SN2SR01MB006.contoso.com&gt;</t:InReplyTo>
<t:IsSubmitted>false</t:IsSubmitted>
<t:IsDraft>false</t:IsDraft>
<t:IsFromMe>false</t:IsFromMe>
<t:IsResend>false</t:IsResend>
<t:IsUnmodified>false</t:IsUnmodified>
<t:DateTimeSent>2013-08-29T16:20:10Z</t:DateTimeSent>
<t:DateTimeCreated>2013-08-28T04:07:33Z</t:DateTimeCreated>
<t:DisplayCc />
<t:DisplayTo>Legal Team; Executives</t:DisplayTo>
<t:HasAttachments>false</t:HasAttachments>
<t:Culture>en-US</t:Culture>
<t:EffectiveRights>
<t:CreateAssociated>false</t:CreateAssociated>
<t:CreateContents>false</t:CreateContents>
<t:CreateHierarchy>false</t:CreateHierarchy>
<t:Delete>true</t:Delete>
<t:Modify>true</t:Modify>
<t:Read>true</t:Read>
<t:ViewPrivateItems>true</t:ViewPrivateItems>
</t:EffectiveRights>
<t:LastModifiedName>Mara Whitley</t:LastModifiedName>
<t:LastModifiedTime>2013-08-28T04:07:35Z</t:LastModifiedTime>
<t:IsAssociated>false</t:IsAssociated>
<t:WebClientReadFormQueryString>?ae=Item&amp;a=Open&amp;t=IPM.Note&amp;id=&amp;exvsurl=1</t:WebClientReadFormQueryString>
<t:ConversationId Id="AAQkADkzNjJjODUzLWZhMDMtNDVkMS05ZDdjLWVmMDlkYjQ1Zjc4MwAQAIsBEZp25UpElByLLUQFH6Q=" />
<t:Sender>
<t:Mailbox>
<t:Name>Hope Gross</t:Name>
<t:EmailAddress>Hope.Gross@contoso.com</t:EmailAddress>
<t:RoutingType>SMTP</t:RoutingType>
<t:MailboxType>Mailbox</t:MailboxType>
</t:Mailbox>
</t:Sender>
<t:IsReadReceiptRequested>false</t:IsReadReceiptRequested>
<t:ConversationIndex>AQHM5WBRiwERmnblSkSUHIstRAUfpJYw9fbSgAAAdm2AAAB6koAAAHTDgAADl6+AAAbxCYAABm5PgAACSA+AANx034AAEKGQgAAAfsiAAB7m3IAABG+ngAABPZyAAASUzoAAA2DNgAAAfKE=</t:ConversationIndex>
<t:ConversationTopic>Review Proposal for Contoso</t:ConversationTopic>
<t:From>
<t:Mailbox>
<t:Name>Hope Gross</t:Name>
<t:EmailAddress>Hope.Gross@contoso.com</t:EmailAddress>
<t:RoutingType>SMTP</t:RoutingType>
<t:MailboxType>Mailbox</t:MailboxType>
</t:Mailbox>
</t:From>
<t:InternetMessageId>&lt;bcdb185495834370a874a1e7ebedbb96@SN2SR01MB005.namsdf01.sdf.contoso.com&gt;</t:InternetMessageId>
<t:IsRead>true</t:IsRead>
<t:References>&lt;2d4d7d…</t:References>
</t:Message>
</t:Create>
<t:Create>
<t:Message>
<t:ItemId Id="Q04AAAAA==" ChangeKey="AAAirbnd" />
<t:ParentFolderId Id="AgENAAAA" ChangeKey="AQAAAA==" />
<t:ItemClass>IPM.Note</t:ItemClass>
<t:Subject>RE: Review Proposal for Contoso</t:Subject>
<t:Sensitivity>Normal</t:Sensitivity>
<t:DateTimeReceived>2013-08-29T15:30:10Z</t:DateTimeReceived>
<t:Size>29518</t:Size>
<t:Importance>Normal</t:Importance>
<t:InReplyTo>&lt;f0db3ead01db4fe087d98022149aa16f@SN2SR01MB001.namsdf01.sdf.contoso.com&gt;</t:InReplyTo>
<t:IsSubmitted>false</t:IsSubmitted>
<t:IsDraft>false</t:IsDraft>
<t:IsFromMe>false</t:IsFromMe>
<t:IsResend>false</t:IsResend>
<t:IsUnmodified>false</t:IsUnmodified>
<t:DateTimeSent>2013-08-29T15:30:10Z</t:DateTimeSent>
<t:DateTimeCreated>2013-08-28T04:07:36Z</t:DateTimeCreated>
<t:DisplayCc />
<t:DisplayTo>Legal Team; Executives</t:DisplayTo>
<t:HasAttachments>false</t:HasAttachments>
<t:Culture>en-US</t:Culture>
<t:EffectiveRights>
<t:CreateAssociated>false</t:CreateAssociated>
<t:CreateContents>false</t:CreateContents>
<t:CreateHierarchy>false</t:CreateHierarchy>
<t:Delete>true</t:Delete>
<t:Modify>true</t:Modify>
<t:Read>true</t:Read>
<t:ViewPrivateItems>true</t:ViewPrivateItems>
</t:EffectiveRights>
<t:LastModifiedName>Mara Whitley</t:LastModifiedName>
<t:LastModifiedTime>2013-08-28T04:07:38Z</t:LastModifiedTime>
<t:IsAssociated>false</t:IsAssociated>
<t:WebClientReadFormQueryString>?ae=Item&amp;a=Open&amp;t=IPM.Note&amp;id=&amp;exvsurl=1</t:WebClientReadFormQueryString>
<t:ConversationId Id="AAQkADkzNjJjODUzLWZhMDMtNDVkMS05ZDdjLWVmMDlkYjQ1Zjc4MwAQAIsBEZp25UpElByLLUQFH6Q=" />
<t:Sender>
<t:Mailbox>
<t:Name>Mack Chaves</t:Name>
<t:EmailAddress>Mack.Chaves@contoso.com</t:EmailAddress>
<t:RoutingType>SMTP</t:RoutingType>
<t:MailboxType>Mailbox</t:MailboxType>
</t:Mailbox>
</t:Sender>
<t:IsReadReceiptRequested>false</t:IsReadReceiptRequested>
<t:ConversationIndex>AQHM5WBRiwERmnblSkSUHIstRAUfpJYw9fbSgAAAdm2AAAB6koAAAHTDgAADl6+AAAbxCYAABm5PgAACSA+AANx034AAEKGQgAAAfsiAAB7m3IAABG+ngAABPZyAAASUzoAAA2DN</t:ConversationIndex>
<t:ConversationTopic>Review Proposal for Contoso</t:ConversationTopic>
<t:From>
<t:Mailbox>
<t:Name>Mack Chaves</t:Name>
<t:EmailAddress>Mack.Chaves@contoso.com</t:EmailAddress>
<t:RoutingType>SMTP</t:RoutingType>
<t:MailboxType>Mailbox</t:MailboxType>
</t:Mailbox>
</t:From>
<t:InternetMessageId>&lt;e52a4de6b98d484887e141da094a2ce6@SN2SR01MB006.namsdf01.sdf.contoso.com&gt;</t:InternetMessageId>
<t:IsRead>true</t:IsRead>
<t:References>namsdf01.sdf.contoso.com&gt;</t:References>
</t:Message>
</t:Create>
<t:ReadFlagChange>
<t:ItemId Id=" q07AAAAA==" ChangeKey="CQAAAA==" />
<t:IsRead>true</t:IsRead>
</t:ReadFlagChange>
<t:Delete>
<t:ItemId Id=" q1AwAAAA==" ChangeKey="CQAAAA==" />
</t:Delete>
</m:Changes>
</m:SyncFolderItemsResponseMessage>
</m:ResponseMessages>
</m:SyncFolderItemsResponse>
</s:Body>
</s:Envelope>
The SyncFolderItems operation is similar to the FindItems method in that it cannot return elements such as the Body or Attachments elements. If you need properties that cannot be returned by the SyncFolderItems operation, set the value of the BaseShape element to IdOnly when you call SyncFolderItems, and then use the GetItem operation to get the properties you require for the items that were returned by the SyncFolderItems operation.
After you retrieve the list of changed items on the server, update the items on the client.
Update the client
If you're using the EWS Managed API, after you get the list of new or changed items, use the LoadPropertiesForItems method to get properties on the new or changed items, compare the properties to the local values, and update the items on the client.
If you're using EWS, use the GetItem operation to get properties on the new or changed items and update the items on the client.