Exchange で EWS を使用してフォルダーを同期させる

クライアントを同期させるために、EWS マネージ API または EWS を使用して、フォルダーの一覧、または変更されたフォルダーの一覧を取得する方法について説明します。

Exchange の EWS では、アイテムの同期とフォルダーの同期を使用して、クライアントとサーバー間でメールボックスのコンテンツを同期します。 フォルダー同期では、ルート フォルダーにあるフォルダーの初期一覧が取得され、その後時間の経過とともに、それらのフォルダーに対して行われた変更が取得され、新しいフォルダーも取得されます。

EWS マネージ API を使用してフォルダー同期を行う場合は、まず ExchangeService.SyncFolderHierarchy メソッドを使用してルート フォルダー内のフォルダーの初期一覧を取得します。 その後、後続の呼び出し中に cSyncState パラメーターの値を更新して、新しいフォルダーと変更されたフォルダーの一覧を取得します。

EWS を使用してフォルダー同期を行うには、SyncFolderHierarchy 操作を使用してルート フォルダー内のフォルダーの初期一覧を要求し、応答を解析します。その後ある時点で、ルート フォルダー内のフォルダーに対する変更を取得し、応答を解析します。 クライアントは、初期のフォルダーまたは変更されたフォルダーの一覧を受信した後、ローカルに更新を実行します。 今後いつどのように変更を取得するかは、アプリケーションが使用している同期デザイン パターンによって異なります。

EWS マネージ API を使用してすべてのフォルダーまたは変更されたフォルダーの一覧を取得する

次のコード例は、ルート フォルダー内のフォルダーの初期一覧を取得した後、ルート フォルダー内のフォルダーに対して前回の同期後に行われた変更の一覧を取得する方法を示しています。 ExchangeService.SyncFolderHierarchy メソッドの最初の呼び出し中に、cSyncState 値を null に設定します。 メソッドが完了したら、次の SyncFolderHierarchy メソッド呼び出しで使用する cSyncState 値をローカルに保存します。 最初の呼び出しと後続の呼び出しの両方で、変更がなくなるまで、SyncFolderHierarchy メソッドの連続呼び出しを使用して、10 回のバッチ処理でフォルダーが取得されます。 次の使用例は、同期のベスト プラクティスである Exchange データベースへの呼び出しを減らすために、propertySet パラメーターを IdOnly に設定します。 この例では、 サービス が有効な ExchangeService オブジェクト バインドであり、 cSyncStateSyncFolderHierarchy の前の呼び出しによって返された同期状態を表すと仮定します。

// Get a list of all folders in the mailbox by calling SyncFolderHierarchy.
// The folderId parameter must be set to the root folder to synchronize. 
// 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 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 SyncFolderHierarchy call 
// in subsequent calls.
ChangeCollection<FolderChange> fcc = service.SyncFolderHierarchy(new FolderId(WellKnownFolderName.Root), PropertySet.IdOnly, cSyncState);
// If the count of changes is zero, there are no changes to synchronize.
if (fcc.Count == 0)
{
    Console.WriteLine("There are no folders to synchronize.");
}
// Otherwise, write all the changes included in the response 
// to the console. 
// For the initial synchronization, all the changes will be of type
// ChangeType.Create.
else
{
    foreach (FolderChange fc in fcc)
    {
        Console.WriteLine("ChangeType: " + fc.ChangeType.ToString());
        Console.WriteLine("FolderId: " + fc.FolderId);
        Console.WriteLine("===========");
    }
}
// Save the sync state for use in future SyncFolderItems requests.
// The sync state is used by the server to determine what changes to report
// to the client.
string fSyncState = fcc.SyncState;

サーバー上の新しいフォルダーまたは変更されたフォルダーの一覧を取得した後、クライアント上のフォルダーを作成または更新します

EWS を使用してフォルダーの初期一覧を取得する

次の例は、SyncFolderHierarchy 操作を使用して初期フォルダー階層を取得するための XML 要求を示しています。 これは、SyncFolderHierarchy メソッドを使用して初期フォルダーの一覧を取得するときに EWS マネージ API が送信する XML 要求でもあります。 SyncFolderHierarchy 操作の SyncState 要素は、これが最初の同期であるために含まれません。 次の例は、BaseShape 要素を IdOnly に設定して、Exchange データベースの呼び出し回数を減らしています。これは同期のベスト プラクティスです。

<?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="Exchange2013" />
  </soap:Header>
  <soap:Body>
    <m:SyncFolderHierarchy>
      <m:FolderShape>
        <t:BaseShape>IdOnly</t:BaseShape>
      </m:FolderShape>
      <m:SyncFolderId>
        <t:DistinguishedFolderId Id="root" />
      </m:SyncFolderId>
    </m:SyncFolderHierarchy>
  </soap:Body>
</soap:Envelope>

次の例は、サーバーが SyncFolderHierarchy 操作要求を処理した後に返す XML 応答を示しています。 最初の応答には、すべてのフォルダーで Create 要素が含まれます。最初の同期ではすべてのフォルダーが新規と見なされるからです。 一部の属性と要素の値は、読みやすくするために短くなっています。また、いくつかの Create 要素ブロックは、簡潔にするために削除されています。

<?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="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 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <m:SyncFolderHierarchyResponse xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages"
                                   xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">
      <m:ResponseMessages>
        <m:SyncFolderHierarchyResponseMessage ResponseClass="Success">
          <m:ResponseCode>NoError</m:ResponseCode>
          <m:SyncState>H4sIAA==</m:SyncState>
          <m:IncludesLastFolderInRange>true</m:IncludesLastFolderInRange>
          <m:Changes>
            <t:Create>
              <t:Folder>
                <t:FolderId Id="AAMkADM="
                            ChangeKey="AQAAABYA"/>
              </t:Folder>
            </t:Create>
            <t:Create>
              <t:Folder>
                <t:FolderId Id="AAMkADMzM="
                            ChangeKey="AQAAABY"/>
              </t:Folder>
            </t:Create>
            <t:Create>
              <t:Folder>
                <t:FolderId Id="AAMkAD/AAA="
                            ChangeKey="AQAAABYA"/>
              </t:Folder>
            </t:Create>
            <t:Create>
              <t:Folder>
                <t:FolderId Id="AAMkADBh="
                            ChangeKey="AQAAABYA"/>
              </t:Folder>
            </t:Create>
            ...
          </m:Changes>
        </m:SyncFolderHierarchyResponseMessage>
      </m:ResponseMessages>
    </m:SyncFolderHierarchyResponse>
  </s:Body>
</s:Envelope>

サーバー上の新しいフォルダーの一覧を受信した後、クライアント上にフォルダーを作成します。

EWS を使用して前回の同期以降の変更を取得する

次の例は、SyncFolderHierarchy 操作を使用してルート フォルダー内のフォルダーに対する変更の一覧を取得するための XML 要求を示しています。 これは、ルート フォルダーに対する変更の一覧を取得するときに EWS マネージ API が送信する XML 要求でもあります。 この例では、SyncState 要素の値を前回の応答で返された値に設定しています。 また、この例では、返される追加のプロパティを示すために、デモの目的で BaseShape 要素を IdOnly ではなく AllProperties に設定しています。 BaseShape 要素を IdOnly に設定することが、同期のベスト プラクティスです。 SyncState の値は、読みやすくするために短くなっています。

<?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="Exchange2013" />
  </soap:Header>
  <soap:Body>
    <m:SyncFolderHierarchy>
      <m:FolderShape>
        <t:BaseShape>AllProperties</t:BaseShape>
      </m:FolderShape>
      <m:SyncFolderId>
        <t:DistinguishedFolderId Id="root" />
      </m:SyncFolderId>
      <m:SyncState>H4sIAA==</m:SyncState>
    </m:SyncFolderHierarchy>
  </soap:Body>
</soap:Envelope>

次の例は、サーバーがクライアントからの SyncFolderHierarchy 操作要求を処理した後に返す XML 応答を示しています。 この応答は、前回の同期以降 1 つのフォルダーが更新され、1 つのフォルダーが作成されて、1 つのフォルダーが削除されたことを示しています。 SyncState 要素の値、Id 属性、および ChangeKey 属性は、読みやすくするために短くなっています。

要求に AllPropertiesBaseShape が含まれていたことを思い出してください。 これは単にデモの目的のためです。 運用環境では、BaseShape 要素を IdOnly に設定することをお勧めします。

<?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="745" MinorBuildNumber="21" Version="V2_3" 
           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 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <m:SyncFolderHierarchyResponse xmlns:m="https://schemas.microsoft.com/exchange/services/2006/messages" 
            xmlns:t="https://schemas.microsoft.com/exchange/services/2006/types">
      <m:ResponseMessages>
        <m:SyncFolderHierarchyResponseMessage ResponseClass="Success">
          <m:ResponseCode>NoError</m:ResponseCode>
          <m:SyncState>H4sIAAA</m:SyncState>
          <m:IncludesLastFolderInRange>true</m:IncludesLastFolderInRange>
          <m:Changes>
            <t:Update>
              <t:Folder>
                <t:FolderId Id="AAMkADM=" ChangeKey="AQAAABY" />
                <t:ParentFolderId Id="AQMkADMzADI1==" ChangeKey="AQAAAA==" />
                <t:FolderClass>IPF.Note</t:FolderClass>
                <t:DisplayName>Meeting Notes</t:DisplayName>
                <t:TotalCount>3</t:TotalCount>
                <t:ChildFolderCount>0</t:ChildFolderCount>
                <t:EffectiveRights>
                  <t:CreateAssociated>true</t:CreateAssociated>
                  <t:CreateContents>true</t:CreateContents>
                  <t:CreateHierarchy>true</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:UnreadCount>0</t:UnreadCount>
              </t:Folder>
            </t:Update>
            <t:Create>
              <t:Folder>
                <t:FolderId Id="AAMkADMzM=" ChangeKey="AQAAABYAA" />
                <t:ParentFolderId Id="AQMkO67A==" ChangeKey="AQAAAA==" />
                <t:FolderClass>IPF.Note</t:FolderClass>
                <t:DisplayName>Schedules</t:DisplayName>
                <t:TotalCount>0</t:TotalCount>
                <t:ChildFolderCount>0</t:ChildFolderCount>
                <t:EffectiveRights>
                  <t:CreateAssociated>true</t:CreateAssociated>
                  <t:CreateContents>true</t:CreateContents>
                  <t:CreateHierarchy>true</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:UnreadCount>0</t:UnreadCount>
              </t:Folder>
            </t:Create>
            <t:Delete>
              <t:FolderId Id="AAMkAD/AAA=" ChangeKey="AQAAAA==" />
            </t:Delete>
          </m:Changes>
        </m:SyncFolderHierarchyResponseMessage>
      </m:ResponseMessages>
    </m:SyncFolderHierarchyResponse>
  </s:Body>
</s:Envelope>

クライアントを更新する

EWS マネージ API を使用する場合は、新しいフォルダーまたは変更されたフォルダーの一覧を取得した後、Folder.Load メソッドを使用して新しいフォルダーまたは変更されたフォルダーのプロパティを取得し、それらのプロパティをローカル値と比較して、クライアント上のフォルダーを更新または作成します。

EWS を使用する場合は、GetFolder 操作を使用して新しいフォルダーまたは変更されたフォルダーのプロパティを取得して、クライアント上のフォルダーを更新または作成します。

関連項目