减少 Outlook 资源丢失的订阅和更改通知(预览版)Reduce missing subscriptions and change notifications for Outlook resources (preview)

订阅 Outlook 资源更改通知的应用可能会删除其订阅并错过一些更改通知。Apps subscribing to change notifications for Outlook resources might get their subscriptions removed and miss some change notifications. 应用程序应实现逻辑以进行检测并恢复丢失的内容,以及恢复连续更改通知流程。Apps should implement logic to detect and recover from the loss, and resume a continuous change notification flow.

Outlook 中的某些事件可能导致订阅被删除。Certain events in Outlook can cause a subscription to be removed. 这些事件包括:These events include:

  • 用户的密码已重置User's password has been reset
  • 用户的设备不合规User's device is out of compliance
  • 用户的帐户已吊销User's account has been revoked

发生此类事件时,Outlook 将发送特殊生命周期通知 subscriptionRemovedWhen such an event happens, Outlook sends a special lifecycle notification, subscriptionRemoved.

如果无法将更改通知传递到应用,Outlook 还会发送另一个生命周期通知 missedOutlook also sends another lifecycle notification, missed, if a change notification cannot be delivered to an app.

订阅 Outlook 资源更改通知的应用(如邮件事件)应收听 subscriptionRemovedmissed 信号,并执行以下操作:An app subscribing to change notifications for Outlook resources, such as message and event, should listen to the subscriptionRemoved and missed signals and do the following:

  • 收到 subscriptionRemoved 生命周期通知后,该应用应重新创建订阅以保持连续流程。Upon receiving a subscriptionRemoved lifecycle notification, the app should recreate the subscription in order to maintain a continuous flow.
  • 收到 missed 生命周期通知后,该应用使用 Microsoft Graph 重新同步资源数据。On receiving a missed lifecycle notification, the app should resynchronize resource data using Microsoft Graph.

若要接收生命周期通知,你可以使用已接收更改通知的现有 notificationUrl 终结点,也可以注册单独的 lifecycleNotificationUrl 以在单独的终结点中接收 subscriptionRemovedmissed 生命周期通知。To receive lifecycle notifications, you can use the existing notificationUrl endpoint that already receives change notifications, or you can register a separate lifecycleNotificationUrl to receive subscriptionRemoved and missed lifecycle notifications in a separate endpoint.

创建订阅Creating a subscription

创建订阅时,你必须使用 lifecycleNotificationUrl 属性指定单独的通知终结点。When creating a subscription, you must specify a separate notification endpoint using the lifecycleNotificationUrl property. 如果指定终结点,所有当前和未来类型的生命周期通知都将传递到那里。If you specify the endpoint, all current and future types of lifecycle notifications will be delivered there. 否则,将无法传递 subscriptionRemovedmissed 生命周期通知。Otherwise, subscriptionRemoved and missed lifecycle notifications will not be delivered.

注意: 只能使用 Microsoft Graph beta API 设置或读取 lifecycleNotificationUrl 属性。Note: The lifecycleNotificationUrl property can only be set or read using Microsoft Graph beta APIs. 但是,使用 beta API 创建的订阅与使用 v1.0 创建的订阅存储在同一个生产环境中,因此除了使用 v1.0 API 创建的订阅外,还可以实现新 Outlook 流程。However, subscriptions created using beta APIs are stored in the same production environment as those created using v1.0, so you can implement the new Outlook flow in addition to your subscriptions creating using v1.0 APIs.

通过 v1.0 API 创建的订阅将收到生命周期通知。Subscriptions created via the v1.0 APIs will receive lifecycle notifications.

订阅请求示例Subscription request example

POST https://graph.microsoft.com/beta/subscriptions
Content-Type: application/json
{
  "changeType": "created,updated",
  "notificationUrl": "https://webhook.azurewebsites.net/api/resourceNotifications",
  "lifecycleNotificationUrl": "https://webhook.azurewebsites.net/api/lifecycleNotifications",
  "resource": "/users/{id}/messages",
  "expirationDateTime": "2019-03-20T11:00:00.0000000Z",
  "clientState": "<secretClientState>"
}

重要提示: 对两个通知 URL 使用相同的主机名。Important: Use the same hostname for both notifications URLs.

注意: 需要按照管理订阅中的说明验证两个终结点。Note: You need to validate both endpoints as described in Managing subscriptions. 如果选择对两个终结点使用相同的 URL,将收到并响应两个验证请求。If you choose to use the same URL for both endpoints you will receive and respond to two validation requests.

注意: 无法更新 (PATCH) 现有订阅以添加 lifecycleNotificationUrl 属性。Note: You cannot update (PATCH) the existing subscriptions to add the lifecycleNotificationUrl property. 应删除此类现有订阅,创建新订阅并指定 lifecycleNotificationUrl 属性。You should remove such existing subscriptions, and create new subscriptions and specify the lifecycleNotificationUrl property. 没有 lifecycleNotificationUrl 属性的现有订阅将接收 subscriptionRemovedmissedExisting subscriptions without lifecycleNotificationUrl property will not receive the subscriptionRemoved and missed.

响应 subscriptionRemoved 通知Responding to subscriptionRemoved notifications

subscriptionRemoved 生命周期通知会通知你订阅已删除,如果想要继续接收更改通知,应重新创建。The subscriptionRemoved lifecycle notification informs you that a subscription has been removed and should be recreated, if you want to continue receiving change notifications.

可以创建长期订阅(3 天),更改通知将开始流向 notificationUrlYou can create a long-lived subscription (3 days), and change notifications will start flowing to the notificationUrl. 但是,资源数据的访问条件可能会随时间变化。However, the conditions of access to the resource data might change over time. 例如,Outlook 服务中的事件可能会发生,需要应用程序对于用户重新进行身份验证。For example, an event in the Outlook service might occur that requires the app to re-authenticate the user. 在此类情况下,流程如下所示:In such a case, the flow is as follows:

  1. Outlook 检测到需要从 Microsoft Graph 删除订阅。Outlook detects that a subscription needs to be removed from Microsoft Graph.

    这些事件没有固定的节奏。There is no set cadence for these events. 对于某些资源,它们可能经常发生,而对于其他资源,几乎永远不会发生。They might occur frequently for some resources, and almost never for others.

  2. Microsoft Graph 将发送 subscriptionRemoved 生命周期通知到 lifecycleNotificationUrl(如果指定)。Microsoft Graph sends a subscriptionRemoved lifecycle notification to the lifecycleNotificationUrl (if specified).

  3. 可以通过为同一资源创建新订阅来响应此生命周期通知。You can respond to this lifecycle notification by creating a new subscription for the same resource. 为此,你需要提供有效的访问令牌;在某些情况下,这意味着应用程序需要重新验证用户以获取新的有效访问令牌。To do this, you need to present a valid access token; in some cases this means the app needs to re-authenticate the user to obtain a new valid access token.

  4. 如果成功创建新订阅,更改通知将再次开始流动。If you successfully create a new subscription, change notifications will start flowing again. 但是,如果失败(例如,应用程序无法获取有效的访问令牌),将不会发送更改通知。However, if you fail (for example, the app can't obtain a valid access token), change notifications will not be sent.

  5. 创建新订阅后,可以同步资源数据以标识任何缺失的更改。After creating the new subscription, you can sync the resource data to identify any missing changes.

subscriptionRemoved 通知示例subscriptionRemoved notification example

{
  "value": [
    {
      "subscriptionId":"<subscription_guid>",
      "subscriptionExpirationDateTime":"2019-03-20T11:00:00.0000000Z",
      "tenantId": "<tenant_guid>",
      "clientState":"<secretClientState>",
      "lifecycleEvent": "subscriptionRemoved"
    }
  ]
}

有关此类型通知的一些注意事项:A few things to note about this type of notification:

  • "lifecycleEvent": "subscriptionRemoved" 字段将此通知指定为与订阅删除相关。The "lifecycleEvent": "subscriptionRemoved" field designates this notification as related to subscription removal. 其他类型的生命周期通知也是可能的,将来会引入新的通知。Other types of lifecycle notifications are also possible, and new ones will be introduced in the future.
  • 生命周期通知不包含有关特定资源的任何信息,因为它与资源更改无关,而与订阅状态更改有关。The lifecycle notification does not contain any information about a specific resource, because it is not related to a resource change, but to the subscription state change.
  • 与更改通知类似,生命周期通知可以一起批处理(在数组中),每个通知都有一个可能不同的 lifecycleEvent 值。Similar to change notifications, lifecycle notifications can be batched together (in the value array), each with a possibly different lifecycleEvent value. 相应地批处理每个生命周期通知。Process each lifecycle notification in the batch accordingly.

注意: 有关传递更改通知时发送的数据的完整说明,请参阅 changeNotificationCollectionNote: for a full description of the data sent when change notifications are delivered, see changeNotificationCollection.

要采取的操作Actions to take

  1. 通过使用 202 - Accepted 来响应 POST 调用,确认收到生命周期通知。Acknowledge the receipt of the lifecycle notification, by responding to the POST call with 202 - Accepted.
  2. 验证生命周期通知的真实性。Validate the authenticity of the lifecycle notification.
  3. 确保应用程序具有执行下一步操作的有效访问令牌。Ensure that the app has a valid access token to take the next step.

注意: 如果使用其中一个身份验证库,他们将通过重复使用有效的缓存令牌或获取新令牌,其中包括要求用户(使用新密码)再次登录来处理此问题。Note: If you're using one of the authentication libraries, they will handle this for you by either reusing a valid cached token, or obtaining a new token, including asking the user to sign in again (with a new password). 请注意,获取新令牌可能会失败,因为访问条件可能已更改,并且可能不再允许调用者访问资源数据。Note that obtaining a new token might fail, because the conditions of access might have changed, and the caller might no longer be allowed access to the resource data.

  1. 使用此处描述的标准流程创建新订阅。Create a new subscription using the standard process described here.

注意: 此操作可能会失败,因为系统执行的授权检查可能会拒绝应用程序或用户访问资源。Note: This action might fail, because the authorization checks performed by the system might deny the app or the user access to the resource. 应用程序可能需要从用户处获取新的访问令牌以成功重新授权订阅。It might be necessary for the app to obtain a new access token from the user to successfully reauthorize a subscription. 以后可以随时重试这些操作,例如,当访问条件发生变化时。You can retry these actions later, at any time; for example, when the conditions of access have changed. 从生命周期通知发送到应用程序成功重新创建订阅的时间段内的任何资源更改都将丢失。Any resource changes in the time period from when the lifecycle notification was sent, to when the app recreates the subscription successfully, will be lost. 该应用需要自己获取这些更改。The app will need to fetch those changes on its own.

  1. 创建新订阅后,从收到此资源的更改通知的上次已知时间同步任何缺失的资源数据;例如:GET https://graph.microsoft.com/v1.0/users/{id}/messages?$filter=createdDateTime+ge+{LastTimeNotificationWasReceived}After creating the new subscription, sync any missing resource data from the last known time you received a change notification for this resource; for example: GET https://graph.microsoft.com/v1.0/users/{id}/messages?$filter=createdDateTime+ge+{LastTimeNotificationWasReceived}

响应错过的通知Responding to missed notifications

这些信号通知你可能尚未发送某些更改通知。These signals inform you that some change notifications might not have been delivered. 你应决定是否忽略或处理这些信号。You should decide if you ignore or handle these signals.

通知示例Notification example

{
  "value": [
    {
      "subscriptionId":"<subscription_guid>",
      "subscriptionExpirationDateTime":"2019-03-20T11:00:00.0000000Z",
      "tenantId": "<tenant_guid>",
      "clientState":"<secretClientState>",
      "lifecycleEvent": "missed"
    }
  ]
}

有关此类型通知的一些注意事项:A few things to note about this type of notification:

  • "lifecycleEvent": "missed" 字段将此指定为有关错过的更改通知的信号。The "lifecycleEvent": "missed" field designates this as a signal about missed change notifications. 其他类型的生命周期通知也是可能的,将来会引入新的通知。Other types of lifecycle notifications are also possible, and new ones will be introduced in the future.
  • 生命周期通知不包含有关特定资源的任何信息,因为它与资源更改无关,而与订阅状态更改有关。The lifecycle notification does not contain any information about a specific resource, because it is not related to a resource change, but to the subscription state change.
  • 与更改通知类似,生命周期通知可以一起批处理(在数组中),每个通知都有一个可能不同的 lifecycleEvent 值。Similar to change notifications, lifecycle notifications might be batched together (in the value array), each with a possibly different lifecycleEvent value. 相应地批处理每个生命周期通知。Process each lifecycle notification in the batch accordingly.

注意: 有关传递更改通知时发送的数据的完整说明,请参阅 changeNotificationCollectionNote: for a full description of the data sent when change notifications are delivered, see changeNotificationCollection.

要采取的操作Actions to take

  1. 通过使用 202 - Accepted 来响应 POST 调用,确认收到生命周期通知。Acknowledge the receipt of the lifecycle notification, by responding to the POST call with 202 - Accepted.
    • 如果忽略这些信号,则无需执行其他任何操作。If you ignore these signals, do nothing else. 或者:Otherwise:
  2. 验证生命周期通知的真实性。Validate the authenticity of the lifecycle notification.
  3. 执行资源的完整数据重新同步,以标识未作为通知发送的更改。Perform a full data resync of the resource to identify the changes that were not delivered as notifications.

前瞻性的代码处理生命周期通知Future-proof the code handling lifecycle notifications

将来,Microsoft Graph 将添加更多类型的订阅生命周期通知。In the future, Microsoft Graph will add more types of subscription lifecycle notifications. 它们将被发布到相同的终结点:lifecycleNotificationUrl,但是它们在 lifecycleEvent 下将具有不同的值,并且可能包含稍微不同的模式和属性,这些模式和属性特定于将为其发布的方案。They will be posted to the same endpoint: lifecycleNotificationUrl, but they will have a different value under lifecycleEvent and might contain a slightly different schema and properties, specific to the scenario for which they will be issued.

你应该以前瞻性的方式实现代码,以便在 Microsoft Graph 引入新类型的生命周期通知时不会中断。You should implement your code in a future-proof way so it does not break when Microsoft Graph introduces new types of lifecycle notifications. 建议使用以下方法:We recommend the following approach:

  1. 使用 lifecycleEvent 属性将每个生命周期通知显式标识为你支持的事件。Explicitly identify each lifecycle notification as an event that you support, using the lifecycleEvent property. 例如,查找 "lifecycleEvent": "subscriptionRemoved" 属性标识特定事件并处理它。For example, look for the "lifecycleEvent": "subscriptionRemoved" property to identify a specific event, and handle it.

  2. 注意有关新方案的生命周期通知公告。Watch for announcements of lifecycle notifications for new scenarions. 将来可能会有更多类型的生命周期通知。There might be more types of lifecycle notifications in the future.

  3. 在你的应用中,忽略应用无法识别的任何生命周期通知,并记录它们以获得认知。In your app, ignore any lifecycle notification that the app does not recognize, and log them to gain awareness.

  4. 你可以自行决定查找新生命周期通知的相关文档,并根据需要实施对它们的支持。At your discretion, look up the related documentation for new lifecycle notifications and implement support for them as appropriate.

另请参阅See also