使用Graph API无法追踪已删除和修改的邮件文件夹变更
问题解决:Graph API邮件文件夹Delta查询changeType参数无效
你遇到的问题核心是:Graph API的邮件文件夹Delta查询并不支持changeType这个查询参数,这个参数是EWS里的专属概念,Graph没有对应参数,所以无论你传deleted还是created,都不会起到过滤作用,自然会返回所有类型的变更。
正确的处理方式是在获取Delta结果后,通过返回对象的特征来区分变更类型:
- 删除的文件夹:返回的对象类型是
DeletedItem,会带有isDeleted: true属性,同时包含originalId字段(对应原文件夹的ID)。 - 创建/更新的文件夹:返回的是普通
MailFolder对象,重命名属于更新操作,对象会包含修改后的displayName等属性,你可以通过对比本地数据库存储的旧数据来判断是创建还是更新。
修改后的代码示例:
static async Task Main(string[] args) { var tenantId = "some tenantId"; var clientId = "some clientid"; var clientSecret = "some client secret"; CancellationToken cancellationToken = default; var credentials = new ClientSecretCredential( tenantId, clientId, clientSecret, new TokenCredentialOptions { AuthorityHost = AzureAuthorityHosts.AzurePublicCloud }); GraphServiceClient _graphServiceClient = new GraphServiceClient(credentials); var users = await _graphServiceClient.Users.Request().GetAsync(); string FolderQueryODataDeltaLink = "previous delta token"; var folderqueryOptions = new List<Option> { }; if (!string.IsNullOrEmpty(FolderQueryODataDeltaLink)) { // 只传入deltatoken,移除无效的changeType参数 folderqueryOptions.Add(new QueryOption("$deltatoken", FolderQueryODataDeltaLink)); } var foldersDelta = await _graphServiceClient.Users[userid] .MailFolders .Delta() .Request(folderqueryOptions) .GetAsync(); // 遍历Delta结果,区分变更类型 foreach (var item in foldersDelta.CurrentPage) { if (item is DeletedItem deletedFolder) { // 处理删除操作:使用originalId匹配本地数据 Console.WriteLine($"已删除文件夹原ID: {deletedFolder.OriginalId}"); // 执行本地数据库删除逻辑 } else if (item is MailFolder mailFolder) { // 检查本地数据库是否存在该ID:不存在则是创建,存在则是更新(比如重命名) bool existsInDb = CheckFolderExistsInDb(mailFolder.Id); // 你自己的检查逻辑 if (existsInDb) { Console.WriteLine($"已更新文件夹: {mailFolder.Id},新名称: {mailFolder.DisplayName}"); // 执行本地数据库更新逻辑 } else { Console.WriteLine($"已创建文件夹: {mailFolder.Id},名称: {mailFolder.DisplayName}"); // 执行本地数据库插入逻辑 } } } Console.ReadKey(); }
额外说明:
- 初始Delta请求(无deltatoken)会返回用户所有邮件文件夹,之后的请求用返回的deltalink获取增量变更。
- 所有变更类型(创建、更新、删除)都会包含在Delta结果里,必须在客户端代码中自行筛选处理,无法通过查询参数提前过滤。
内容的提问来源于stack exchange,提问作者Lavanya Senthilkumar
相关产品推荐
相关产品推荐

