You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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>'";
    });

问题

  1. 在Graph中对日历事件使用permanentDelete()/delete()后,它会进入与EWS不同的文件夹吗?
  2. 查询日历事件专属的“可恢复项目”分区的正确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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.11 09:59:50