EWS Managed API报错‘DTD在XML文档中被禁止’的原因及解决方法
问题描述
在搜索Allitems文件夹时,遇到了**"DTD在XML文档中被禁止"**的错误。该代码此前正常运行多年,更换服务器后又正常运行了数月,当前突然触发此错误。
使用的示例代码如下:
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013_SP1); string exchangeURL = "ExchangeURL"; Uri myUri = new Uri(exchangeURL); service.TraceEnabled = true; service.Url = myUri; service.UseDefaultCredentials = true; service.Credentials = new WebCredentials("email", "password"); //service.AutodiscoverUrl(empMail.PrimaryEmail); service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, empMail.EmployeeEmail); //Certificate validation handling ServicePointManager.ServerCertificateValidationCallback += (se, cert, chain, sslerror) => { return true; }; EmailMessage message; PropertySet propertySet; Mailbox mailBox = new Mailbox("Email"); ItemView itemView = new ItemView(1); itemView.Traversal = ItemTraversal.Shallow; //Try to get 'Allitems' folder so that we could search items in all folders FolderId fid = new FolderId(WellKnownFolderName.Root); FolderView fv = new FolderView(1); fv.Traversal = FolderTraversal.Shallow; ExtendedPropertyDefinition epd = new ExtendedPropertyDefinition(13825, MapiPropertyType.Integer); SearchFilter sf = new SearchFilter.IsEqualTo(epd, "2"); SearchFilter sf2 = new SearchFilter.IsEqualTo(FolderSchema.DisplayName, "allitems"); SearchFilter.SearchFilterCollection sfc = new SearchFilter.SearchFilterCollection(LogicalOperator.And); sfc.Add(sf); sfc.Add(sf2); FindFoldersResults findAllItemsFolderresult = service.FindFolders(fid, sfc, fv);
错误原因
- 服务器安全策略更新:Exchange服务器近期可能调整了XML解析配置,禁用DTD解析以防范注入类安全风险,导致客户端收到含DTD的响应时触发错误。
- EWS响应格式变化:服务器返回的XML响应中新增了DTD声明,但当前使用的EWS Managed API默认不允许解析DTD。
- 版本兼容性偏差:代码中指定的
Exchange2013_SP1版本与服务器实际版本不匹配,引发响应解析兼容性问题。
解决方案
1. 允许EWS API解析DTD
在初始化ExchangeService前,修改XmlReaderSettings开启DTD解析:
// 先配置XML解析设置 System.Xml.XmlReaderSettings xmlSettings = new System.Xml.XmlReaderSettings(); xmlSettings.DtdProcessing = System.Xml.DtdProcessing.Parse; // 初始化ExchangeService ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013_SP1); // 若上述方法不生效,通过反射修改API内部的XmlReader配置 var bindingFlags = System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic; var internalSettings = service.GetType().GetField("_xmlReaderSettings", bindingFlags) as System.Xml.XmlReaderSettings; if (internalSettings != null) { internalSettings.DtdProcessing = System.Xml.DtdProcessing.Parse; }
2. 匹配Exchange服务器版本
确认当前Exchange服务器的实际版本,将代码中的ExchangeVersion参数更新为对应版本,例如服务器为Exchange 2016时:
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2016);
3. 直接绑定AllItems文件夹
放弃通过搜索属性查找Allitems的方式,直接使用WellKnownFolderName.AllItems绑定文件夹,这是官方推荐的可靠方法:
// 替换原有的文件夹查找逻辑 Folder allItemsFolder = Folder.Bind(service, WellKnownFolderName.AllItems, new PropertySet(BasePropertySet.IdOnly));
4. 协调服务器端配置
联系Exchange管理员,确认是否近期修改了XML安全策略,可尝试调整服务器配置,使EWS响应不包含DTD声明,或允许特定客户端的DTD解析请求。
内容的提问来源于stack exchange,提问作者tushar
相关产品推荐
相关产品推荐

