创建加密 Outlook 外接程序 (预览版)

在 Outlook 外接程序中实现自定义加密和解密功能,以保护电子邮件通信。 该 OnMessageRead 事件允许加载项自动识别加密消息并处理解密、内容显示和错误通知。

注意

事件 OnMessageRead 和解密 API 处于预览状态。 不应在生产加载项中使用预览版功能,因为它们可能会根据我们收到的反馈而更改。 我们邀请你在测试或开发环境中试用此功能,并欢迎通过 GitHub 提供有关体验的反馈 (请参阅本页末尾的“Office 加载项反馈”部分) 。

加密和解密工作流概述

提示

  • 加密和解密工作流实现基于事件的激活功能。 如果不熟悉 Outlook 加载项中的基于事件的激活,建议首先了解该功能及其实现。 若要了解详细信息,请参阅 使用事件激活加载项
  • 本部分建议的每个 API 的最低要求集和支持的平台可能会有所不同。 建议针对 Outlook JavaScript API 要求集 验证任何要求,并使用特定 API 的文档对其进行补充。

下表概述了 Outlook 加载项的加密和解密工作流。 它还标识步骤是否需要自定义解决方案或 Office JavaScript (Office.js) API 库支持。

步骤 实现
用户撰写邮件并使用加载项应用加密规则 您必须实现自己的加密协议,以便加载项可以保护邮件及其附件的内容。
用户发送消息 实现 OnMessageSend 事件的处理程序,以便在用户选择 “发送”时,外接程序可以自动运行加密协议。

若要标识在解密过程中使用加载项加密的消息,请使用 Internet 标头 API 向消息添加标头。 标头键必须与加载项清单中 HeaderNameOnMessageRead 事件的 LaunchEvent> 元素的 属性<中指定的值匹配。 有关详细信息,请参阅 使用基于事件的激活实现解密
收件人接收加密邮件并将其打开 如果收件人具有用于加密 Outlook 中安装的邮件的相同加载项,则外接程序会检查邮件中包含的标头密钥是否与清单中为 OnMessageRead 事件指定的值匹配。 此作由处理OnMessageRead事件的加载项自动完成,因此无需手动实现检查。 如果标头匹配,则 OnMessageRead 发生事件,并运行其处理程序。 有关详细信息,请参阅 使用基于事件的激活实现解密
加载项解密消息 必须在事件处理程序中 OnMessageRead 实现自己的解密协议。 当加载项解密邮件及其附件时,会向用户显示一条通知,提醒他们加载项正在处理其邮件。 此通知由处理 OnMessageRead 事件的加载项自动显示,因此无需手动创建一个。
收件人查看解密的邮件及其附件(如果有) 解密作完成后,系统会自动向用户显示一条通知,提醒他们加载项已完成消息处理。 OnMessageRead在处理程序中,调用 event.completed 方法并向其传递 MessageDecryptEventCompletedOptions 对象。 MessageDecryptEventCompletedOptions使用 对象,可以指定是否向收件人显示解密的内容。 有关详细信息,请参阅 实现事件处理

使用基于事件的激活实现解密

必须实现自己的加密和解密协议。 加载项还必须配置为处理事件, OnMessageRead 以便方便地确定加载项何时可以解密消息并显示解密的内容。 若要实现事件 OnMessageRead ,必须:

  1. 配置加载项的清单
  2. 实现事件处理

支持的环境

消息OnMessageRead读取图面支持事件。 支持因客户端和 Exchange 环境而异,如下表所示。

客户端 Exchange Online Exchange Subscription Edition (SE) Exchange Server 2019 Exchange Server 2016
Web 浏览器 不可用 不可用 不可用 不可用
Windows (新) 不可用 不可用 不可用 不可用
Windows (经典)
版本 2510 (内部版本 19312.20000) 及更高版本
预览版 不可用 不可用 不可用
Mac 不可用 不可用 不可用 不可用
Android 不可用 不可用 不可用 不可用
iOS 不可用 不可用 不可用 不可用

预览经典 Outlook on Windows 中的解密 API

若要预览经典 Outlook on Windows 中的解密 API,请加入 Microsoft 365 预览体验计划,然后选择 Outlook 客户端中的 Beta 版频道。 客户端必须位于版本 2510 (内部版本 19312.20000) 或更高版本上。

经典 Outlook on Windows 包括 Office.js 的生产和 beta 版本的本地副本,而不是从内容分发网络加载 (CDN) 。 默认情况下,将引用 API 的本地生产副本。 若要引用 API 的本地 beta 版副本,必须配置计算机的注册表。 这将使您能够在经典 Outlook on Windows 中的事件处理程序中测试 预览功能

  1. 在注册表中,导航到 HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\Outlook\Options\WebExt\Developer。 如果该键不存在,请创建它。

  2. 创建名为 的 EnableBetaAPIsInJavaScript 条目,并将其值设置为 1

    注册表编辑器中的“EnableBetaAPIsInJavaScript”项设置为 1。

配置清单

注意

事件 OnMessageRead 当前只能使用仅外接程序清单实现。

若要在事件上 OnMessageRead 激活加载项,必须配置 <加载项manifest.xml> 文件的 VersionOverridesV1_1 节点,如下所示。

  • 若要在经典 Outlook on Windows 中运行基于事件的外接程序,必须在 Runtime> 元素的 Override 子元素中指定包含事件处理程序的< JavaScript 文件。<>
  • OnMessageReadLaunchEvent> 元素的< 属性中Type指定 事件。 必须将事件处理程序的函数名称分配给 FunctionName 元素的 属性。 为了便于检查消息是否已由加载项加密,必须在 属性中 HeaderName 指定标头密钥。 同一标头将添加到由加载项加密的消息中。

下面是实现 OnMessageRead 事件的节点示例<VersionOverrides>

<VersionOverrides xmlns="http://schemas.microsoft.com/office/mailappversionoverrides" xsi:type="VersionOverridesV1_0">
  <VersionOverrides xmlns="http://schemas.microsoft.com/office/mailappversionoverrides/1.1" xsi:type="VersionOverridesV1_1">
    <Requirements>
      <bt:Sets DefaultMinVersion="1.15">
        <bt:Set Name="Mailbox"/>
      </bt:Sets>
    </Requirements>
    <Hosts>
      <Host xsi:type="MailHost">
        <Runtimes>
            <!-- References the HTML file that links to the event handler. -->
          <Runtime resid="WebViewRuntime.Url">
            <!-- References the JavaScript file that contains the event handler. This is used by classic Outlook on Windows. -->
            <Override type="javascript" resid="JSRuntime.Url"/>
          </Runtime>
        </Runtimes>
        <DesktopFormFactor>
          <FunctionFile resid="WebViewRuntime.Url"/>
          <!-- Implements event-based activation. -->
          <ExtensionPoint xsi:type="LaunchEvent">
            <LaunchEvents>
              <LaunchEvent Type="OnMessageSend" FunctionName="onMessageSendHandler" SendMode="SoftBlock"/>
              <LaunchEvent Type="OnMessageRead" FunctionName="onMessageReadHandler" HeaderName="contoso-encrypted"/>
            </LaunchEvents>
            <!-- Identifies the runtime to be used (also referenced by the Runtime element). -->
            <SourceLocation resid="WebViewRuntime.Url"/>
        </ExtensionPoint>
        </DesktopFormFactor>
      </Host>
    </Hosts>
    <Resources>
      ...
      <bt:Urls>
        <bt:Url id="WebViewRuntime.Url" DefaultValue="https://www.contoso.com/launchevent.html"/>
        <bt:Url id="JSRuntime.Url" DefaultValue="https://www.contoso.com/launchevent.js"/>
      </bt:Urls>
      ...
    </Resources>
  </VersionOverrides>
</VersionOverrides>

实现事件处理

事件处理程序 OnMessageRead 用于运行解密作,并确定是否显示消息的解密内容。

  • 若要确保处理程序在事件发生时 OnMessageRead 运行,请在实现处理程序的 JavaScript 文件中调用 Office.actions.associate 。 这会将清单中 元素的 <LaunchEvent> 属性中指定的FunctionName处理程序名称映射到其 JavaScript 对应名称。
  • 解密作完成后,必须调用 event.completed 以向客户端发出信号,指出加载项已完成事件处理 OnMessageRead 。 若要显示邮件及其附件的解密内容,请将 MessageDecryptEventCompletedOptions 对象传递给调用, event.completed 并将其 allowEvent 属性设置为 true。 然后,在对象的 emailBody附件 属性中指定邮件的解密内容。 还可以在 contextData 属性中指定加载项可能需要处理的任何数据。 例如,可以存储自定义 Internet 标头,以在答复和转发方案中解密消息。

注意

为 Windows 上的经典 Outlook 创建基于事件的加载项时,请注意以下事项。

  • 包含事件处理程序的 JavaScript 文件中当前不支持导入。
  • 当清单中指定的用于处理事件的 JavaScript 函数运行时,和 中的代码Office.onReady()Office.initialize不会运行。 建议改为将事件处理程序所需的任何启动逻辑(例如检查用户的 Outlook 版本)添加到事件处理程序。

下面是事件处理程序的示例 OnMessageRead

function onMessageReadHandler(event) {
    // Your code to decrypt the contents of a message would appear here.
    ...

    // Use the results from your decryption process to display the decrypted contents of the message body and attachments.
    const decryptedBodyContent = "<p>Please find attached the recent report and its supporting documentation.</p>";
    const decryptedBody = {
        coercionType: Office.CoercionType.Html,
        content: decryptedBodyContent
    };

    // Decrypted content and properties of a file attachment.
    const decryptedPdfFile = "JVBERi0xLjQKJeLjz9MKNCAwIG9i...";
    const pdfFileName = "Fabrikam_Report_202509";

    // Decrypted content and properties of a mail item.
    const decryptedEmailFile = "VGhpcyBpcyBhIHRleHQgZmlsZS4=...";
    const emailFileName = "Fabrikam_Report_202508.eml";

    // Decrypted properties of a cloud attachment.
    const cloudFilePath = "https://contosostorage.com/reports/weekly_forecast.xlsx";
    const cloudFileName = "weekly_forecast.xlsx";

    // Decrypted content and properties of an inline image.
    const decryptedImageFile = "iVBORw0KGgoAAAANSUhEUgAA...";
    const imageFileName = "banner.png";
    const imageContentId = "image001.png@01DC1DD9.1A4AA300";

    const decryptedAttachments = [
      {
        attachmentType: Office.MailboxEnums.AttachmentType.File,
            content: decryptedPdfFile,
            isInline: false,
            name: pdfFileName
        },
        {
          attachmentType: Office.MailboxEnums.AttachmentType.Item,
            content: decryptedEmailFile,
            isInline: false,
            name: emailFileName
        },
        {
          attachmentType: Office.MailboxEnums.AttachmentType.Cloud,
            isInline: false,
            name: cloudFileName,
            path: cloudFilePath
        },
        {
          attachmentType: Office.MailboxEnums.AttachmentType.File,
            content: decryptedImageFile,
            contentId: imageContentId,
            isInline: true,
            name: imageFileName
        }
    ];

    event.completed({
        allowEvent: true,
        emailBody: decryptedBody,
        attachments: decryptedAttachments,
        contextData: { messageType: "ReplyFromDecryptedMessage" }
    });
}

// IMPORTANT: To ensure your add-in is supported in Outlook, remember to map the event handler name specified in the manifest to its JavaScript counterpart.
Office.actions.associate("onMessageReadHandler", onMessageReadHandler);

提示

在经典 Outlook on Windows 中,当图像作为内联附件添加到邮件时,会自动为其分配内容 ID。 在邮件正文中,内联附件的内容 ID 在 元素的 <img> 属性中src指定,类似于以下示例。

<img width=96 height=96 id="Picture_1" src="cid:image001.png@01DC1E6F.FC7C7410">

为了在解密期间轻松识别并提供这些内联附件,我们建议在加密期间将内联附件的内容 ID 保存到邮件头。 调用 Office.context.mailbox.item.getAttachmentsAsync 以获取内联附件 的内容 ID 。 然后,调用 Office.context.mailbox.item.internetHeaders.setAsync 将 ID 保存到邮件头。

行为和限制

  • 请注意基于事件的加载项的行为和限制。若要了解详细信息,请参阅 使用事件激活加载项

  • 由于每个外接程序都使用其自己的加密协议,因此消息只能由加密它的同一加载项解密。 如果用户未安装解密消息所需的加载项,则会发出通知,提醒他们消息已加密。 若要引导用户完成解密过程,请为加密邮件的正文自定义占位符消息。 占位符消息可以包含有关如何安装加载项的信息。 若要在加密过程中设置邮件正文,请调用 Office.context.mailbox.item.body.setAsync

    加密消息的示例占位符消息。

  • 为确保数据安全性和机密性,已解密的内容不会存储在 Outlook 客户端上。 每次用户打开加密邮件时,都会解密该邮件的内容。

  • 必须先解密加密邮件,然后用户才能答复或转发该邮件。 在解密加密邮件时,用户无法回复或转发该邮件。

  • 如果用户在解密加密邮件时导航到另一个邮件项,则解密过程将停止运行。 用户必须再次选择或打开邮件才能激活解密过程。

  • 答复或转发加密邮件时,草稿以未加密的方式保存在 “草稿 ”文件夹中。

解密通知

处理 OnMessageRead 事件的加载项在某些解密方案中自动显示通知,如下表所述。

通知 应用场景
<加载项名称> 不可用,目前无法处理你的消息。 仅适用于经典 Outlook on Windows。 当加载项加载失败时,将显示此通知,因为错误阻止加载项加载或用户的客户端或计算机脱机。
<加载项名称> 无法处理邮件。 加载项解密消息时遇到错误。 若要重试解密作,收件人必须切换到另一封邮件,然后再次打开加密邮件以调用事件 OnMessageRead
<加载项名称> 加载项正在解密邮件。 加载项正在处理 事件 OnMessageRead 以解密消息。
此消息由 <外接程序名称> 加载项加密。 此通知将显示给未安装必要加密加载项的收件人。 若要提供有关如何解密消息的指导,请在加密邮件的正文中包含占位符消息。 有关详细信息,请参阅 行为和限制
<加载项名称> 加载项已解密邮件。 加载项已成功解密消息的内容。 用户现在可以查看邮件及其附件。
<加载项名称> 处理邮件所需的时间比预期长。 加载项运行时间已超过 5 秒,但不到 5 分钟。
<加载项名称> 超时。若要重试,请选择另一封电子邮件,然后返回到此邮件。 加载项在运行 5 分钟后超时。 若要重试解密作,收件人必须切换到另一封邮件,然后再次打开加密邮件以调用事件 OnMessageRead

另请参阅