我可以使用 Microsoft Graph API 同步日历事件吗?

Posted

技术标签:

【中文标题】我可以使用 Microsoft Graph API 同步日历事件吗?【英文标题】:Can I sync calendar events with the Microsoft Graph API? 【发布时间】:2016-09-15 19:24:57 【问题描述】:

我正在使用 Microsoft Graph api 尝试从 Outlook 同步日历事件。我正在查看有关 Outlook api 的 this article,它建议我将标头 odata.track-changes 添加到我的请求中,我会收到一个 deltaToken,我可以在以后的请求中使用它来仅获取那些已更新的事件或自上次同步后创建。

我已成功获取事件,但没有返回 deltaToken:/

这仅在 Outlook api 中支持吗? Graph 的响应有Preference-Applied: odata.track-changes,所以它承认我的标题。这是我的示例请求:

GET /v1.0/me/calendar/calendarView
    ?startDateTime=2016-09-01T00:00:00.0000000
    &endDateTime=2099-01-01T00:00:00.0000000
    HTTP/1.1
Host: graph.microsoft.com
Authorization: Bearer XXX
Prefer: odata.track-changes
Prefer: odata.maxpagesize=3  //for testing
Cache-Control: no-cache

我的示例回复:


  "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('')/calendar/calendarView",
  "value": [
    
      "@odata.etag": "",
      "id": "",
      "createdDateTime": "2016-08-04T14:00:25.8552351Z",
      "lastModifiedDateTime": "2016-08-25T14:43:54.9950828Z",
      "changeKey": "",
      "categories": [
        "Orange category"
      ],
      "originalStartTimeZone": "Eastern Standard Time",
      "originalEndTimeZone": "Eastern Standard Time",
      "responseStatus": 
        "response": "organizer",
        "time": "0001-01-01T00:00:00Z"
      ,
      "iCalUId": "",
      "reminderMinutesBeforeStart": 15,
      "isReminderOn": true,
      "hasAttachments": false,
      "subject": "Closing on House",
      "body": 
        "contentType": "html",
        "content": ""
      ,
      "bodyPreview": "",
      "importance": "normal",
      "sensitivity": "normal",
      "start": 
        "dateTime": "2016-09-08T19:30:00.0000000",
        "timeZone": "UTC"
      ,
      "end": 
        "dateTime": "2016-09-08T21:30:00.0000000",
        "timeZone": "UTC"
      ,
      "location": 
        "displayName": "245 E Main St",
        "address": 
          "street": "245 E Main St",
          "city": "Somewhere",
          "state": "NY",
          "countryOrRegion": "United States",
          "postalCode": ""
        
      ,
      "isAllDay": false,
      "isCancelled": false,
      "isOrganizer": true,
      "recurrence": null,
      "responseRequested": true,
      "seriesMasterId": null,
      "showAs": "busy",
      "type": "singleInstance",
      "attendees": [],
      "organizer": 
        "emailAddress": 
          "name": "",
          "address": ""
        
      ,
      "webLink": "https://outlook.office365.com/owa/?ItemID="
    ,
    
      "@odata.etag": "",
      "id": "",
      "createdDateTime": "2016-08-19T18:02:39.0607411Z",
      "lastModifiedDateTime": "2016-08-19T18:04:10.548447Z",
      "changeKey": "",
      "categories": [
        "Green category"
      ],
      "originalStartTimeZone": "UTC",
      "originalEndTimeZone": "UTC",
      "responseStatus": 
        "response": "organizer",
        "time": "0001-01-01T00:00:00Z"
      ,
      "iCalUId": "",
      "reminderMinutesBeforeStart": 15,
      "isReminderOn": true,
      "hasAttachments": false,
      "subject": "Moving (off work)",
      "body": 
        "contentType": "html",
        "content": ""
      ,
      "bodyPreview": "",
      "importance": "normal",
      "sensitivity": "normal",
      "start": 
        "dateTime": "2016-09-10T00:00:00.0000000",
        "timeZone": "UTC"
      ,
      "end": 
        "dateTime": "2016-09-13T00:00:00.0000000",
        "timeZone": "UTC"
      ,
      "location": 
        "displayName": "",
        "address": 
      ,
      "isAllDay": true,
      "isCancelled": false,
      "isOrganizer": true,
      "recurrence": null,
      "responseRequested": true,
      "seriesMasterId": null,
      "showAs": "oof",
      "type": "singleInstance",
      "attendees": [],
      "organizer": 
        "emailAddress": 
          "name": "",
          "address": ""
        
      ,
      "webLink": "https://outlook.office365.com/owa/?ItemID="
    ,
    
      "@odata.etag": "",
      "id": "",
      "createdDateTime": "2016-09-13T19:05:20.8438647Z",
      "lastModifiedDateTime": "2016-09-13T19:05:22.1899702Z",
      "changeKey": "",
      "categories": [],
      "originalStartTimeZone": "America/New_York",
      "originalEndTimeZone": "America/New_York",
      "responseStatus": 
        "response": "organizer",
        "time": "0001-01-01T00:00:00Z"
      ,
      "iCalUId": "",
      "reminderMinutesBeforeStart": 15,
      "isReminderOn": true,
      "hasAttachments": false,
      "subject": "Coffee Break",
      "body": 
        "contentType": "html",
        "content": ""
      ,
      "bodyPreview": "",
      "importance": "normal",
      "sensitivity": "normal",
      "start": 
        "dateTime": "2016-09-15T20:15:00.0000000",
        "timeZone": "UTC"
      ,
      "end": 
        "dateTime": "2016-09-15T21:15:00.0000000",
        "timeZone": "UTC"
      ,
      "location": 
        "displayName": "",
        "address": 
      ,
      "isAllDay": false,
      "isCancelled": false,
      "isOrganizer": true,
      "recurrence": null,
      "responseRequested": true,
      "seriesMasterId": null,
      "showAs": "busy",
      "type": "singleInstance",
      "attendees": [],
      "organizer": 
        "emailAddress": 
          "name": "",
          "address": ""
        
      ,
      "webLink": "https://outlook.office365.com/owa/?ItemID="
    
  ]

我编辑了我认为可能是轻度敏感的任何内容。最终,我的 Laravel 应用尝试从 4 个月前开始同步事件,并一直持续到未来。

如果有更有效/更好的方法可以做到这一点,我愿意接受建议。如果重要的话,这些结果是由 Postman 生成的。对此的任何帮助或澄清表示赞赏。

【问题讨论】:

【参考方案1】:

我最终像这样使用odata filter:

https://graph.microsoft.com/beta/me/calendar/calendarView?startDateTime=2016-05-01T00:00:00Z&endDateTime=2099-01-01T00:00:00Z&$filter=type eq 'singleInstance' and lastModifiedDateTime eq '2016-09-20T07:30:00+00:00'

这将获取在2016-05-01T00:00:00Z (May 1st, 2016, midnight, UTC2099-01-01T00:00:00Z (January 1st, 2099, midnight, UTC) 之间安排的所有日历事件,其中事件类型为singleInstance(不是重复事件),而lastModifiedDateTime 是在最后一次同步之后(在本例中为2016-09-20T07:30:00+00:00 )。

这有几个陷阱:

    显然,这不是 url 编码的。您需要这样做。 确保 lastModifiedDateTime 示例中的 + 正确编码为 %2B,否则 Graph API 会将其视为空格并拒绝它。 如果您不过滤掉重复事件,您将获得从现在到 2099 年的每个重复事件。这是获取calendarViews 列表而不是events 列表的本质。

如果我能再做一次,我可能会回去做完整的日历同步,Graph 支持(我相信)。我只是不想同步整个日历,只想同步一个日期范围,但这似乎注定要失败。

但尽管没有重复事件,它仍然有效。

更新

我最终放弃了这个实现,主要是因为我在维护数据同步完整性、缺乏重复事件等方面遇到了持续的陷阱。相反,我实时提取日历事件,并维护一个缓存。只是一些建议,以防其他人最终遇到我的情况。

【讨论】:

嘿,您能帮我详细解释一下您采用的方法吗?你是如何管理只获取更新的事件的?你们每次都拉所有事件吗? 我最终做的是,我没有将他们的日历事件下载到我的数据库,而是在他们使用相同的端点 (calendarView) 访问页面时实时获取事件。您可以使用 lastModifiedDateTime 在特定时间后修改事件,但我不需要,因为我没有同步任何东西(更容易)。用户有一个日历,该日历显示来自几个不同日历服务(包括 Outlook)的事件。因此,当他们点击 1 月份时,我会从他们的 Outlook 日历视图中获取 1 月份的事件,并且不会将其存储在我的服务器上。

以上是关于我可以使用 Microsoft Graph API 同步日历事件吗?的主要内容,如果未能解决你的问题,请参考以下文章

Microsoft graph api预订-与onlinemeeting集成

MS Graph API:microsoft.graph.createLink 未创建匿名视图链接

通过 Microsoft Graph API 发送自适应卡片 - 获取提交操作时出错

如何使用 microsoft graph api 获取 EndRecurrenceDate

使用 microsoft graph api 检出 onedrive 文件的状态

获取 Microsoft Graph API 的有效访问令牌