如何使用EWS将公用文件夹联系人复制到Exchange 365各用户邮箱?
解决方案:用EWS实现Exchange Online联系人自动化操作
一、删除指定文件夹或特定主题的联系人
步骤说明
- 定位用户邮箱中目标联系人文件夹(如「Cell Phone List」)
- 构建筛选条件(按公司名称/主题匹配待删除联系人)
- 批量获取并删除符合条件的联系人
代码示例(C#)
using Microsoft.Exchange.WebServices.Data; using System; using System.Collections.Generic; using System.Linq; public void DeleteTargetContacts(string userEmail, string accessToken, string targetFolderName = "Cell Phone List", string companyNameToDelete = "你的公司名称") { var service = new ExchangeService(ExchangeVersion.Exchange2016); service.Credentials = new OAuthCredentials(accessToken); service.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx"); // 定位联系人根文件夹下的目标文件夹 var contactsRoot = Folder.Bind(service, WellKnownFolderName.Contacts); var targetFolder = contactsRoot.FindFolders(new FolderView(100)) .FirstOrDefault(f => f.DisplayName.Equals(targetFolderName, StringComparison.OrdinalIgnoreCase)); if (targetFolder == null) { Console.WriteLine($"未找到文件夹:{targetFolderName}"); return; } // 按公司名称构建筛选器(替换为主题筛选只需修改Schema) var searchFilter = new SearchFilter.ContainsSubstring(ContactSchema.CompanyName, companyNameToDelete); // 按主题筛选示例:var searchFilter = new SearchFilter.ContainsSubstring(ItemSchema.Subject, "目标主题关键词"); var itemView = new ItemView(1000); // 单次批量获取上限1000条 var foundItems = service.FindItems(targetFolder.Id, searchFilter, itemView); if (foundItems.Items.Count == 0) { Console.WriteLine("无符合条件的联系人需删除"); return; } // 批量硬删除(如需软删除可改为DeleteMode.SoftDelete) service.DeleteItems(foundItems.Select(item => item.Id), DeleteMode.HardDelete); Console.WriteLine($"成功删除 {foundItems.Items.Count} 个联系人"); }
PowerShell 实现思路
加载EWS Managed API模块后,逻辑与C#一致:
- 初始化ExchangeService并配置OAuth令牌
- 查找目标联系人文件夹
- 构建SearchFilter筛选目标联系人
- 调用
DeleteItems方法批量执行删除
二、复制公用文件夹联系人到用户邮箱
步骤说明
- 定位公用文件夹中的源联系人文件夹
- 批量获取源文件夹内的联系人
- 定位用户邮箱的目标文件夹(不存在则创建)
- 批量复制联系人至目标文件夹
代码示例(C#)
using Microsoft.Exchange.WebServices.Data; using System; using System.Collections.Generic; using System.Linq; public void CopyPublicFolderContactsToUser(string userEmail, string accessToken, string publicFolderName = "公用联系人列表", string userTargetFolderName = "Cell Phone List") { var service = new ExchangeService(ExchangeVersion.Exchange2016); service.Credentials = new OAuthCredentials(accessToken); service.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx"); // 1. 获取公用文件夹中的源联系人文件夹 var publicFolderRoot = Folder.Bind(service, WellKnownFolderName.PublicFoldersRoot); var sourcePublicFolder = publicFolderRoot.FindFolders(new FolderView(100)) .FirstOrDefault(f => f.DisplayName.Equals(publicFolderName, StringComparison.OrdinalIgnoreCase)); if (sourcePublicFolder == null) { Console.WriteLine($"未找到公用文件夹:{publicFolderName}"); return; } // 批量获取源文件夹内的联系人 var itemView = new ItemView(1000); var sourceContacts = service.FindItems(sourcePublicFolder.Id, itemView); if (sourceContacts.Items.Count == 0) { Console.WriteLine("公用文件夹中无联系人可复制"); return; } // 2. 定位用户邮箱的目标文件夹(不存在则创建) var userContactsRoot = Folder.Bind(service, new FolderId(WellKnownFolderName.Contacts, userEmail)); var userTargetFolder = userContactsRoot.FindFolders(new FolderView(100)) .FirstOrDefault(f => f.DisplayName.Equals(userTargetFolderName, StringComparison.OrdinalIgnoreCase)); if (userTargetFolder == null) { userTargetFolder = new Folder(service) { DisplayName = userTargetFolderName, FolderClass = "IPF.Contact" }; userTargetFolder.Save(userContactsRoot.Id); Console.WriteLine($"已创建目标文件夹:{userTargetFolderName}"); } // 3. 批量复制联系人(CopyItems效率优于逐个复制) var sourceItemIds = sourceContacts.Items.Select(item => item.Id).ToList(); var copiedItemIds = service.CopyItems(sourceItemIds, userTargetFolder.Id); Console.WriteLine($"成功复制 {copiedItemIds.Count} 个联系人到用户 {userEmail} 的文件夹"); }
关键注意事项
- 权限配置:EWS应用需拥有
Mail.ReadWrite(用户邮箱)和PublicFolder.ReadWrite(公用文件夹)的应用权限,且已在Azure AD完成管理员同意授权。 - 分页处理:若联系人数量超过1000条,需通过
ItemView的Offset和PageSize实现分页获取,避免单次操作超限。 - 令牌刷新:OAuth令牌存在有效期,需实现自动刷新逻辑,防止操作中途因令牌失效中断。
内容的提问来源于stack exchange,提问作者ADY
相关产品推荐
相关产品推荐

