You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 03:24:30