当代码尝试保存邮件项目时,Outlook 互操作代码第二次抛出 "message has been changed" 错误

Outlook interop code throws "message has been changed" error the second time when the code tries to save a mail item

首先,这个问题只发生在少数客户端机器上,我无法在我的任何测试机器上复制它。

所以我在LINQPad中有如下测试代码:

var application = new Application();
var session = application.Session;
const string entryId = "arbitrary entry ID";
const string propertyName = "http://schemas.microsoft.com/mapi/string/{31A9B8DA-D4A0-4B96-87AE-01D6E9BCFCCE}/Test/0x0000001F";

// Save test property for the first time.
var mail = (MailItem)session.GetItemFromID(entryId);
var propertyAccessor = mail.PropertyAccessor;
propertyAccessor.SetProperty(propertyName, 1);
mail.Save();

Marshal.ReleaseComObject(propertyAccessor);
Marshal.ReleaseComObject(mail);

// Save test property for the second time.
mail = (MailItem)session.GetItemFromID(entryId);
var propertyAccessor = mail.PropertyAccessor;
propertyAccessor.SetProperty(propertyName, 2);
mail.Save();

Marshal.ReleaseComObject(propertyAccessor);
Marshal.ReleaseComObject(mail);
Marshal.ReleaseComObject(session);
Marshal.ReleaseComObject(application);

第二个 mail.Save() 调用在这几台客户端机器上有 100% 的抛出异常:System.Runtime.InteropServices.COMException (0x80040109): The operation cannot be performed because the message has been changed.

由于上述代码正确释放了第一个 mail 对象并再次使用条目 ID 检索第二个 mail 对象。在第二次检索对象和调用其 Save() 方法之间更改 mail 对象的机会非常低,更不用说 100% 的可重现率了。

我只能认为它看起来像是 Outlook 中的一个错误,它可能会在任何东西调用一次 Save() 方法后立即将邮件对象永久标记为已更改。

有人知道是否有解决方法吗?

这些机器使用的是最新版本的 Office 2016。

IMAP4 是最差的之一 - 每次您尝试触摸任何存储对象时,它都会尝试同步。您可以尝试绕过 IMAP4 层并直接转到用作底层本地存储的 PST 提供程序。在扩展 MAPI(C++ 或 Delphi)中,您可以使用 IProxyStoreObject interface. In case of languages other than C++ or Delphi, you can use Redemption (I am its author) and its RDOSession.Stores.UnwrapStore method - the message can be then opened from the unwrapped store using RDOStore.GetMessageFromID.