MacOS Outlook2016中makeEwsRequestAsync大邮件无回调问题
我之前也踩过Mac Outlook 2016这个特定版本的坑——当EWS请求响应超过1MB时,makeEwsRequestAsync会直接静默失败,既不触发成功回调,也不返回错误提示,这和Windows版、较新Mac Outlook版本的行为完全不同。结合你提到的场景,这里有几个可行的解决方案:
1. 拆分EWS请求,控制单请求响应大小
问题的核心是单次请求的响应超过了1MB限制,我们可以把原来一次性获取Body、Subject、MimeContent的操作拆分成多个独立请求,让每个请求的响应都保持在1MB以内:
第一步:获取基础字段(Subject + Body)
先发送只包含Subject和Body的EWS请求,这两个字段的响应通常不会超过1MB:<?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Header> <t:RequestServerVersion Version="Exchange2013" /> </soap:Header> <soap:Body> <m:GetItem> <m:ItemShape> <t:BaseShape>IdOnly</t:BaseShape> <t:AdditionalProperties> <t:FieldURI FieldURI="item:Subject" /> <t:FieldURI FieldURI="item:Body" /> </t:AdditionalProperties> </m:ItemShape> <m:ItemIds> <t:ItemId Id="YOUR_ITEM_ID" /> </m:ItemIds> </m:GetItem> </soap:Body> </soap:Envelope>第二步:单独获取MimeContent
等第一个请求成功返回后,再发送专门获取MimeContent的请求——这个字段是大邮件体积的主要来源,单独请求能有效控制响应大小:<?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Header> <t:RequestServerVersion Version="Exchange2013" /> </soap:Header> <soap:Body> <m:GetItem> <m:ItemShape> <t:BaseShape>IdOnly</t:BaseShape> <t:AdditionalProperties> <t:FieldURI FieldURI="item:MimeContent" /> </t:AdditionalProperties> </m:ItemShape> <m:ItemIds> <t:ItemId Id="YOUR_ITEM_ID" /> </m:ItemIds> </m:GetItem> </soap:Body> </soap:Envelope>
2. 绕过makeEwsRequestAsync,直接调用EWS API
如果拆分请求还是无法解决(比如超大邮件的MimeContent单独请求也超过1MB),更可靠的方案是直接使用getCallbackTokenAsync获取授权令牌,然后自己通过fetch或XMLHttpRequest发起EWS请求。这种方式能完全掌控请求和响应的处理流程,不会出现静默失败的问题:
Office.context.mailbox.getCallbackTokenAsync({isRest: false}, function(tokenResult) { if (tokenResult.status === Office.AsyncResultStatus.Succeeded) { const authToken = tokenResult.value; const ewsEndpoint = Office.context.mailbox.ewsUrl; const targetItemId = Office.context.mailbox.item.itemId; const userEmail = Office.context.mailbox.userProfile.emailAddress; // 构造完整的EWS请求XML const ewsRequest = `<?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Header> <t:RequestServerVersion Version="Exchange2013" /> <t:ExchangeImpersonation> <t:ConnectingSID> <t:SmtpAddress>${userEmail}</t:SmtpAddress> </t:ConnectingSID> </t:ExchangeImpersonation> </soap:Header> <soap:Body> <m:GetItem> <m:ItemShape> <t:BaseShape>IdOnly</t:BaseShape> <t:AdditionalProperties> <t:FieldURI FieldURI="item:Subject" /> <t:FieldURI FieldURI="item:Body" /> <t:FieldURI FieldURI="item:MimeContent" /> </t:AdditionalProperties> </m:ItemShape> <m:ItemIds> <t:ItemId Id="${targetItemId}" /> </m:ItemIds> </m:GetItem> </soap:Body> </soap:Envelope>`; // 自己发起请求 fetch(ewsEndpoint, { method: 'POST', headers: { 'Authorization': `Bearer ${authToken}`, 'Content-Type': 'text/xml; charset=utf-8' }, body: ewsRequest }) .then(response => { if (!response.ok) { throw new Error(`请求失败,状态码:${response.status}`); } return response.text(); }) .then(xmlData => { // 解析XML响应,处理所需字段 console.log('获取到邮件数据:', xmlData); }) .catch(error => { // 这里可以捕获所有错误,包括响应过大的情况 console.error('处理邮件数据时出错:', error); }); } else { console.error('获取授权令牌失败:', tokenResult.error); } });
为什么会出现这个问题?
Mac Outlook 2016的makeEwsRequestAsync实现存在一个已知缺陷:当EWS响应超过1MB时,它不会触发任何回调(成功或失败都不会),而是直接丢弃响应。这个问题在后续的Mac Outlook版本中已经修复,但由于2016版本不再更新,只能通过上述方法规避。
内容的提问来源于stack exchange,提问作者Sagar Pilkhwal

