OnSend事件中确定性设置OfficeJs邮件项头及有效性验证技术问询
确保EWS设置的互联网头在OnSend事件完成前同步到OfficeJS邮件项
嘿,这个问题我之前开发Outlook插件时也踩过坑——核心难点在于mailbox.makeEwsRequestAsync是异步操作,而OnSend事件必须等所有关键操作完成后才能放行发送。结合你提到的REST API变更不体现、ExtendedProperties设置头的关联问题,我整理了一套可靠的解决方案:
1. 把EWS调用封装成Promise,用async/await控制流程
别再用传统的回调嵌套了,把makeEwsRequestAsync包装成返回Promise的函数,这样就能在OnSend的异步处理逻辑里用await等待它执行完毕,确保设置头的操作先完成:
function makeEwsRequestAsyncPromise(ewsXml) { return new Promise((resolve, reject) => { Office.context.mailbox.makeEwsRequestAsync(ewsXml, function(asyncResult) { if (asyncResult.status === Office.AsyncResultStatus.Failed) { reject(asyncResult.error); } else { resolve(asyncResult.value); } }); }); }
2. 强制刷新OfficeJS邮件项的属性,同步服务器变更
EWS在服务器端修改完邮件头后,OfficeJS本地的Office.context.mailbox.item对象不会自动同步最新数据。所以在EWS调用成功后,必须主动刷新属性来确认头已经存在:
- 如果是自定义互联网头,你可以用
getPropertyAsync直接获取并验证:
// 验证指定的互联网头是否已设置 function verifyInternetHeader(headerName, expectedValue) { return new Promise((resolve, reject) => { Office.context.mailbox.item.getPropertyAsync("InternetHeaders", function(result) { if (result.status === Office.AsyncResultStatus.Succeeded) { const headers = result.value; if (headers[headerName] === expectedValue) { resolve(); } else { reject(new Error(`Header ${headerName} not set correctly`)); } } else { reject(result.error); } }); }); }
- 如果是用ExtendedProperties设置的头,就调用
loadCustomPropertiesAsync来刷新并验证自定义属性。
3. 用OnSend的event.completed()精准控制发送时机
OnSend事件的核心规则是:你必须调用event.completed()来告诉Outlook是否允许发送邮件。所以一定要把所有异步操作(EWS调用、属性刷新、验证)都完成后,再执行这个方法。完整的OnSend处理流程示例:
Office.actions.associate("onSend", async function(event) { try { // 构造EWS请求XML,替换成你要设置的互联网头 const targetHeader = "X-Custom-Workflow-Id"; const headerValue = "WF-2024-001"; const ewsXml = `<?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"> <soap:Header> <t:RequestServerVersion Version="Exchange2013_SP1"/> </soap:Header> <soap:Body> <UpdateItem MessageDisposition="SaveOnly" ConflictResolution="AlwaysOverwrite" xmlns="http://schemas.microsoft.com/exchange/services/2006/messages"> <ItemChanges> <t:ItemChange> <t:ItemId Id="${Office.context.mailbox.item.itemId}" ChangeKey="${Office.context.mailbox.item.changeKey}"/> <t:Updates> <t:SetItemField> <t:FieldURI FieldURI="item:InternetHeaders"/> <t:Message> <t:InternetHeaders> <t:InternetHeader HeaderName="${targetHeader}">${headerValue}</t:InternetHeader> </t:InternetHeaders> </t:Message> </t:SetItemField> </t:Updates> </t:ItemChange> </ItemChanges> </UpdateItem> </soap:Body> </soap:Envelope>`; // 等待EWS设置头的操作完成 await makeEwsRequestAsyncPromise(ewsXml); // 验证头是否已同步到OfficeJS的邮件项中 await verifyInternetHeader(targetHeader, headerValue); // 所有操作都没问题,允许发送邮件 event.completed({ allowEvent: true }); } catch (error) { // 出错时取消发送,并提示用户 event.completed({ allowEvent: false, errorMessage: `Failed to set required email header: ${error.message}` }); } });
4. 解决关联的REST API变更不体现问题
不管你是用EWS还是Outlook REST API设置邮件头/扩展属性,OfficeJS的本地对象都不会自动同步服务器端的变更。所以处理逻辑是一致的:修改完成后必须主动刷新并验证属性,确保在OnSend放行前,本地对象能获取到最新的服务器数据。另外,尽量避免在OnSend事件中同时混用REST和EWS调用,防止并发修改导致的冲突。
内容的提问来源于stack exchange,提问作者Michahell
相关产品推荐
相关产品推荐

