获取文件夹中邮件的增量更改
通过 Delta 查询,可通过一系列的 delta 函数调用来查询文件夹中邮件的添加、删除或更新。 借助 Delta 数据,能够维护和同步本地存储的用户邮件,而无需每次从服务器中提取整组用户邮件。
在本地存储中同步消息项可以使用 增量 查询进行初始完全同步和后续增量同步。 通常,你会对文件夹中的所有邮件执行初始完全同步, (例如,用户的收件箱) ,然后定期获取该文件夹的增量更改。
若要仅获取特定类型的增量更改(自初始同步后创建、更新或删除的邮件),请对文件夹中的所有邮件执行初始一轮同步,然后在后续轮次中获取特定所需类型的增量更改。 在初始 增量 请求中指定所需的更改类型作为查询选项;Microsoft Graph 自动将任何 OData 和自定义查询选项编码到 @odata.nextLink 响应中提供的 或 @odata.deltaLink 中。
跟踪文件夹中的邮件更改
Delta 查询对每个文件夹分别执行操作。 为跟踪文件夹层次结构中邮件的更改,需要分别跟踪每个文件夹。
跟踪邮件文件夹中的邮件更改通常需要使用 delta 函数按轮发出一个或多个 GET 请求。 初始 GET 请求非常类似于获取邮件,区别在于要添加 delta 函数:
GET https://graph.microsoft.com/v1.0/me/mailFolders/{id}/messages/delta
使用 delta 函数的 GET 请求返回以下任一内容:
-
@odata.nextLink
(包含具有 delta 函数调用和 skipToken 的 URL),或 -
@odata.deltaLink
(包含具有 delta 函数调用和 deltaToken 的 URL)。
这些令牌是客户端不透明的 状态令牌 。
若要继续执行一轮更改跟踪,请将从最后一个 GET 请求返回的 URL 复制并应用于同一文件夹的下一个 delta 函数调用。 响应中返回的 @odata.deltaLink
表示当前一轮更改跟踪已完成。 可以保存 @odata.deltaLink
URL,并在开始下一轮时使用。
本文的其余部分包括 2 个示例:
在邮件的增量查询中使用查询参数
- 像在任何 GET 请求中一样,你可以使用
$select
查询参数以仅指定获取最佳性能所需的属性。 始终id
返回 属性。 - 对于邮件,Delta 查询支持
$select
、$top
和$expand
。 - 提供对
$filter
和$orderby
的有限支持:- 唯一支持的
$filter
表达式是$filter=receivedDateTime+ge+{value}
或$filter=receivedDateTime+gt+{value}
。 - 在增量查询中应用
$filter
最多仅返回 5000 个邮件。 - 唯一支持的
$orderby
表达式是$orderby=receivedDateTime+desc
。 如果未包含$orderby
表达式,则无法保证返回顺序。
- 唯一支持的
- 不支持
$search
。
此外,若要仅返回特定类型的更改 (在增量查询的响应中创建、更新或删除) ,可以选择使用自定义查询选项 changeType
筛选所需的更改类型。 可能的值为 created
、 updated
或 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
可选的请求标头
每个 delta 查询 GET 请求在响应中返回包含一个或多个邮件的集合。 可以视需要指定请求头 Prefer: odata.maxpagesize={x}
,设置响应中可包含的邮件数上限。
示例 1:同步文件夹中的邮件
以下示例显示了对最初包含 5 个邮件的特定文件夹进行的 2 轮同步。
第一轮包含一系列用于同步文件夹中所有 5 个邮件的 3 个请求:
第一轮后,将删除其中一个邮件,并将其他邮件标记为已读。 第二轮同步仅返回 delta(删除和更新),而无需返回保持不变的其他邮件。
示例:初始请求
在此示例中,指定的文件夹首次同步,因此初始同步请求不包含任何状态令牌。 此轮返回该文件夹中的所有邮件。
第一个请求指定以下内容:
-
$select
参数用于在响应中返回每个邮件的subject
、sender
和isRead
属性。 - 可选的请求标头odata.maxpagesize,一次返回两封邮件。
GET https://graph.microsoft.com/v1.0/me/mailfolders/AQMkADNkNAAAgEMAAAA/messages/delta?$select=subject,sender,isRead HTTP/1.1
Prefer: odata.maxpagesize=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=="
}
]
}
示例第二个请求
第二个请求指定上一个响应中返回的 @odata.nextLink
URL。 请注意,不再需要像第一个请求一样指定相同的 $select
参数,因为 skipToken
URL 中的 @odata.nextLink
已将其编码并包含在内。
GET https://graph.microsoft.com/v1.0/me/mailfolders/AQMkADNkNAAAgEMAAAA/messages/delta?$skiptoken=GwcBoTmPuoTQWfcsAbkYM HTTP/1.1
Prefer: odata.maxpagesize=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"
}
]
}
示例第三个请求
第三个请求继续使用上一个同步请求返回的最新 @odata.nextLink
URL。
GET https://graph.microsoft.com/v1.0/me/mailFolders/AQMkADNkNAAAgEMAAAA/messages/delta?$skiptoken=GwcBoTmPKILK4jLH7mAd1lLU HTTP/1.1
Prefer: odata.maxpagesize=2
示例第三个响应(即最终响应)
第三个响应返回文件夹中唯一剩余的邮件,并返回一个 @odata.deltaLink
URL,指示此文件夹的同步暂时已完成。 保存并使用 @odata.deltaLink
URL 在下一轮中同步同一文件夹。
{
"@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
。 这表示现已同步远程邮件文件夹中的所有更改。 已删除一个邮件并更改其他邮件。
{
"@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:根据更改类型同步文件夹中的邮件
以下示例显示仅获取自初始同步以来在特定文件夹中创建的邮件。该示例涉及该文件夹的 2 轮同步,最初包含 4 条消息。
第一轮涉及一系列 2 个请求,以同步文件夹中的所有 4 条消息:
第一轮之后,将再创建两条消息,删除一条消息,另一条消息标记为已读。
第二轮同步仅返回更改类型文件夹中 created
的更改 () 创建的两个新邮件,而不返回自上次同步以来保持相同、已删除或更新的其他邮件。
具有指定更改类型的示例初始请求
在此示例中,指定的文件夹首次同步,因此初始同步请求不包含任何状态令牌。 此轮返回该文件夹中的所有邮件。
第一个请求指定以下内容:
- 一个
changeType
参数,用于仅返回后续增量响应中 创建 的消息。 -
$select
参数用于在响应中返回每个邮件的subject
、sender
和isRead
属性。 - 可选的请求标头odata.maxpagesize,一次返回两封邮件。
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
具有指定更改类型的示例初始响应
响应包括两条消息和一个 @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"
}
}
}
]
}
具有指定更改类型的示例第二个请求
第二个请求指定上一个响应中返回的 @odata.nextLink
URL。 请注意,它不再需要指定与初始请求中相同的 $select
或 changeType
参数,因为 skipToken
URL 中的 @odata.nextLink
编码并包含它。
GET https://graph.microsoft.com/v1.0/me/mailFolders/AAMkAGUwNc4LTMzAAA=/messages/delta?$skiptoken=P4lmXpjPRrjB6haAQzSkpK89jYTVD2kVtOeXNRnfYzPbCs HTTP/1.1
Prefer: odata.maxpagesize=2
具有指定更改类型的示例第二个响应
第二个响应返回 文件夹中接下来的 2 条消息和 @odata.deltaLink
URL,指示此文件夹的同步暂时已完成。 保存并使用 @odata.deltaLink
URL 在下一轮中同步同一文件夹。
{
"@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
。 这表示现已同步远程邮件文件夹中的所有更改。 自上次同步以来添加了两条消息。自上次同步以来更新 & 删除的消息不会在此增量响应中返回。
{
"@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"
}
}
}
]
}