如何使用Microsoft Graph API恢复已删除的日历事件?
从EWS迁移至Microsoft Graph API:日历事件删除与恢复问题
背景信息
我们正将功能从EWS迁移至Java版Microsoft Graph API,需求是通过编程方式删除并恢复日历事件。EWS实现运行正常,但使用Graph API时无法找到已删除的事件。
当前EWS实现(运行正常)
在EWS中,我们使用DeleteMode.HardDelete删除事件,随后在RecoverableItemsPurges文件夹中搜索并将项目移回日历。
// 从日历中删除会议的逻辑 if (msg instanceof MeetingMessage) { MeetingMessage meetingMessage = MeetingMessage.bind(service, msg.getId()); ItemId masterId = meetingMessage.getAssociatedAppointmentId(); if (masterId != null) { Appointment appointment = Appointment.bind(service, masterId); appointment.delete(DeleteMode.HardDelete); } } // 恢复已删除项目的逻辑 ItemView itemView = new ItemView(EwsServer.FOLDER_VIEW_PAGE_SIZE); itemView.setTraversal(ItemTraversal.Shallow); SearchFilter filterColl = new SearchFilter.SearchFilterCollection( LogicalOperator.And, new SearchFilter.IsEqualTo(ItemSchema.Subject, message.getSubject()), new SearchFilter.IsEqualTo(EmailMessageSchema.Sender, message.getSender().getAddress()) ); FindItemsResults<Item> deletedItems = server.getExchangeService() .findItems(WellKnownFolderName.RecoverableItemsPurges, filterColl, itemView); if (deletedItems.getItems().size() > 0) { for (Item item : deletedItems.getItems()) { item.move(WellKnownFolderName.Calendar); break; } }
Graph API实现(存在问题)
使用Graph API删除日历事件后,无法在可恢复项目文件夹中找到该事件。
删除代码
// 方式一:永久删除 graphClient .users().byUserId(mailboxBeingScanned) .calendar().events().byEventId(eventId) .permanentDelete().post(); // 方式二:普通删除 graphClient .users().byUserId(mailboxBeingScanned) .calendar().events().byEventId(eventId).delete()
尝试的恢复代码
我们尝试使用internetMessageId在recoverableitemspurges、deleteditems和recoverableitemsdeletions中搜索,但返回的集合始终为空。
MessageCollectionResponse eventMessage = graphClient.users().byUserId(mailboxBeingScanned) .mailFolders().byMailFolderId("recoverableitemspurges") .messages() .get(requestConfiguration -> { requestConfiguration.queryParameters.filter = "internetMessageId eq '<MN2PR13...prod.outlook.com>'"; });
问题
- 在Graph中对日历事件使用
permanentDelete()/delete()后,它会进入与EWS不同的文件夹吗? - 查询日历事件专属的“可恢复项目”分区的正确
mailFolderId或端点是什么?
解决方案
问题1解答
- 使用
delete()方法删除日历事件时,默认会将事件移到已删除邮件(deleteditems)文件夹,这和EWS的SoftDelete行为一致; - 使用
permanentDelete()方法时,事件会被移到可恢复项目的清除文件夹(recoverableitemspurges),这和EWS的HardDelete行为对应。 - 核心差异:Graph API中,日历事件属于
events资源,而非messages,所以直接搜索mailFolders下的messages无法找到已删除的日历事件。
问题2解答
查询日历事件专属的可恢复项目分区,需要使用专门的calendarEvents端点,而非邮件的messages端点:
- 若使用普通删除(
delete()),已删除事件在日历的已删除项目中,端点为:/users/{userId}/calendar/deletedItems/events - 若使用永久删除(
permanentDelete()),事件会进入可恢复项目的清除/删除分区,对应端点为:/users/{userId}/mailFolders/recoverableitemsdeletions/calendarEvents/users/{userId}/mailFolders/recoverableitemspurges/calendarEvents
修正后的恢复代码示例
查询日历已删除项目中的事件
EventCollectionResponse deletedEvents = graphClient.users().byUserId(mailboxBeingScanned) .calendar().deletedItems().events() .get(requestConfiguration -> { requestConfiguration.queryParameters.filter = "subject eq '" + message.getSubject() + "' and organizer/emailAddress/address eq '" + message.getSender().getAddress() + "'"; }); if (!deletedEvents.getValue().isEmpty()) { // 将事件移回日历 graphClient.users().byUserId(mailboxBeingScanned) .calendar().deletedItems().events().byEventId(deletedEvents.getValue().get(0).getId()) .move().post(new MovePostRequestBody().destinationId("calendar")); }
查询可恢复项目清除文件夹中的事件
CalendarEventCollectionResponse purgedEvents = graphClient.users().byUserId(mailboxBeingScanned) .mailFolders().byMailFolderId("recoverableitemspurges") .calendarEvents() .get(requestConfiguration -> { requestConfiguration.queryParameters.filter = "subject eq '" + message.getSubject() + "' and organizer/emailAddress/address eq '" + message.getSender().getAddress() + "'"; }); if (!purgedEvents.getValue().isEmpty()) { // 将事件移回日历 graphClient.users().byUserId(mailboxBeingScanned) .mailFolders().byMailFolderId("recoverableitemspurges") .calendarEvents().byCalendarEventId(purgedEvents.getValue().get(0).getId()) .move().post(new MovePostRequestBody().destinationId("calendar")); }
注意事项
- 确保应用拥有足够权限:需配置
Calendars.ReadWrite、RecoverableItems.ReadWrite等权限(根据操作场景选择); - 使用
internetMessageId过滤时,无需包裹尖括号,直接使用原始值即可; - 部分Exchange Online环境可能对可恢复项目的保留时间有限制,需确认租户配置。
内容的提问来源于stack exchange,提问作者Raghu Chaitanya
相关产品推荐
相关产品推荐

