フォルダー内のメッセージへの増分の変更を取得する

デルタ クエリでは、一連の デルタ 関数呼び出しを使用して、フォルダー内のメッセージへの追加、削除、または更新に対してクエリを実行できます。 デルタ データを使用すると、毎回サーバーからユーザーのメッセージのセット全体をフェッチせずに、ユーザーのメッセージのローカル ストアの保守と同期が行えます。

ローカル ストア内のメッセージ項目を同期すると、最初の完全同期とその後の増分同期に デルタ クエリを使用できます。 通常、フォルダー内のすべてのメッセージ (ユーザーの受信トレイなど) の初期完全同期を行い、そのフォルダーに対する増分変更を定期的に取得します。

最初の同期以降に作成、更新、または削除された特定の種類のメッセージのみの増分変更を取得するには、フォルダー内のすべてのメッセージの初期同期を行い、後続のラウンドで特定の目的の種類の増分変更を取得します。 最初のデルタ要求でクエリ オプションとして目的の変更の種類を指定します。Microsoft Graph は、OData およびカスタム クエリ オプションを 応答で 指定された @odata.deltaLink に@odata.nextLink自動的にエンコードします。

フォルダー内のメッセージの変更を追跡する

デルタ クエリはフォルダー単位の操作です。 フォルダー階層内のメッセージの変更を追跡するには、各フォルダーを個別に追跡する必要があります。

通常、メール フォルダー内のメッセージ変更の追跡は、デルタ関数を使用した、1 つ以上の GET 要求のラウンドです。 最初の GET 要求は、デルタ関数を含めることを除いて、メッセージの取得方法とほぼ同じです。

GET https://graph.microsoft.com/v1.0/me/mailFolders/{id}/messages/delta

デルタ関数を使用した GET 要求は、次のいずれかを返します。

  • @odata.nextLink (デルタ関数の呼び出しと skipToken を使用した URL を含む)、または
  • @odata.deltaLink (デルタ関数の呼び出しと deltaToken を使用した URL を含む)。

これらのトークンは、クライアントに対して不透明な 状態トークン です。 変更追跡のラウンドを続行するには、最後の GET 要求から返された URL をコピーして、同じフォルダーの次の デルタ 関数呼び出しに適用します。 応答で返される @odata.deltaLink は、変更追跡の現在のラウンドが完了したことを示します。 @odata.deltaLink URL を保存して、次のラウンドを開始する際に使用することができます。

この記事の残りの部分には、次の 2 つの例が含まれています。

  • URL と @odata.deltaLink URL の使用方法@odata.nextLinkについては、例 1 を参照してください。
  • 最初のラウンド以降に作成されたメッセージのみを段階的に取得する方法については、 例 2 を参照してください。

メッセージのデルタ クエリでクエリ パラメーターを使用する

  • GET 要求と同様にクエリ パラメーターを $select 使用して、最適なパフォーマンスを得るために必要なプロパティのみを指定できます。 プロパティは id 常に返されます。
  • デルタ クエリは、メッセージの $select$top、および $expand をサポートします。
  • $filter$orderby に対するサポートには制限があります。
    • サポートされている唯一の $filter 式は、$filter=receivedDateTime+ge+{value} または $filter=receivedDateTime+gt+{value} です。
    • デルタ クエリに $filter を適用すると、最大 5,000 件のメッセージが返されます。
    • サポートされている唯一の $orderby 式は、$orderby=receivedDateTime+desc です。 式を $orderby 含めない場合、戻り値の順序は保証されません。
  • $search に対するサポートはありません。

さらに、デルタ クエリの応答で特定の種類の変更 (作成、更新、または削除) のみを返すには、必要に応じて、カスタム クエリ オプション changeTypeを使用して目的の種類の変更をフィルター処理できます。 指定できる値は、 createdupdated または deletedです。

GET /me/mailfolders/{id}/messages/delta?changeType=created
GET /me/mailfolders/{id}/messages/delta?changeType=updated
GET /me/mailfolders/{id}/messages/delta?changeType=deleted

オプションの要求ヘッダー

各デルタ クエリの GET 要求は、応答で 1 つ以上のメッセージのコレクションを返します。 必要に応じて、要求ヘッダー Prefer: odata.maxpagesize={x} を指定して、応答内の最大メッセージ数を設定できます。

例 1: フォルダー内のメッセージを同期する

次の例では、初めに 5 件のメッセージを含む特定のフォルダーを 2 回同期しています。

最初のラウンドには、フォルダー内の 5 つのメッセージをすべて同期するための一連の 3 つの要求が含まれます。

最初のラウンドの後、メッセージの 1 つが削除され、別の 1 つのメッセージが既読としてマークされます。 同期の 2 回目のラウンドでは、変更されていない他のメッセージは返さず、デルタ (削除と更新) のみを返します。

最初の要求のサンプル

この例では、指定したフォルダーが初めて同期されるため、初期同期要求には状態トークンは含まれません。 このラウンドは、そのフォルダー内のすべてのメッセージを返します。

最初の要求では、次のものを指定しています。

  • 応答の各メッセージの subject プロパティ、sender プロパティ、isRead プロパティを返す $select パラメーター。
  • オプションの要求ヘッダーである odata.maxpagesize。一度に 2 通のメッセージを返すよう指定しています。
GET https://graph.microsoft.com/v1.0/me/mailfolders/AQMkADNkNAAAgEMAAAA/messages/delta?$select=subject,sender,isRead HTTP/1.1
Prefer: odata.maxpagesize=2

最初の応答のサンプル

応答には、2 つのメッセージと応答ヘッダーが @odata.nextLink 含まれます。 URL は、取得するフォルダーにさらにメッセージがあることを示します。

{
  "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#Collection(message)",
  "@odata.nextLink": "https://graph.microsoft.com/v1.0/me/mailfolders('AQMkADNkNAAAgEMAAAA')/messages/delta?$skiptoken=GwcBoTmPuoTQWfcsAbkYM",
  "value": [
    {
      "@odata.type": "#microsoft.graph.message",
      "@odata.etag": "W/\"CQAAABYAAAARn2vdzPFjSbaPPxzjlzOTAAASsKZz\"",
      "subject": "Holiday hours update",
      "isRead": false,
      "sender": {
        "emailAddress": {
          "name": "Dana Swope",
          "address": "danas@contoso.com"
        }
      },
      "id": "AAMkADNkNAAASq35xAAA="
    },
    {
      "@odata.type": "#microsoft.graph.message",
      "@odata.etag": "W/\"CQAAABYAAAARn2vdzPFjSbaPPxzjlzOTAAAEfYB/\"",
      "subject": "Holiday promotion sale",
      "isRead": true,
      "sender": {
        "emailAddress": {
          "name": "Samantha Booth",
          "address": "samanthab@contoso.com"
        }
      },
      "id": "AQMkADNkNAAAVRMKAAAAA=="
    }
  ]
}

2 番目の要求のサンプル

2 番目の要求では、前の応答で返された @odata.nextLink URL が指定されます。 URL 内の と同じパラメーターがエンコードされて含まれるのskipTokenで、最初の要求と同じ$selectパラメーターを@odata.nextLink指定する必要がなくなりました。

GET https://graph.microsoft.com/v1.0/me/mailfolders/AQMkADNkNAAAgEMAAAA/messages/delta?$skiptoken=GwcBoTmPuoTQWfcsAbkYM HTTP/1.1
Prefer: odata.maxpagesize=2

2 番目の応答のサンプル

2 番目の応答は、フォルダーから取得するメッセージがまだあることを示す、フォルダー内の次の 2 つのメッセージと別の @odata.nextLink を返します。

{
  "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#Collection(message)",
  "@odata.nextLink": "https://graph.microsoft.com/v1.0/me/mailfolders('AQMkADNkNAAAgEMAAAA')/messages/delta?$skiptoken=GwcBoTmPKILK4jLH7mAd1lLU",
  "value": [
    {
      "@odata.type": "#microsoft.graph.message",
      "@odata.etag": "W/\"CQAAABYAAAARn2vdzPFjSbaPPxzjlqfdAAAEfYB+\"",
      "subject": "Microsoft Virtual Academy at Contoso",
      "isRead": true,
      "sender": {
        "emailAddress": {
          "name": "Elliot Hyde",
          "address": "elliot-hyde@tailspintoys.com"
        }
      },
      "id": "AQMkADNkNAAAgWkAAAA"
    },
    {
      "@odata.type": "#microsoft.graph.message",
      "@odata.etag": "W/\"CQAAABYAAAARn2vdzPFjSbaPPxzjlzOTAAAEfYB+\"",
      "subject": "New or modified user account information",
      "isRead": true,
      "sender": {
        "emailAddress": {
          "name": "Randi Welch",
          "address": "randiw@contoso.com"
        }
      },
      "id": "AQMkADNkNAAAgWJAAAA"
    }
  ]
}

3 番目の要求のサンプル

3 番目の要求は、最後の同期要求から返された最新の @odata.nextLink URL を引き続き使用します。

GET https://graph.microsoft.com/v1.0/me/mailFolders/AQMkADNkNAAAgEMAAAA/messages/delta?$skiptoken=GwcBoTmPKILK4jLH7mAd1lLU HTTP/1.1
Prefer: odata.maxpagesize=2

3 番目と最後の応答のサンプル

3 番目の応答は、フォルダー内の残りの唯一のメッセージと @odata.deltaLink 、このフォルダーの同期が完了したことを示す URL を返します。 URL を @odata.deltaLink 保存して使用して 、次のラウンドで同じフォルダーを同期します

{
  "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#Collection(message)",
  "@odata.deltaLink": "https://graph.microsoft.com/v1.0/me/mailfolders('AQMkADNkNAAAgEMAAAA')/messages/delta?$deltatoken=GwcBoTmPuoGNlgXgF1nyUNMXY",
  "value": [
    {
      "@odata.type": "#microsoft.graph.message",
      "@odata.etag": "W/\"CQAAABYAAAARn2vdzFPjSbaPPxzjlzOTAAAEfYB+\"",
      "subject": "Fabric CDN now available",
      "isRead": true,
      "sender": {
        "emailAddress": {
          "name": "Jodie Sharp",
          "address": "Jodie.Sharp@contoso.com"
        }
      },
      "id": "AAMkADk0MGFkODE3LWEAAA="
    }
  ]
}

次のラウンドで同じフォルダー内のメッセージを同期する

@odata.deltaLink最後のラウンドの最後の要求から を使用すると、そのフォルダー内で変更 (追加、削除、または更新) されたメッセージのみを取得できます。 次のラウンドの最初の要求は、同じ最大ページ サイズを維持することを前提とすると、次のようになります。

GET https://graph.microsoft.com/v1.0/me/mailfolders/AQMkADNkNAAAgEMAAAA/messages/delta?$deltatoken=GwcBoTmPuoGNlgXgF1nyUNMXY HTTP/1.1
Prefer: odata.maxpagesize=2

応答には @odata.deltaLink が含まれます。 これは、リモート メール フォルダー内のすべての変更が同期されていることを示します。 1 つのメッセージは削除され、その他のメッセージは変更されました。

{
  "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#Collection(message)",
  "@odata.deltaLink": "https://graph.microsoft.com/v1.0/me/mailfolders('AQMkADNkNAAAgEMAAAA')/messages/delta?$deltatoken=GwcBoTmPuoGNlgXgF1nyUNMXY",
  "value": [
    {
      "@odata.type": "#microsoft.graph.message",
      "id": "AAMkADk0MGFkODE3LWE4MmYtNDRhOS0Dh_6qB-pB2Sa2pUum19a6YAAKnLuxoAAA=",
      "@removed": {
        "reason": "deleted"
      }
    },
    {
      "@odata.type": "#microsoft.graph.message",
      "@odata.etag": "W/\"CQAAABYAAAARn2vdzPFjSbaPPxzjlzOTAAASsKZz\"",
      "subject": "Holiday hours update",
      "isRead": "true",
      "sender": {
        "emailAddress": {
          "name": "Dana Swope",
          "address": "danas@contoso.com"
        }
      },
      "id": "AAMkADNkNAAASq35xAAA="
    }
  ]
}

例 2: 変更の種類に基づいてフォルダー内のメッセージを同期する

次の例は、最初の同期以降に特定のフォルダーに作成されたメッセージのみを取得する方法を示しています。この例では、最初に 4 つのメッセージを含むフォルダーの同期を 2 回行います。

最初のラウンドでは、フォルダー内のすべての 4 つのメッセージを同期するための一連の 2 つの要求が含まれます。

最初のラウンドの後、さらに 2 つのメッセージが作成され、1 つのメッセージが削除され、もう 1 つのメッセージが読み取りとしてマークされます。

2 回目の同期では、変更の種類 (作成された 2 つの新しいメッセージ) のフォルダー内の created 変更のみが返されます。最後の同期以降も同じ、削除、または更新された他のメッセージは返されません。

指定された変更の種類を持つサンプルの初期要求

この例では、指定したフォルダーが初めて同期されるため、初期同期要求には状態トークンは含まれません。 このラウンドは、そのフォルダー内のすべてのメッセージを返します。

最初の要求では、次のものを指定しています。

  • 後続の changeType デルタ応答で 作成 されたメッセージのみを返すパラメーター。
  • 応答の各メッセージの subject プロパティ、sender プロパティ、isRead プロパティを返す $select パラメーター。
  • オプションの要求ヘッダーである odata.maxpagesize。一度に 2 通のメッセージを返すよう指定しています。
GET https://graph.microsoft.com/v1.0/me/mailFolders/AAMkAGUwNc4LTMzAAA=/messages/delta?changeType=created&$select=subject,sender,isRead HTTP/1.1
Prefer: odata.maxpagesize=2

指定された変更の種類を持つサンプルの初期応答

応答には、2 つのメッセージと応答ヘッダーが @odata.nextLink 含まれます。 URL は、取得するフォルダーにさらにメッセージがあることを示します。

{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#Collection(message)",
    "@odata.nextLink": "https://graph.microsoft.com/v1.0/me/mailFolders/AAMkAGUwNc4LTMzAAA=/messages/delta?$skiptoken=P4lmXpjPRrjB6haAQzSkpK89jYTVD2kVtOeXNRnfYzPbCs",
    "value": [
        {
            "@odata.type": "#microsoft.graph.message",
            "@odata.etag": "W/\"CQAAABYAAACQ2fKdhq8oSKEDSVrdi3lRAAId0MBP\"",
            "subject": "Inline Attachments Again",
            "isRead": true,
            "id": "AAMkAGUwNjQ4ZjIxLTQ3Y2YtNDViMi1iZjc4LT2fKdhq8oSKEDSVrdi3lRAAIei5gdAAA=",
            "sender": {
                "emailAddress": {
                    "name": "Megan Brown",
                    "address": "Megan.Brown@contoso.com"
                }
            }
        },
        {
            "@odata.type": "#microsoft.graph.message",
            "@odata.etag": "W/\"CQAAABYAAACQ2fKdhq8oSKEDSVrdi3lRAAId0MBR\"",
            "subject": "RE: Test Outlook TimeZone",
            "isRead": true,
            "id": "AAMkAGUwNjQ4ZjIxLTQ3Y2YtNDViMi1iZjc4LTMKdhq8oSKEDSVrdi3lRAAIei5geAAA=",
            "sender": {
                "emailAddress": {
                    "name": "Megan Brown",
                    "address": "Megan.Brown@contoso.com"
                }
            }
        }
    ]
}

指定された変更の種類を持つ 2 番目の要求のサンプル

2 番目の要求では、前の応答で返された @odata.nextLink URL が指定されます。 URL 内の がエンコードして含めるので、skipToken最初の要求と同じ$selectまたはchangeTypeパラメーターを@odata.nextLink指定する必要がなくなったことに注意してください。

GET https://graph.microsoft.com/v1.0/me/mailFolders/AAMkAGUwNc4LTMzAAA=/messages/delta?$skiptoken=P4lmXpjPRrjB6haAQzSkpK89jYTVD2kVtOeXNRnfYzPbCs HTTP/1.1
Prefer: odata.maxpagesize=2

指定された変更の種類を持つ 2 番目の応答のサンプル

2 番目の応答は、フォルダー内の次の 2 つのメッセージと、 @odata.deltaLink このフォルダーの同期が完了したことを示す URL を返します。 URL を @odata.deltaLink 保存して使用して 、次のラウンドで同じフォルダーを同期します

{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#Collection(message)",
    "@odata.deltaLink": "https://graph.microsoft.com/v1.0/me/mailFolders/AAMkAGUwNc4LTMzAAA=/messages/delta?$deltatoken=P4lmXpjPRrjB6haAQ_37roqIbjXe66KoV7SMlLH--Jgi8",
    "value": [
        {
            "@odata.type": "#microsoft.graph.message",
            "@odata.etag": "W/\"CQAAABYAAACQ2fKdhq8oSKEDSVrdi3lRAAId0MBu\"",
            "subject": "Your preview of the new Briefing email",
            "isRead": true,
            "id": "AAMkAGUwNjQ4ZjIxLTQ3Y2YtNDViMi1iZjc4LTMzNjMwNWM0ZGE2YQBGAAAAAADbrwBIJ",
            "sender": {
                "emailAddress": {
                    "name": "Cortana",
                    "address": "cortana@contoso.com"
                }
            }
        },
        {
            "@odata.type": "#microsoft.graph.message",
            "@odata.etag": "W/\"CQAAABYAAACQ2fKdhq8oSKEDSVrdi3lRAAId0MBw\"",
            "subject": "Char Coding HTML",
            "isRead": true,
            "id": "AAMkAGUwNjQ4ZjIxLTQ3Y2YtNDViMi1iZjc4LTMzNjMwNWM0ZGE2YQBGAAAAAADbrwBA=",
            "sender": {
                "emailAddress": {
                    "name": "John Doe",
                    "address": "John.Doe@contoso.com"
                }
            }
        }
    ]
}

指定した変更の種類に基づいて、次のラウンドで同じフォルダー内のメッセージを同期する

@odata.deltaLink最後のラウンドの最後の応答から を使用すると、そのフォルダーに追加されたメッセージのみを取得できます。 次のラウンドの最初の要求は、同じ最大ページ サイズを維持することを前提とすると、次のようになります。

GET https://graph.microsoft.com/v1.0/me/mailFolders/AAMkAGUwNc4LTMzAAA=/messages/delta?$deltatoken=P4lmXpjPRrjB6haAQ_37roqIbjXe66KoV7SMlLH--Jgi8 HTTP/1.1
Prefer: odata.maxpagesize=2

応答には @odata.deltaLink が含まれます。 これは、リモート メール フォルダー内のすべての変更が同期されていることを示します。 前回の同期以降に 2 つのメッセージが追加されました。最後の同期以降に更新 & 削除されたメッセージは、この差分応答では返されません。

{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#Collection(message)",
    "@odata.deltaLink": "https://graph.microsoft.com/v1.0/me/mailFolders/AAMkAGUwNc4LTMzAAA=/messages/delta?$skiptoken=EPuhZPRDHo-r3EBfscYE444fuGSBRV1eXex3JZkLzT9fRM",
    "value": [
        {
            "@odata.type": "#microsoft.graph.message",
            "@odata.etag": "W/\"CQAAABYAAACQ2fKdhq8oSKEDSVrdi3lRAAId0MCP\"",
            "subject": "Nested Attachment",
            "isRead": true,
            "id": "AAMkAGUwNjQ4ZjIxLTQ3Y2YtNDViMi1iZjc4LTMzNjMwNWM0ZGE2YQBGAAAAAADbrwBIJ",
            "sender": {
                "emailAddress": {
                    "name": "Patti Fernandez",
                    "address": "PattiF@contoso.com"
                }
            }
        },
        {
            "@odata.type": "#microsoft.graph.message",
            "@odata.etag": "W/\"CQAAABYAAACQ2fKdhq8oSKEDSVrdi3lRAAId0MCN\"",
            "subject": "Attachment Testing",
            "isRead": true,
            "id": "AAMkAGUwNjQ4ZjIxLTQ3Y2YtNDViMi1iZjc4LTMzNjMwNWM0ZGE2YQBGAAAAAADbrwZA=",
            "sender": {
                "emailAddress": {
                    "name": "Patti Fernandez",
                    "address": "PattiF@contoso.com"
                }
            }
        }
    ]
}