Outlook 365/Windows 10插件无法自动加载默认邮件签名
Outlook 365/Windows 10插件无法自动加载默认邮件签名
我明白你现在遇到的问题了——刚开发的Outlook 365/Windows 10插件,下拉菜单打开对应模板邮件的功能都正常,但就是设置好的默认签名没法自动加载到新邮件里,明明已经把签名设为新邮件默认了对吧?
先给你梳理下问题根因:当你通过displayNewMessageForm方法指定了htmlBody参数时,Outlook会判定你要完全自定义邮件内容,不会自动插入默认签名。你原来的代码里尝试在打开邮件后去获取签名,但这个时机不对——新邮件草稿还没完全初始化完成,Office.context.mailbox.item可能还没指向新打开的草稿,自然拿不到正确的签名内容。
下面给你调整后的解决方案,核心是先获取用户的默认签名,再和模板内容组合后一起创建新邮件:
原代码参考
manifest.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <OfficeApp xmlns="http://schemas.microsoft.com/office/appforoffice/1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bt="http://schemas.microsoft.com/office/officeappbasictypes/1.0" xmlns:mailappor="http://schemas.microsoft.com/office/mailappversionoverrides/1.0" xsi:type="MailApp"> <Id>2eb95a7a-bc4a-4f53-bc6f-ba64b72d8663</Id> <Version>1.0.0.0</Version> <ProviderName>Contoso</ProviderName> <DefaultLocale>en-US</DefaultLocale> <DisplayName DefaultValue="NewClientMatter"/> <Description DefaultValue="A template to get started."/> <IconUrl DefaultValue="https://localhost:3000/assets/icon-64.png"/> <HighResolutionIconUrl DefaultValue="https://localhost:3000/assets/icon-128.png"/> <SupportUrl DefaultValue="https://www.contoso.com/help"/> <AppDomains> <AppDomain>https://www.contoso.com</AppDomain> </AppDomains> <Hosts> <Host Name="Mailbox"/> </Hosts> <Requirements> <Sets> <Set Name="Mailbox" MinVersion="1.5"/> </Sets> </Requirements> <FormSettings> <Form xsi:type="ItemRead"> <DesktopSettings> <SourceLocation DefaultValue="https://localhost:3000/taskpane.html"/> <RequestedHeight>250</RequestedHeight> </DesktopSettings> </Form> </FormSettings> <Permissions>ReadWriteItem</Permissions> <Rule xsi:type="RuleCollection" Mode="Or"> <Rule xsi:type="ItemIs" ItemType="Message" FormType="Read"/> <Rule xsi:type="ItemIs" ItemType="Message" FormType="Edit"/> </Rule> <DisableEntityHighlighting>false</DisableEntityHighlighting> <VersionOverrides xmlns="http://schemas.microsoft.com/office/mailappversionoverrides" xsi:type="VersionOverridesV1_0"> <Requirements> <bt:Sets DefaultMinVersion="1.5"> <bt:Set Name="Mailbox"/> </bt:Sets> </Requirements> <Hosts> <Host xsi:type="MailHost"> <DesktopFormFactor> <FunctionFile resid="Commands.Url"/> <ExtensionPoint xsi:type="MessageReadCommandSurface"> <OfficeTab id="TabDefault"> <Group id="msgReadGroup"> <Label resid="GroupLabel"/> <Control xsi:type="Menu" id="DropdownMenu"> <Label resid="DropdownMenu.Label"/> <Supertip> <Title resid="DropdownMenu.Label"/> <Description resid="DropdownMenu.Tooltip"/> </Supertip> <Icon> <bt:Image size="16" resid="MenuIcon.16x16"/> <bt:Image size="32" resid="MenuIcon.32x32"/> <bt:Image size="80" resid="MenuIcon.80x80"/> </Icon> <Items> <Item id="InternalAction"> <Label resid="InternalAction.Label"/> <Supertip> <Title resid="InternalAction.Label"/> <Description resid="InternalAction.Tooltip"/> </Supertip> <Icon> <bt:Image size="16" resid="InternalIcon.16x16"/> <bt:Image size="32" resid="InternalIcon.32x32"/> <bt:Image size="80" resid="InternalIcon.80x80"/> </Icon> <Action xsi:type="ExecuteFunction"> <FunctionName>handleInternalAction</FunctionName> </Action> </Item> <Item id="ExternalAction"> <Label resid="ExternalAction.Label"/> <Supertip> <Title resid="ExternalAction.Label"/> <Description resid="ExternalAction.Tooltip"/> </Supertip> <Icon> <bt:Image size="16" resid="ExternalIcon.16x16"/> <bt:Image size="32" resid="ExternalIcon.32x32"/> <bt:Image size="80" resid="ExternalIcon.80x80"/> </Icon> <Action xsi:type="ExecuteFunction"> <FunctionName>handleExternalAction</FunctionName> </Action> </Item> </Items> </Control> </Group> </OfficeTab> </ExtensionPoint> </DesktopFormFactor> </Host> </Hosts> <Resources> <bt:Images> <bt:Image id="MenuIcon.16x16" DefaultValue="https://localhost:3000/assets/menu-icon-16.png"/> <bt:Image id="MenuIcon.32x32" DefaultValue="https://localhost:3000/assets/menu-icon-32.png"/> <bt:Image id="MenuIcon.80x80" DefaultValue="https://localhost:3000/assets/menu-icon-80.png"/> <bt:Image id="InternalIcon.16x16" DefaultValue="https://localhost:3000/assets/int-16.png"/> <bt:Image id="InternalIcon.32x32" DefaultValue="https://localhost:3000/assets/int-32.png"/> <bt:Image id="InternalIcon.80x80" DefaultValue="https://localhost:3000/assets/int-80.png"/> <bt:Image id="ExternalIcon.16x16" DefaultValue="https://localhost:3000/assets/ext-16.png"/> <bt:Image id="ExternalIcon.32x32" DefaultValue="https://localhost:3000/assets/ext-32.png"/> <bt:Image id="ExternalIcon.80x80" DefaultValue="https://localhost:3000/assets/ext-80.png"/> </bt:Images> <bt:Urls> <bt:Url id="Commands.Url" DefaultValue="https://localhost:3000/commands.html"/> <bt:Url id="Taskpane.Url" DefaultValue="https://localhost:3000/taskpane.html"/> <bt:Url id="CommandsJs.Url" DefaultValue="https://localhost:3000/commands/commands.js"/> </bt:Urls> <bt:ShortStrings> <bt:String id="GroupLabel" DefaultValue="New Client/Matter"/> <bt:String id="DropdownMenu.Label" DefaultValue="Choose Action"/> <bt:String id="InternalAction.Label" DefaultValue="Internal"/> <bt:String id="ExternalAction.Label" DefaultValue="External"/> </bt:ShortStrings> <bt:LongStrings> <bt:String id="DropdownMenu.Tooltip" DefaultValue="Select an action to perform."/> <bt:String id="InternalAction.Tooltip" DefaultValue="Opens an internal email template."/> <bt:String id="ExternalAction.Tooltip" DefaultValue="Opens an external email template."/> </bt:LongStrings> </Resources> </VersionOverrides> </OfficeApp>
原commands.ts代码
/* global Office */ Office.onReady(function (info) { if (info.host === Office.HostType.Outlook) { Office.actions.associate("handleInternalAction", handleInternalAction); Office.actions.associate("handleExternalAction", handleExternalAction); } }); /** * Handles the "Internal" action. * @param event The Office Add-in event. */ function handleInternalAction(event: Office.AddinCommands.Event): void { openEmailTemplate("internal", event); } /** * Handles the "External" action. * @param event The Office Add-in event. */ function handleExternalAction(event: Office.AddinCommands.Event): void { openEmailTemplate("external", event); } /** * Opens an email template with the user's signature. * @param templateType The type of template ("internal" or "external"). * @param event The Office Add-in event. */ function openEmailTemplate(templateType: string, event: Office.AddinCommands.Event): void { let templateBody: string; let subject: string; if (templateType === "internal") { templateBody = ` My fields<br/><br/> `; subject = "(Internal)"; } else if (templateType === "external") { templateBody = ` My fields<br/><br/> `; subject = "(External)"; } else { console.error("Invalid template type specified:", templateType); event.completed(); return; } // Open a new email draft Office.context.mailbox.displayNewMessageForm({ subject, htmlBody: templateBody, }); // Function to check draft readiness and insert the signature const checkDraftReady = () => { Office.context.mailbox.item.body.getAsync(Office.CoercionType.Html, (result) => { if (result.status === Office.AsyncResultStatus.Succeeded) { const userSignature = result.value || ""; if (userSignature) { const combinedBody = ` <html> <head> <meta charset="utf-8"> </head> <body> ${templateBody} <!-- Template Body --> <br/><br/> ${userSignature} <!-- User Signature --> </body> </html> `; Office.context.mailbox.item.body.setAsync(combinedBody, { coercionType: Office.CoercionType.Html }, (setResult) => { if (setResult.status === Office.AsyncResultStatus.Succeeded) { console.log("Signature inserted successfully"); } else { console.error("Failed to insert signature:", setResult.error.message); } event.completed(); }); } else { console.log("No signature found"); event.completed(); } } else { console.error("Failed to get email body:", result.error.message); // Retry if draft isn't ready yet setTimeout(checkDraftReady, 500); } }); }; checkDraftReady(); }
修改后的解决方案(更新commands.ts)
核心是用Office.context.mailbox.userProfile.getSignatureAsync先获取用户的默认签名,再和模板内容组合后创建新邮件,这样就能确保签名正确加载:
/* global Office */ Office.onReady(function (info) { if (info.host === Office.HostType.Outlook) { Office.actions.associate("handleInternalAction", handleInternalAction); Office.actions.associate("handleExternalAction", handleExternalAction); } }); /** * Handles the "Internal" action. * @param event The Office Add-in event. */ function handleInternalAction(event: Office.AddinCommands.Event): void { openEmailTemplate("internal", event); } /** * Handles the "External" action. * @param event The Office Add-in event. */ function handleExternalAction(event: Office.AddinCommands.Event): void { openEmailTemplate("external", event); } /** * Opens an email template with the user's signature. * @param templateType The type of template ("internal" or "external"). * @param event The Office Add-in event. */ function openEmailTemplate(templateType: string, event: Office.AddinCommands.Event): void { let templateBody: string; let subject: string; if (templateType === "internal") { templateBody = ` My fields<br/><br/> `; subject = "(Internal)"; } else if (templateType === "external") { templateBody = ` My fields<br/><br/> `; subject = "(External)"; } else { console.error("Invalid template type specified:", templateType); event.completed(); return; } // 先获取用户默认签名 Office.context.mailbox.userProfile.getSignatureAsync((signatureResult) => { if (signatureResult.status === Office.AsyncResultStatus.Succeeded) { const userSignature = signatureResult.value || ""; // 组合模板内容和签名 const combinedHtmlBody = ` <html> <head> <meta charset="utf-8"> </head> <body> ${templateBody} ${userSignature} </body> </html> `; // 打开带签名的新邮件 Office.context.mailbox.displayNewMessageForm({ subject, htmlBody: combinedHtmlBody }).then(() => { console.log("New email with signature opened successfully"); event.completed(); }).catch((err) => { console.error("Failed to open new message form:", err.message); event.completed(); }); } else { console.error("Failed to get user signature:", signatureResult.error.message); // 如果获取签名失败,直接打开模板邮件 Office.context.mailbox.displayNewMessageForm({ subject, htmlBody: templateBody }).then(() => { event.completed(); }).catch((err) => { console.error("Failed to open new message form:", err.message); event.completed(); }); } }); }
补充说明
getSignatureAsync是Outlook专门用来获取用户默认签名的API,比你原来的方式更可靠,因为它直接获取系统存储的默认签名,不需要依赖新邮件草稿的加载状态。- 当你指定
htmlBody时,Outlook不会自动插入签名,所以必须手动把签名和模板内容组合后传入。 - 如果你想保留Outlook自动插入签名的行为,也可以不指定
htmlBody,打开邮件后再用body.setAsync设置模板内容,但这样用户可能会看到签名先出现再被模板覆盖的闪屏,体验不如提前组合好。
备注:内容来源于stack exchange,提问作者adumith
相关产品推荐
相关产品推荐

