VSTO Outlook:如何判断MailItem是否为本地保存后打开的邮件
可靠检测本地磁盘打开的Outlook MailItem方法
本地打开的邮件(如.eml/.msg文件)与Outlook账户内的邮件(收件箱、草稿等)核心区别在于:未关联任何Exchange/IMAP存储,无父文件夹,且EntryID无法通过MAPI命名空间检索到有效项。以下是精准的检测方案:
核心检测方法:组合验证属性与父对象
1. 基础判断函数
通过三个维度验证,确保精准区分本地打开的邮件与账户内邮件:
public bool IsLocalOpenedMail(Outlook.MailItem mailItem) { if (mailItem == null) return false; // 本地打开的邮件无有效父文件夹 bool hasNoValidParent = false; try { var parent = mailItem.Parent; hasNoValidParent = parent == null || !(parent is Outlook.MAPIFolder); } catch { hasNoValidParent = true; // 访问Parent属性失败时判定为本地文件 } // 本地打开的邮件不属于任何Outlook存储(Exchange/IMAP等) bool hasEmptyStoreID = string.IsNullOrEmpty(mailItem.StoreID); // 验证EntryID有效性:本地文件的EntryID无法通过GetItemFromID检索到有效项 bool isInvalidEntryID = false; if (!string.IsNullOrEmpty(mailItem.EntryID)) { try { var mapiNamespace = mailItem.Session; var retrievedItem = mapiNamespace.GetItemFromID(mailItem.EntryID); isInvalidEntryID = retrievedItem == null; } catch { isInvalidEntryID = true; } } return hasNoValidParent && hasEmptyStoreID && isInvalidEntryID; }
2. 辅助:获取本地文件路径
通过读取MAPI属性获取原始文件路径,进一步确认是否为本地打开的邮件:
public string GetLocalMailFilePath(Outlook.MailItem mailItem) { if (mailItem == null) return null; try { var propAccessor = mailItem.PropertyAccessor; // 0x7D01001E 对应PR_ATTACH_PATHNAME,存储本地打开邮件的原始文件路径 string filePath = propAccessor.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x7D01001E") as string; if (!string.IsNullOrEmpty(filePath) && System.IO.File.Exists(filePath)) { return filePath; } } catch { } return null; }
最终判断逻辑
组合两个方法,覆盖所有场景:
if (IsLocalOpenedMail(mailItem) || !string.IsNullOrEmpty(GetLocalMailFilePath(mailItem))) { // 执行仅针对本地打开邮件的操作 }
关键区分点说明
- 草稿邮件:有明确的父文件夹(草稿箱),StoreID不为空,会被
IsLocalOpenedMail排除 - Exchange/IMAP邮件:关联对应存储,有父文件夹,EntryID可正常检索,会被排除
- 临时新建邮件:未保存时EntryID/StoreID为空,但
IsDraft()返回true,可通过额外判断!mailItem.IsDraft()进一步区分
内容的提问来源于stack exchange,提问作者Willy
相关产品推荐
相关产品推荐

