Outlook Add-in如何在ItemSend时获取已发送邮件的itemId?
获取Outlook已发送邮件的ItemId解决方案
问题原因
你用saveAsync拿到的是草稿邮件的临时ItemId——邮件发送前的保存操作仅生成草稿,当邮件真正发送并移入已发送文件夹时,Outlook会创建全新的邮件条目,对应的ItemId自然会发生变更。
两种可行实现方式
方式一:监听已发送文件夹的ItemAdded事件
这是最直接可靠的方案,通过监听已发送文件夹的新增邮件事件,直接获取最终的ItemId。
更新清单配置
添加监听已发送文件夹的扩展点,同时保留原有的ItemSend事件配置:<ExtensionPoint xsi:type="Events"> <Event Type="ItemSend" FunctionExecution="synchronous" FunctionName="onEmailOrEventSend" /> </ExtensionPoint> <ExtensionPoint xsi:type="Folder"> <FolderName>Sent Items</FolderName> <Event Type="ItemAdded" FunctionName="onSentItemAdded" /> </ExtensionPoint>标记待追踪邮件
在ItemSend事件中给邮件添加自定义属性,方便后续识别当前发送的邮件:function onEmailOrEventSend(event) { mailboxItem.loadCustomPropertiesAsync(asyncContext => { const customProps = asyncContext.value; // 生成唯一追踪标识(时间戳+主题哈希) const trackingId = Date.now() + '-' + mailboxItem.subject.replace(/\s/g, ''); customProps.set('TrackingId', trackingId); customProps.saveAsync(saveResult => { if (saveResult.error) { console.error('保存自定义属性失败:', saveResult.error); event.completed({ allowEvent: false }); } else { event.completed({ allowEvent: true }); // 存储追踪标识,用于后续匹配 window.currentTrackingId = trackingId; } }); }); }处理已发送文件夹新增事件
在onSentItemAdded函数中匹配追踪标识,获取最终ItemId:function onSentItemAdded(event) { const addedItem = event.item; addedItem.loadCustomPropertiesAsync(asyncContext => { const customProps = asyncContext.value; const trackingId = customProps.get('TrackingId'); if (trackingId === window.currentTrackingId) { console.log('已发送邮件ItemId:', addedItem.itemId); // 清除全局追踪标识 window.currentTrackingId = null; } }); }
方式二:通过Graph API查询已发送邮件
如果无法使用文件夹事件监听,可在邮件发送后通过Graph API查询匹配的邮件获取ItemId。
记录邮件信息并获取令牌
在ItemSend事件中留存邮件关键属性,同时获取Graph API访问令牌:function onEmailOrEventSend(event) { // 记录邮件核心信息 const emailInfo = { subject: mailboxItem.subject, sentTime: new Date().toISOString() }; // 获取Graph API令牌 Office.context.mailbox.getCallbackTokenAsync({ isRest: true }, result => { if (result.error) { console.error('获取令牌失败:', result.error); event.completed({ allowEvent: false }); } else { event.completed({ allowEvent: true }); // 延迟查询(邮件发送到已发送文件夹存在延迟) setTimeout(() => querySentEmail(result.value, emailInfo), 3000); } }); }调用Graph API查询匹配邮件
编写查询函数,根据主题和发送时间匹配已发送邮件:function querySentEmail(token, emailInfo) { const endpoint = `https://graph.microsoft.com/v1.0/me/mailFolders('sentitems')/messages?$filter=subject eq '${encodeURIComponent(emailInfo.subject)}' and sentDateTime ge '${emailInfo.sentTime}'`; fetch(endpoint, { headers: { 'Authorization': `Bearer ${token}` } }) .then(response => response.json()) .then(data => { if (data.value.length > 0) { // 取最新的匹配邮件(避免同主题重复邮件) const sentEmail = data.value.sort((a,b) => new Date(b.sentDateTime) - new Date(a.sentDateTime))[0]; console.log('已发送邮件ItemId:', sentEmail.id); } else { // 未找到则重试 setTimeout(() => querySentEmail(token, emailInfo), 2000); } }) .catch(err => console.error('查询失败:', err)); }
方案对比
- 方式一:本地事件监听,响应及时,无需额外权限,推荐优先使用。
- 方式二:依赖Graph API和网络请求,需处理延迟和重试,适合无法使用文件夹事件的场景。
内容的提问来源于stack exchange,提问作者Ritesh734
相关产品推荐
相关产品推荐

