假设您正在构建一个从EWS同步消息体和元数据的应用程序.使初始状态同步非常简单:调用SyncFolderHierarchy
获取文件夹列表,SyncFolderItems
获取消息ItemIds,以及GetItem
获取消息体和元数据.
当试图通过移动来跟踪消息时,事情变得有点复杂.移动后,调用SyncFolderItems
将在一个文件夹中返回Create,在另一个文件夹中返回Delete.您希望关联这些内容,以便客户端可以避免重新加载邮件正文和附件.(另外,客户端不会丢失与其本地副本关联的任何元数据.)但是,在文件夹之间移动消息会更改其EWS ItemId,因此ItemId不能用于关联Create和Delete.
EWS文档建议订阅流式通知,它确实支持Move事件.但是,当流未连接时,流缓存通知不会被缓冲,因此在建立流连接之前,您仍然必须使客户端恢复同步.因此,流式传输通知不能是完全相关的移动解决方案.
另一个EWS选项是订阅拉取通知.与流式通知一样,拉动通知支持移动事件.与流式通知不同,拉订阅缓冲区更改.但是,如果您的客户端在请求订阅到期时处于脱机状态,那么您将回到相同的状态.(尽管如此,因为拉取订阅的范围可以持续一整天,这可能仍然可行.)
最后一个选项是使用ItemId之外的其他内容来关联移动的项目SyncFolderItems
:
PR_SEARCH_KEY
通过移动工作,但副本有问题(因为副本最终与PR_SEARCH_KEY
原始相同)
PR_ENTRYID
似乎它可以用于此目的,似乎比PR_RECORD_KEY
以下更好:
A MAPI store provider assigns a unique ID string when an item is created in its store. Therefore, the EntryID property is not set for a Microsoft Outlook item until it is saved or sent. The EntryID changes when an item is moved into another store, for example, from your Inbox to a Microsoft Exchange Server public folder, or from one Personal Folders (.pst) file to another .pst file. Solutions should not depend on the EntryID property to be unique unless items will not be moved. The EntryID property returns a MAPI long-term EntryID.
那么...... 通过EWS移动来关联项目的正确方法是什么?
有两件事可以帮助你:
第一种方法
我们通过为每个项目(在我们的案例中为日历项目)提供包含EWS项目ID(每当我们编写/更新它)的副本的用户定义属性(又名扩展属性)来解决这个问题.
每当我们读取项目以进行同步时,我们都会检查该属性是否仍与EWS项目ID匹配.如果没有,我们知道该项已被移动并相应地处理它(我们清除了User Defined属性).
与其他一些用户定义的簿记属性一起,这使我们可以维护Exchange中的项目与应用程序中的项目之间的完整性.
第二种方法
有一些边缘情况,这不起作用(但我们忽略它们).对于那些,使用EWS项ID进行跟踪不再有效,建议使用UID/PidLidGlobalObject属性.我没有必要实际实现这一点,但这里有一些参考来帮助你入门:
"Exchange日历:ConversationId是FindItem事件的主事件的良好标识符吗?"
"约会
.Id.UniqueID已更改" "EWS API-在Office 365帐户与Microsoft Outlook Mac客户端创建约会时返回的ICalUid差异"
"EWS:对于同一会议的孤立实例,UID并不总是相同
" :UID"
"PidLidGlobalObjectId规范属性"
"PidLidCleanGlobalObjectId规范属性"
"从UID获取GlobalObjectID(从IPhone创建的约会)"
"有关日历的开发人员信息在Outlook 2003 Service Pack 2,Exchange Server 2003 Service Pack 2和更高版本中更改版本的Exchange Server和Outlook"
"使用EWS托管API 2.0处理扩展属性"
我无法详细说明要使用的代码,因为我们的应用程序是用Delphi编写的,并且只使用SOAP调用来同步日历项目.