如何通过ID/GUID访问已移动文件夹的Exchange Web Services邮件
如何访问已移动的Exchange邮件(解决UniqueId变更问题)
没错,Exchange邮件的UniqueId确实会在移动文件夹后发生变化——因为这个ID里包含了邮件所在文件夹的标识信息,位置一变,ID自然就跟着变了。不过有几种可靠的方法可以定位到移动后的邮件:
1. 直接使用Move方法的返回值(最推荐)
其实mailItem.Move()方法本身就会返回移动后的新邮件对象,这个对象的Id.UniqueId就是更新后的正确ID,完全不需要事后再额外查找:
// 获取原邮件 EmailMessage mailItem = EmailMessage.Bind(service, ItemID, new PropertySet(BasePropertySet.FirstClassProperties)); // 移动邮件并直接拿到移动后的邮件实例 EmailMessage movedMailItem = mailItem.Move(destinationFolderID); // 这里直接使用movedMailItem的ID即可,就是变更后的"ChangedID" string newUniqueId = movedMailItem.Id.UniqueId;
这种方法最直接高效,没有额外的搜索开销,是优先选择的方案。
2. 利用邮件的全局唯一标识(事后查找场景)
如果已经完成了移动操作,没法再获取Move的返回值,可以用邮件本身的全局标识来查找,这些标识不会随文件夹变更而改变:
方法A:使用InternetMessageId
InternetMessageId是邮件的SMTP消息ID,每个邮件在创建后就固定不变,适合用来定位:
// 先记录原邮件的InternetMessageId string originalMessageId = mailItem.InternetMessageId; // 移动邮件(假设已经完成移动) mailItem.Move(destinationFolderID); // 在目标文件夹中搜索匹配的邮件 SearchFilter filter = new SearchFilter.IsEqualTo(EmailMessageSchema.InternetMessageId, originalMessageId); FindItemsResults<Item> searchResults = service.FindItems(destinationFolderID, filter, new ItemView(1)); if (searchResults.Items.Count > 0) { EmailMessage movedMail = EmailMessage.Bind(service, searchResults.Items[0].Id); // 这里就是移动后的邮件 }
方法B:使用PidTagSearchKey(二进制全局标识)
这是Exchange底层的一个二进制属性,同样跨文件夹保持唯一,需要通过扩展属性来访问:
// 先加载原邮件的PidTagSearchKey属性 ExtendedPropertyDefinition searchKeyProp = new ExtendedPropertyDefinition(0x300B, MapiPropertyType.Binary); PropertySet props = new PropertySet(BasePropertySet.IdOnly, searchKeyProp); mailItem = EmailMessage.Bind(service, ItemID, props); byte[] originalSearchKey = (byte[])mailItem.ExtendedProperties[0].Value; // 移动邮件 mailItem.Move(destinationFolderID); // 在目标文件夹中搜索匹配的邮件 SearchFilter filter = new SearchFilter.IsEqualTo(searchKeyProp, originalSearchKey); FindItemsResults<Item> searchResults = service.FindItems(destinationFolderID, filter, new ItemView(1)); if (searchResults.Items.Count > 0) { EmailMessage movedMail = EmailMessage.Bind(service, searchResults.Items[0].Id); }
总结
- 如果你是在移动邮件的代码流程中需要访问新邮件,优先用
Move方法的返回值,这是最可靠高效的方式。 - 如果是事后需要查找已移动的邮件,
InternetMessageId是最易用的全局标识,实现起来更简单。
内容的提问来源于stack exchange,提问作者d1no
相关产品推荐
相关产品推荐

