如何在C#中获取Outlook中未知收件人的所有共享文件夹
好问题!我之前做Outlook集成的时候也遇到过这个需求——不用指定收件人就能获取所有共享文件夹。其实可以通过遍历Outlook的存储和文件夹树,结合所有者判断来实现,下面是具体的思路和代码示例:
实现思路
Outlook里的共享文件夹主要分两种:一种是完整的共享邮箱(会作为独立的Store挂载),另一种是单个共享的子文件夹(挂在你自己的邮箱文件夹下)。我们可以分两步处理:
- 遍历所有
Store,筛选出不属于当前用户的共享邮箱,直接递归获取其下所有文件夹 - 遍历当前用户邮箱的文件夹树,检查每个文件夹的所有者是否为他人,以此判断是否是共享子文件夹
完整代码示例
首先要确保你引用了Microsoft.Office.Interop.Outlook程序集,然后可以用以下代码实现:
using System.Collections.Generic; using System.Runtime.InteropServices; using Outlook = Microsoft.Office.Interop.Outlook; public class OutlookSharedFolderHelper { public List<Outlook.Folder> GetAllSharedFolders() { List<Outlook.Folder> sharedFolders = new List<Outlook.Folder>(); Outlook.Application outlookApp = new Outlook.Application(); Outlook.NameSpace mapiNamespace = outlookApp.GetNamespace("MAPI"); // 遍历所有存储容器(包括主邮箱和共享邮箱) foreach (Outlook.Store store in mapiNamespace.Stores) { // 处理完整的共享邮箱:判断是否是Exchange邮箱且所有者不是当前用户 if (store.ExchangeStoreType == Outlook.OlExchangeStoreType.olExchangeMailbox && store.Owner?.Name != mapiNamespace.CurrentUser.Name) { var rootFolder = store.GetRootFolder() as Outlook.Folder; if (rootFolder != null) { AddAllSubfolders(rootFolder, sharedFolders); } } else { // 处理当前邮箱下的共享子文件夹 var rootFolder = store.GetRootFolder() as Outlook.Folder; if (rootFolder != null) { CheckSharedSubfolders(rootFolder, sharedFolders); } } Marshal.ReleaseComObject(store); } // 清理COM对象,避免内存泄漏 mapiNamespace.Logoff(); Marshal.ReleaseComObject(mapiNamespace); Marshal.ReleaseComObject(outlookApp); return sharedFolders; } // 递归添加共享邮箱下的所有子文件夹 private void AddAllSubfolders(Outlook.Folder parentFolder, List<Outlook.Folder> sharedFolders) { sharedFolders.Add(parentFolder); foreach (Outlook.Folder subFolder in parentFolder.Folders) { AddAllSubfolders(subFolder, sharedFolders); Marshal.ReleaseComObject(subFolder); } } // 递归检查当前邮箱下的文件夹是否为共享文件夹 private void CheckSharedSubfolders(Outlook.Folder parentFolder, List<Outlook.Folder> sharedFolders) { // 判断条件:文件夹所有者存在且不是当前用户 if (parentFolder.Owner != null && parentFolder.Owner.Name != parentFolder.Session.CurrentUser.Name) { sharedFolders.Add(parentFolder); } foreach (Outlook.Folder subFolder in parentFolder.Folders) { CheckSharedSubfolders(subFolder, sharedFolders); Marshal.ReleaseComObject(subFolder); } } }
注意事项
- COM对象释放:Outlook是COM组件,使用后必须手动释放对象,否则会导致Outlook进程残留内存泄漏,代码里已经用
Marshal.ReleaseComObject处理了。 - 权限判断:如果需要更精确的权限筛选(比如只获取有编辑权限的共享文件夹),可以结合
Folder.PermissionSet属性来进一步判断。 - 类型筛选:如果只需要特定类型的共享文件夹(比如日历、联系人),可以在添加时检查
parentFolder.DefaultItemType,比如筛选日历可以判断parentFolder.DefaultItemType == Outlook.OlItemType.olAppointmentItem。 - Outlook版本兼容:这段代码在Outlook 2016及以上版本测试有效,旧版本可能需要调整部分属性的判断逻辑。
内容的提问来源于stack exchange,提问作者Yohan Chung
相关产品推荐
相关产品推荐

