EWS 通知を Microsoft Graph に移行する際の考慮点

Last Update:

※ この記事は、Migrating EWS notifications to Microsoft Graph の抄訳です。最新の情報はリンク先をご確認ください。この記事は Microsoft 365 Copilot および GitHub Copilot を使用して抄訳版の作成が行われています。

プッシュ、プル、ストリーミングの各通知タイプをサポートする Exchange Web Services (EWS) の通知フレームワークから Microsoft Graph のサブスクリプション モデルへ移行することは、統合され、ステートレスで、イベント ドリブンなフレームワークへ移行することを意味します。このフレームワークは Exchange データ以外もサポートします。Microsoft Graph では Webhook によって通知が簡素化されますが、EWS のプッシュ、プル、長時間接続という複数のモデルを置き換えるには、アーキテクチャの再設計が必要です。

アプリケーションを移行するには、待機時間を短縮する リッチ通知 (rich notifications) や、安定したアイテム追跡を実現する 不変 ID (immutable IDs) など、Microsoft Graph のモダンな機能を組み込むことができます。移行を成功させるには、単純にイベントを待ち受けるだけではなく、ほぼリアルタイムの変更通知と、整合性を取るための デルタ クエリ (delta queries) を組み合わせるハイブリッド戦略が必要です。また、クラウド ネイティブ環境における厳格な同時実行数と可用性のしきい値にも対応する必要があります。

EWS 通知

アプリケーションでは、EWS 通知として 3 種類の通知を使用できます。それぞれ、待機時間、スケーラビリティ、接続管理の面で異なるトレードオフがあります。

  • プッシュ通知: イベントが発生するたびに、Exchange がアプリケーションでホストされているリスナー エンドポイントへ HTTP/HTTPS 要求を送信します。
  • プル通知: アプリケーションが定期的に Exchange を呼び出し、新しいイベントがあるかどうかを確認します。
  • ストリーミング通知: Exchange への長時間接続 (HTTP GET 経由) を確立し、イベントが発生したときにサーバーからクライアントへイベントをプッシュできるようにします。これにより、公開エンドポイントは不要になります。

Microsoft Graph 変更通知

Microsoft Graph の変更通知は 1 種類のみで、Webhook によって配信されます。これは、サブスクライブしたイベントが発生したときに、アプリケーションでホストされているリスナー エンドポイントへ送信される HTTP POST 要求です。このモデルでは、常時ポーリングを行わずに、ほぼリアルタイムの更新を実現できます。

より高度なシナリオでは、Microsoft Graph は Azure Event Hubs を通じた変更通知の配信もサポートしています。このオプションはエンタープライズ グレードのアプリケーションにより適しており、特に高スループットや分散処理の環境で、セキュリティ、スケーラビリティ、信頼性を高められます。

Microsoft Graph リッチ通知 (rich notifications)

Microsoft Graph リッチ通知を使用すると、変更通知に、そのイベントを発生させたアイテムに関する関連データを含めることができます。リアルタイム通知のシナリオでは、アイテムが届いてからクライアントに通知されるまでの待機時間を短縮でき、新しいメッセージの件名や送信者などの主要な詳細へすぐにアクセスできます。

リッチ通知は、従来の EWS 通知と比べて、特定のユース ケースを簡素化します。リアルタイム通知が主な要件であるアプリケーションでは、リッチ通知によって、アイテム データを取得するための後続の呼び出しを減らせます。

Microsoft Graph におけるプル通知と変更追跡

EWS では、前回の通知以降の変更を取得するために、通知は GetEvents 操作に依存していました。プッシュ通知とプル通知では、サブスクリプション マーカーとして機能するウォーターマークを利用できました。Microsoft Graph では、同等の機能がデルタ クエリによって提供されます。

デルタ クエリを使用すると、アプリケーションは前回のクエリ以降に追加、更新、削除されたデータだけを要求して変更を追跡できます。接続を維持したり、イベントをポーリングしたりする代わりに、Microsoft Graph から返された delta token をアプリケーションで保存し、後続の要求でそれを使用して前回の続きから処理できます。

Microsoft Graph は、以下のリソース タイプに対するデルタ クエリをサポートしています。

  • フォルダー: 個別のメール、連絡先、予定表フォルダー。
  • アイテム コレクション: メッセージ、連絡先、イベント、to do (タスク)。

予定表データについては、定期的なシリーズが 1 つのマスター イベントとして表される展開されていない定期的なデータを公開するイベント コレクションと、指定した時間範囲内の各回が個別のイベントとして展開される予定表ビューの両方で、デルタ クエリがサポートされます。

不変 ID (Immutable IDs)

Microsoft Graph では、メールボックス アイテムの不変 ID が導入されています。これは EWS には直接対応するものがない機能です。不変 ID は、メッセージ、連絡先、イベントなどのアイテムに対する安定した一意の識別子であり、メールボックス内でそのアイテムが存在している間は一定に保たれます。

EWS や Microsoft Graph の itemId 値は、アイテムがフォルダー間で移動されると変わりますが、不変 ID は変わりません。そのため、アプリケーションが ID を外部に保存している場合でも、メールボックス内でフォルダー移動が発生しても同じアイテムを参照し続けることができます。

不変 ID により、EWS と比べてアプリケーション設計を簡素化できます。EWS では、開発者がアイテム移動操作の後に外部保存されたアイテム識別子を追跡し、更新しなければならないことがよくありました。これは通知でよくあるユース ケースです。不変 ID では、その追加の追跡ロジックが不要になります。その結果、コードはより堅牢になり、保守しやすくなります。

ただし、メールボックス間やメールボックスからアーカイブ ストアへの移動など、メールボックスの境界をまたいでアイテムが移動される場合、不変 ID は無効になります。これは、アイテムに新しい ID が割り当てられるためです。メールボックスとアーカイブ間で移動されるアイテムをアプリケーションで追跡する必要がある場合は、代わりにカスタム拡張プロパティの使用を検討してください。

EWS と Microsoft Graph のサブスクリプションの違い

EWS では、通常、特定のメールボックス フォルダー、またはメールボックス内のすべてのフォルダーに対してサブスクリプションを作成します。

Microsoft Graph では、受信トレイや予定表などの特定のフォルダー タイプ、または messagescontactsevents などのリソース コレクションに対して変更通知サブスクリプションを作成できます。ただし、このモデルは EWS より制約があります。サポートされるフォルダー タイプは少なく、すべてのメールボックス フォルダーに対して同じ粒度を提供するものではありません。

たとえば、メールボックス内のすべてのメール フォルダーを EWS 通知でサブスクライブしている EWS アプリケーションを考えてみます。このアプリケーションでは、新しいメールが届いたことに加えて、メールが処理済みフォルダーへ移動されたことも検出する必要があります。Microsoft Graph では、代わりに /messages コレクションをサブスクライブして、メールボックス全体の通知を受け取ります。

移動を追跡するために、アプリケーションは作成イベントと削除イベントを監視し、parentFolderId を確認してアイテムの場所を判断します。標準のアイテム ID はメッセージがフォルダー間で移動されると変わるため、アプリケーションは不変 ID を使用して、メールボックス全体でアイテムの同一性を関連付けます。その後、アプリケーションはデルタ クエリを使用してこれらの変更の整合性を取り、新しく受信したメッセージと移動されたメッセージを区別できるようにします。

カスタム フォルダーのギャップ

Microsoft Graph サブスクリプションは、すべてのメールボックス フォルダーで機能するわけではありません。カスタム フォルダーや、従来のクライアント機能に関連付けられることが多いフォルダーには、Microsoft Graph の messagescontactseventsto do エンドポイントからアクセスできません。カスタム フォルダーについては、Exchange の外部で代替ソリューションを見つけるか、Webhook を利用できる messages などのサポート対象エンドポイントへコンテンツを移行できます。

ストリーミング サブスクリプションのギャップ

Microsoft Graph は EWS のストリーミング サブスクリプション モデルに相当する機能を提供していないため、ストリーミング通知を使用しているアプリケーションでは、通常、アーキテクチャの再設計が必要です。長時間接続を維持する代わりに、Microsoft Graph は Webhook ベースの通知に依存します。この通知には、公開アクセス可能なエンドポイントが必要です。

一般的なアプローチは、Microsoft Azure や同等のクラウド プロバイダーなど、安全な公開エンドポイントを公開できる高可用性プラットフォームでアプリケーションをホストすることです。このホスティングにより、信頼性、スケーラビリティ、受信通知の適切な処理を確保できます。モバイルやデスクトップなど、デバイス ベースの通知アプリケーションでは、簡略化された通知を以下のようなモバイル プッシュ サービスに転送するバックエンド処理レイヤーを使用できます。

  • Apple Push Notification service (APNs) for iOS
  • Firebase Cloud Messaging (FCM) for Android

より大量の通知を扱うシナリオやエンタープライズ シナリオでは、Azure Event Hubs によって、多数の通知を取り込んで処理するための、よりスケーラブルで回復性の高いパターンを利用できます。

ストリーミング サブスクリプションから移行することで、永続的な接続を維持することに伴うセキュリティと運用上のリスクも軽減されます。このアプローチにより、より堅牢でクラウドに適したアーキテクチャになります。

イベント タイプの違い

EWS は Microsoft Graph よりも細かいイベント タイプを提供します。移行時にはこの違いを考慮してください。

アイテムの作成と新しいメールの到着

  • EWS: NewMail (受信トレイ固有) または Created (その他のフォルダー)。
  • Microsoft Graph: Created (メッセージ、連絡先、イベントで統一)。

Microsoft Graph は専用の NewMail イベントを公開しません。新しいアイテムは単に created として表されます。つまり、created イベントは、新しく配信されたメールを表す場合もあれば、フォルダーへコピーまたは移動されたアイテムを表す場合もあります。

アプリケーションが NewMail 固有の動作に依存している場合は、receivedDateTimecreatedDateTime などのメッセージ プロパティを使用して、そのメッセージが配信されたものなのか、単に移動またはコピーされたものなのかを推測する必要があります。

✏️ 変更と更新

  • EWS: Modified
  • Microsoft Graph: Updated

これらの操作は機能的に同じです。

🗑️ 削除とライフサイクル

  • EWS: Deleted、Moved、Copied
  • Microsoft Graph: Deleted

Microsoft Graph は、明示的な moved または copied イベント タイプを公開しません。これらの操作を区別することが重要なシナリオでは、アプリケーションはフォルダー間のイベントを関連付け、immutableId を使用して意図を推測する必要があります。

たとえば、メッセージが受信トレイからカスタム フォルダーへ移動されると、Microsoft Graph は受信トレイで delete イベントを、移動先フォルダーで create イベントを生成します。immutableId は同じままであるため、これら 2 つのイベントを関連付けて、操作が移動であると識別できます。

一方、コピー操作では、移動先フォルダーで新しい immutableId を持つ create イベントが発生し、元のフォルダーには対応する削除イベントは発生しません。

これは、移動とコピーの操作が明示的に公開されていた EWS からの変化です。Microsoft Graph では、開発者はイベント パターンと識別子を使用して基になる操作を判断する、より解釈的なアプローチを採用する必要があります。

Tips

サブスクリプションを扱う場合、clientState 値は、GET 要求を使用して特定のサブスクリプションを取得したときにのみ返されます。サブスクリプションを列挙するときには含まれません。この場合、clientState プロパティは常に null です。

スロットリング

EWS と Microsoft Graph では異なるスロットリング モデルが使用されており、サブスクリプションはその違いが重要になる領域の 1 つです。Microsoft Graph では、Exchange によってメールボックスごとに 4 つの同時接続という厳格な制限が適用されます。この制限は、サブスクリプション処理によってトリガーされる要求を含む、すべてのアクティブな要求に適用されます。アプリケーションが大きなアイテムを処理したり、大量のイベントを扱ったりする場合、この制限を超えてスロットリングが発生する可能性があります。

よくある落とし穴は、各通知を独立した作業単位として扱い、それを処理するために並列要求を作成することです。負荷がかかった状態では、同時接続数の制限を超え、待機時間が増え、スロットリングが繰り返される可能性があります。その結果、全体のスループットは向上するどころか低下します。

これらの制約の中で効率的に動作するには、より制御された処理モデルを採用してください。受信イベントをキューに入れ、並列バーストではなく管理されたパイプラインで処理します。同じアイテムに対する複数の作成通知や更新通知など、近いタイミングで発生したイベントをまとめる重複排除ロジックを実装し、冗長な処理を避けてください。

さらに、メールボックスに対して同時に行われる要求が常に 4 つ以下になるように、クライアント側の同時実行制御 (たとえば、制限付きワーカー プールやセマフォ) を適用します。回復性とスループットをさらに高めるには、バックオフを伴う再試行ロジックを組み込み、アイテム全体の取得を繰り返すよりも、デルタ クエリなどの軽量な操作を優先してください。

Webhook エンドポイントのパフォーマンスとスロットリングのしきい値

Microsoft Graph Webhook と EWS プッシュ通知のもう 1 つの重要な違いは、通知エンドポイントのパフォーマンスと可用性がどのように適用されるかです。Microsoft Graph は Webhook の応答性を積極的に監視し、しきい値を超えた場合にバック プレッシャーを適用します。

10 分間のウィンドウ内で、10 秒を超える応答が 10% を超えると、slow state がトリガーされます。この状態になると、Microsoft Graph はすべての新しい通知について、配信前に約 10 秒の遅延を挿入します。リアルタイム通知のシナリオでは、これにより目に見える待機時間が発生し、通知が利用者の期待と同期しなくなる可能性があります。

より深刻な drop state は、同じ 10 分間のウィンドウ内で、10 秒を超える応答が 15% を超えるとトリガーされます。この場合、Microsoft Graph は最大 10 分間、エンドポイントへの新しい通知の配信を一時的に停止します。この期間中に生成された通知は、エンドポイントの回復後に再送されないため、イベントの取りこぼしにつながる可能性があります。

Microsoft Graph Webhook は、リスニング エンドポイントに対して、EWS のプッシュ通知やストリーミング通知よりも厳しいパフォーマンス要件を課します。アプリケーションは受信をすばやく確認応答し、回復性と復旧のためのロジックを組み込む必要があります。通知の取りこぼしや遅延に対応するには、データの一貫性を維持するために、デルタ クエリを使用した整合性確認プロセスが必要です。