Outlook 加载项的 Onsend 功能

Outlook 加载项的 on-send 功能提供了一种方法来处理邮件或会议项目,或阻止用户执行某些操作,并允许加载项在发送时设置某些属性。

注意

使用 Microsoft 365 统一清单的加载项不支持发送时功能。 通过使用 基于事件的激活 和/或对 OnMessageSendOnAppointmentSend 事件实现处理程序来实现类似的效果。 另请参阅以下有关智能警报的说明。

例如,使用 on-send 功能可以:

  • 防止用户发送敏感信息或将主题行留空。
  • 将特定的收件人添加到邮件中的“抄送”行中,或添加到会议中的“可选收件人”行中。

on-send 功能是由事件类型 ItemSend 触发的,无 UI。

有关 Onsend 功能的限制信息,请参阅本文稍后部分中介绍的限制

注意

智能警报 是发送功能的较新版本。 它在 要求集 1.12 中发布, OnMessageSend 并引入了 和 OnAppointmentSend 事件。 与“发送时”功能类似,智能警报使外接程序能够在发送邮件项目之前检查满足某些条件。 智能警报将自身与发送时功能区分开来,如下所示:

有关智能警报与按发送功能之间的差异的详细信息,请参阅 智能警报与发送时功能之间的差异。 我们邀请你 通过完成演练来试用智能警报

支持的客户端和平台

下表显示了 On-send 功能支持的客户端-服务器组合,包括所需的最低累积更新(如果适用)。 不支持排除的组合。

客户端 Exchange Online Exchange 2019 本地
(累积更新 1 或更高版本)
Exchange 2016 本地
(累积更新 6 或更高版本)
Web 浏览器:
新式 Outlook UI
不适用 不适用
Web 浏览器:
经典 Outlook UI
不适用
Windows:
版本 1910 (内部版本 12130.20272) 或更高版本
Mac:
版本 16.47 或更高版本

注意

on-send 功能已在要求集 1.8 中正式发布, (请参阅 当前服务器和客户端支持 以了解详细信息) 。 但请注意,该功能的支持矩阵是要求集的 超集。

重要

AppSource 中不允许使用 on-send 功能的加载项。

Onsend 功能的工作原理

可使用 Onsend 功能生成集成了 ItemSend 同步事件的 Outlook 加载项。 此事件检测到用户正在按“发送”按钮(或现有会议的“发送更新”按钮),并且如果验证失败,则可用于阻止该项目发送。 例如,当用户触发邮件发送事件时,使用 Onsend 功能的 Outlook 加载项可以执行以下操作:

  • 读取并验证电子邮件内容。
  • 验证邮件是否包含主题行。
  • 设置预先确定的收件人。

触发发送事件时,在 Outlook 的客户端上执行验证,并且加载项在超时前最多有 5 分钟的时间。如果验证失败,将阻止项目的发送,并在提示用户采取措施的信息栏中显示一条错误消息。

注意

在 Outlook 网页版中,当在 Outlook 浏览器选项卡中撰写的邮件中触发 on-send 功能时,项目会弹出到其自己的浏览器窗口或选项卡中,以便完成验证和其他处理。

以下屏幕截图显示了通知发件人添加主题的信息栏。

提示用户输入缺少的主题行的错误消息。

以下屏幕截图显示了一个信息栏,通知发件人已找到禁止使用的词语。

一条错误消息,告知用户已找到阻止的字词。

限制

Onsend 功能目前具有以下限制。

  • 发送时追加功能 – 如果在 on-send 处理程序中调用 item.body.AppendOnSendAsync ,则会返回错误。

  • AppSource – 不能将使用 On-send 功能的 Outlook 加载项发布到 AppSource, 因为它们将失败 AppSource 验证。 使用 Onsend 功能的加载项应由管理员部署。 如果想要将加载项发布到 AppSource 的选项,请考虑改用智能警报,这是发送时功能的较新版本。 若要详细了解智能警报以及如何部署这些外接程序,请参阅 使用智能警报和 Outlook 外接程序中的 OnMessageSend 和 OnAppointmentSend 事件 ,以及 基于事件的 Outlook 外接程序的 AppSource 列表选项

    重要

    运行 npm run validate验证加载项清单时,将收到错误“包含 ItemSend 事件的邮箱加载项无效。 邮箱外接程序清单包含 VersionOverrides 中的 ItemSend 事件,这是不允许的。”出现此消息是因为使用 ItemSend 事件的加载项(此版本的 on-send 功能需要)无法发布到 AppSource。 如果找不到其他验证错误,仍可旁加载和运行加载项。

  • 清单 - 每个加载项仅支持一个 ItemSend 事件。 如果清单中有两个或多个 ItemSend 事件,则该清单将无法通过验证。

  • 性能 – 到托管外接程序的 Web 服务器的多次往返可能会影响加载项的性能。 创建需要多个基于消息或会议的操作的加载项时,请考虑对性能的影响。

  • “稍后发送 ” (Mac 仅) - 如果有“发送时”加载项,则“ 稍后发送” 功能将不可用。

此外,不建议在 on-send 事件处理程序中调用 item.close() ,因为关闭项应在事件完成后自动发生。

邮箱类型/模式限制

只有 Outlook 网页版、Windows 版和 Mac 版中的用户邮箱支持 Onsend 功能。 除了加载项未按照 Outlook 加载项概述页的 “可用于加载项的邮箱项目 ”部分所述激活加载项的情况外,在脱机模式下,该功能目前不支持该模式可用的脱机模式。

如果 Outlook 加载项未激活,则 On-send 加载项不会运行,并且会发送消息。

但是,如果启用并可以使用“发送时”功能,但邮箱方案不受支持,则 Outlook 将不允许发送。

多个 Onsend 加载项

如果安装了多个 Onsend 加载项,则加载项将按照从 API getAppManifestCallgetExtensibilityContext 接收到的顺序运行。 如果第一个外接程序允许发送,则第二个外接程序可以更改阻止第一个外接程序进行发送的某些设置。 但是,如果所有已安装的外接程序均允许发送,则第一个外接程序将不会重新运行。

例如,Add-in1 和 Add-in2 均使用 Onsend 功能。 首先安装的是 Add-in1,接着安装的是 Add-in2。 Add-in1 验证邮件中出现的 Fabrikam 一词作为外接程序允许发送的条件。 但是,Add-in2 可以删除出现的所有 Fabrikam 词语。 邮件将与已删除 Fabrikam 的所有实例一同发送(归因于 Add-in1 和 Add-in2 的安装顺序)。

部署使用 Onsend 的 Outlook 加载项

建议管理员部署使用 Onsend 功能的 Outlook 加载项。 管理员必须确保 Onsend 加载项满足以下条件:

  • 任何时候打开撰写项目时均可用(针对电子邮件:新建、回复或转发)。
  • 用户无法关闭或禁用。

安装使用 Onsend 的 Outlook 加载项

Outlook 中的 Onsend 功能要求针对发送事件类型配置加载项。 选择要配置的平台。

Outlook 网页版 (经典) 的加载项(使用 on-send 功能)将为分配了将 OnSendAddinsEnabled 标志设置为 trueOutlook 网页版 邮箱策略的用户运行。

若要安装新的外接程序,请运行以下 Exchange Online PowerShell cmdlet。

$Data=Get-Content -Path '.\Contoso Message Body Checker.xml' -Encoding Byte –ReadCount 0
New-App -OrganizationApp -FileData $Data -DefaultStateForUser Enabled

注意

若要了解如何使用远程 PowerShell 连接到 Exchange Online,请参阅连接到 Exchange Online PowerShell

启用 Onsend 功能

默认情况下,Onsend 功能处于禁用状态。 管理员可以通过运行 Exchange Online PowerShell cmdlet 启用 Onsend。

要为所有用户启用 Onsend 加载项,请执行以下操作:

  1. 创建新的 Outlook 网页版邮箱策略。

     New-OWAMailboxPolicy OWAOnSendAddinAllUserPolicy
    

    注意

    管理员可以使用现有策略,但只有某些邮箱类型才支持 Onsend 功能。 系统将默认阻止 Outlook 网页版中不受支持的邮箱进行发送。

  2. 启用 Onsend 功能。

     Get-OWAMailboxPolicy OWAOnSendAddinAllUserPolicy | Set-OWAMailboxPolicy –OnSendAddinsEnabled:$true
    
  3. 将策略分配给用户。

     Get-User -Filter {RecipientTypeDetails -eq 'UserMailbox'}|Set-CASMailbox -OwaMailboxPolicy OWAOnSendAddinAllUserPolicy
    

为一组用户启用 Onsend 功能

为特定用户组启用 Onsend 功能的步骤如下。 在此示例中,管理员仅希望在财务用户(其中财务用户属于财务部门)的环境中启用 Outlook 网页版 Onsend 加载项功能。

  1. 为该组创建新的 Outlook 网页版邮箱策略。

     New-OWAMailboxPolicy FinanceOWAPolicy
    

    注意

    管理员可以使用现有策略,但只有某些邮箱类型才支持 Onsend 功能(有关详细信息,请参阅本文前面介绍的邮箱类型限制)。 系统将默认阻止 Outlook 网页版中不受支持的邮箱进行发送。

  2. 启用 Onsend 功能。

     Get-OWAMailboxPolicy FinanceOWAPolicy | Set-OWAMailboxPolicy –OnSendAddinsEnabled:$true
    
  3. 将策略分配给用户。

     $targetUsers = Get-Group 'Finance'|select -ExpandProperty members
     $targetUsers | Get-User -Filter {RecipientTypeDetails -eq 'UserMailbox'}|Set-CASMailbox -OwaMailboxPolicy FinanceOWAPolicy
    

注意

需要等待 60 分钟该策略才能生效,或重启 Internet Information Services (IIS)。 策略生效后,将为该组启用 Onsend 功能。

禁用 Onsend 功能

若要禁用用户的 Onsend 功能或分配未启用该标志的 Outlook 网页版邮箱策略,请运行以下 cmdlet。 在此示例中,该邮箱策略是 ContosoCorpOWAPolicy

Get-CASMailbox joe@contoso.com | Set-CASMailbox –OWAMailboxPolicy "ContosoCorpOWAPolicy"

注意

有关如何使用 Set-OwaMailboxPolicy cmdlet 配置现有 Outlook 网页版邮箱策略的详细信息,请参阅 Set-OwaMailboxPolicy

若要禁用所有分配了指定 Outlook 网页版邮箱策略的用户的 Onsend 功能,请运行以下 cmdlet。

Get-OWAMailboxPolicy OWAOnSendAddinAllUserPolicy | Set-OWAMailboxPolicy –OnSendAddinsEnabled:$false

Onsend 功能的应用场景

以下是支持和不支持使用 Onsend 功能的加载项的应用场景。

事件处理程序是动态定义的

加载项的事件处理程序必须在时间 Office.initialize 之前定义或 Office.onReady() 调用 (有关详细信息,请参阅 Outlook 加载项的启动初始化 Office 外接程序) 。 如果处理程序代码是在初始化期间由某些情况动态定义的,则必须创建一个存根函数,以在完全定义处理程序后调用该处理程序。 必须在清单的 Event> 元素的 属性中<引用存根函数。FunctionName 此解决方法可确保已定义处理程序,并准备好在一次或Office.onReady()运行后Office.initialize被引用。

如果在初始化加载项后未定义处理程序,则发件人将通过邮件项中的信息栏收到“无法访问回调函数”的通知。

用户邮箱启用了 Onsend 加载项功能,但未安装任何加载项

在此方案中,用户无需执行任何加载项即可发送消息和会议项目。

用户邮箱启用了 Onsend 加载项功能,并且安装并启用了支持 Onsend 的加载项

外接程序在发送事件期间运行,然后允许或阻止用户发送。

邮箱委派,其中邮箱 1 具有对邮箱 2 的完全访问权限

Web 浏览器(经典 Outlook)

方案 邮箱 1 Onsend 功能 邮箱 2 Onsend 功能 Outlook Web 会话(经典) 结果 是否支持?
1 已启用 已启用 新会话 邮箱 1 无法从邮箱 2 发送邮件或会议项目。 目前尚不支持。 可以使用方案 3 作为一种解决办法。
2 已禁用 已启用 新会话 邮箱 1 无法从邮箱 2 发送邮件或会议项目。 目前尚不支持。 可以使用方案 3 作为一种解决办法。
3 已启用 已启用 同一个会话 分配给邮箱 1 的 Onsend 加载项运行 Onsend。 支持。
4 已启用 已禁用 新会话 未运行 Onsend 加载项;邮件或会议项目已发送。 支持。

Web 浏览器(新式 Outlook)、Windows、Mac

若要强制执行 Onsend,管理员应确保对两个邮箱都启用了该策略。 若要了解如何在加载项中支持委托访问,请参阅 启用共享文件夹和共享邮箱方案

用户邮箱启用了 Onsend 加载项功能/策略,并且安装并启用了支持 Onsend 的加载项,启用了脱机模式

Onsend 加载项将根据用户、加载项后端和 Exchange 的联机状态运行。

用户的状态

如果用户处于联机状态,则 Onsend 加载项将在发送期间运行。 如果用户处于脱机状态,Onsend 加载项不会在发送期间运行,也不会发送邮件或会议项目。

加载项后端的状态

如果 Onsend 加载项的后端处于联机状态且可访问,则将运行该加载项。 如果后端处于脱机状态,则将禁用发送。

Exchange 的状态

如果 Exchange 服务器处于联机状态且可访问,则 Onsend 加载项将在发送期间运行。 如果 Onsend 加载项无法访问 Exchange 并且已启用适用的策略或 cmdlet,则将禁用发送。

注意

在处于任何脱机状态的 Mac 上,“发送”按钮(或现有会议的“发送更新”按钮)将被禁用,并显示当用户脱机时其组织不允许发送的通知。

用户可以在 on-send 加载项处理项目时对其进行编辑

当 on-send 外接程序正在处理项目时,用户可以通过添加(例如,不适当的文本或附件)来编辑该项目。 如果要在加载项在发送时处理时阻止用户编辑项目,可以使用对话框实现解决方法。 此解决方法可用于Outlook 网页版 (经典) 、Windows 和 Mac。

重要

新式Outlook 网页版:若要防止用户在加载项处理发送时编辑项目,应将 OnSendAddinsEnabled 标志设置为 true ,如本文前面的安装使用 on-send 的 Outlook 加载项部分中所述。

在 on-send 处理程序中:

  1. 调用 displayDialogAsync 以打开对话框,以便禁用鼠标单击和击键。

    重要

    若要在经典Outlook 网页版中获取此行为,应在调用的 displayDialogAsync 参数中optionsdisplayInIframe 属性设置为 true

  2. 实现项的处理。

  3. 关闭该对话框。 此外,处理用户关闭对话框时发生的情况。

代码示例

以下代码示例说明如何创建一个简单的 Onsend 加载项。 若要下载这些示例所基于的代码示例,请参阅 Outlook-Add-in-On-Send

提示

如果将对话与 on-send 事件一起使用,请确保在完成事件之前关闭对话。

清单、版本重写和事件

Outlook-Add-in-On-Send 代码示例包括两个清单:

  • Contoso Message Body Checker.xml– 演示如何在发送时检查邮件正文中的受限字词或敏感信息。

  • Contoso Subject and CC Checker.xml – 演示如何将收件人添加到抄送行,并验证邮件在发送时是否包含主题行。

Contoso Message Body Checker.xml 清单文件中,将包含在 ItemSend 事件中应调用的函数文件和函数名称。 该操作将同步运行。

<Hosts>
    <Host xsi:type="MailHost">
        <DesktopFormFactor>
            <!-- The functionfile and function name to call on message send.  -->
            <!-- In this case, the function validateBody will be called within the JavaScript code referenced in residUILessFunctionFileUrl. -->
            <FunctionFile resid="residUILessFunctionFileUrl" />
            <ExtensionPoint xsi:type="Events">
                <Event Type="ItemSend" FunctionExecution="synchronous" FunctionName="validateBody" />
            </ExtensionPoint>
        </DesktopFormFactor>
    </Host>
</Hosts>

重要

如果使用 Visual Studio 2019 开发 on-send 加载项,则可能会收到如下所示的验证警告:“这是无效的 xsi:type 'http://schemas.microsoft.com/office/mailappversionoverrides/1.1:Events'。”若要解决此问题,需要更新版本的 MailAppVersionOverridesV1_1.xsd,该版本已在 有关此警告的博客中作为 GitHub gist 提供。

对于 Contoso Subject and CC Checker.xml 清单文件,以下示例中显示了邮件发送事件中要调用的函数文件和函数名称。

<Hosts>
    <Host xsi:type="MailHost">
        <DesktopFormFactor>
            <!-- The functionfile and function name to call on message send.  -->
            <!-- In this case the function validateSubjectAndCC will be called within the JavaScript code referenced in residUILessFunctionFileUrl. -->
            <FunctionFile resid="residUILessFunctionFileUrl" />
            <ExtensionPoint xsi:type="Events">
                <Event Type="ItemSend" FunctionExecution="synchronous" FunctionName="validateSubjectAndCC" />
            </ExtensionPoint>
        </DesktopFormFactor>
    </Host>
</Hosts>

Onsend API 需要 VersionOverrides v1_1。 以下显示如何在清单中添加 VersionOverrides 节点。

 <VersionOverrides xmlns="http://schemas.microsoft.com/office/mailappversionoverrides" xsi:type="VersionOverridesV1_0">
     <!-- On-send requires VersionOverridesV1_1 -->
     <VersionOverrides xmlns="http://schemas.microsoft.com/office/mailappversionoverrides/1.1" xsi:type="VersionOverridesV1_1">
         ...
     </VersionOverrides>
</VersionOverrides>

注意

若要了解有关 Outlook 外接程序清单的详细信息,请参阅 Office 外接程序清单

Eventitem 对象以及 body.getAsyncbody.setAsync 方法

若要访问当前选择的邮件或会议项目(在本示例中为新撰写的邮件),请使用 Office.context.mailbox.item 命名空间。 事件 ItemSend 由 on-send 功能自动传递到清单中指定的函数(在此示例中为 validateBody 函数)。

let mailboxItem;

Office.initialize = function (reason) {
    mailboxItem = Office.context.mailbox.item;
}

// Entry point for Contoso Message Body Checker add-in before send is allowed.
// <param name="event">ItemSend event is automatically passed by on-send code to the function specified in the manifest.</param>
function validateBody(event) {
    mailboxItem.body.getAsync("html", { asyncContext: event }, checkBodyOnlyOnSendCallBack);
}

函数 validateBody 以指定格式 (HTML) 获取当前正文,并传递 ItemSend 代码希望在回调函数中访问的事件对象。 除 getAsync 方法之外,Body 对象还提供了 setAsync 方法,可用于将正文替换为指定的文本。

注意

有关详细信息,请参阅 Event 对象Body.getAsync

NotificationMessages 对象和 event.completed 方法

checkBodyOnlyOnSendCallBack 函数使用正则表达式来确定邮件正文是否包含禁止使用的词语。 如果该函数发现受限词语数组的匹配项,则将阻止发送电子邮件,并通过信息栏通知发件人。 为此,它使用 notificationMessages 对象的 属性 Item 返回 NotificationMessages 对象。 然后,通过调用 addAsync 方法向该项目添加通知,如以下示例所示。

// Determine whether the body contains a specific set of blocked words. If it contains the blocked words, block email from being sent. Otherwise allow sending.
// <param name="asyncResult">ItemSend event passed from the calling function.</param>
function checkBodyOnlyOnSendCallBack(asyncResult) {
    const listOfBlockedWords = new Array("blockedword", "blockedword1", "blockedword2");
    const wordExpression = listOfBlockedWords.join('|');

    // \b to perform a "whole words only" search using a regular expression in the form of \bword\b.
    // i to perform case-insensitive search.
    const regexCheck = new RegExp('\\b(' + wordExpression + ')\\b', 'i');
    const checkBody = regexCheck.test(asyncResult.value);

    if (checkBody) {
        mailboxItem.notificationMessages.addAsync('NoSend', { type: 'errorMessage', message: 'Blocked words have been found in the body of this email. Please remove them.' });
        // Block send.
        asyncResult.asyncContext.completed({ allowEvent: false });
    }

    // Allow send.
    asyncResult.asyncContext.completed({ allowEvent: true });
}

下面是 方法的参数 addAsync

  • NoSend – 一个字符串,它是开发人员指定的用于引用通知消息的键。 可用于在以后修改此邮件。 密钥长度不能超过 32 个字符。
  • type – JSON 对象参数的属性之一。 表示邮件的类型;类型对应于 Office.MailboxEnums.ItemNotificationMessageType 枚举的值。 可能的值是进度指示器、信息消息或错误消息。 在此示例中,type 是错误消息。
  • message – JSON 对象参数的属性之一。 在此示例中,message 是通知邮件的文本。

若要指示加载项已完成处理 ItemSend 由发送操作触发的事件,请调用 event.completed ({allowEvent:Boolean}) 方法。 allowEvent 属性是布尔值。 如果设置为 true,则允许发送。 如果设置为 false,则将阻止发送电子邮件。

replaceAsyncremoveAsyncgetAllAsync 方法

除了 addAsync 方法之外,NotificationMessages 对象还包括 replaceAsyncremoveAsyncgetAllAsync 方法。 此代码示例中不使用这些方法。 有关详细信息,请参阅 NotificationMessages

主题和抄送检查器代码

以下代码示例介绍如何将收件人添加到抄送行,并验证邮件在发送时是否包含主题。 此示例使用 Onsend 功能允许或禁止发送电子邮件。

// Invoke by Contoso Subject and CC Checker add-in before send is allowed.
// <param name="event">ItemSend event is automatically passed by on-send code to the function specified in the manifest.</param>
function validateSubjectAndCC(event) {
    shouldChangeSubjectOnSend(event);
}

// Determine whether the subject should be changed. If it is already changed, allow send. Otherwise change it.
// <param name="event">ItemSend event passed from the calling function.</param>
function shouldChangeSubjectOnSend(event) {
    mailboxItem.subject.getAsync(
        { asyncContext: event },
        function (asyncResult) {
            addCCOnSend(asyncResult.asyncContext);
            //console.log(asyncResult.value);
            // Match string.
            const checkSubject = (new RegExp(/\[Checked\]/)).test(asyncResult.value)
            // Add [Checked]: to subject line.
            subject = '[Checked]: ' + asyncResult.value;

            // Determine whether a string is blank, null, or undefined.
            // If yes, block send and display information bar to notify sender to add a subject.
            if (asyncResult.value === null || (/^\s*$/).test(asyncResult.value)) {
                mailboxItem.notificationMessages.addAsync('NoSend', { type: 'errorMessage', message: 'Please enter a subject for this email.' });
                asyncResult.asyncContext.completed({ allowEvent: false });
            }
            else {
                // If can't find a [Checked]: string match in subject, call subjectOnSendChange function.
                if (!checkSubject) {
                    subjectOnSendChange(subject, asyncResult.asyncContext);
                    //console.log(checkSubject);
                }
                else {
                    // Allow send.
                    asyncResult.asyncContext.completed({ allowEvent: true });
                }
            }
        });
}

// Add a CC to the email. In this example, CC contoso@contoso.onmicrosoft.com
// <param name="event">ItemSend event passed from calling function</param>
function addCCOnSend(event) {
    mailboxItem.cc.setAsync(['Contoso@contoso.onmicrosoft.com'], { asyncContext: event });
}

// Determine whether the subject should be changed. If it is already changed, allow send, otherwise change it.
// <param name="subject">Subject to set.</param>
// <param name="event">ItemSend event passed from the calling function.</param>
function subjectOnSendChange(subject, event) {
    mailboxItem.subject.setAsync(
        subject,
        { asyncContext: event },
        function (asyncResult) {
            if (asyncResult.status == Office.AsyncResultStatus.Failed) {
                mailboxItem.notificationMessages.addAsync('NoSend', { type: 'errorMessage', message: 'Unable to set the subject.' });

                // Block send.
                asyncResult.asyncContext.completed({ allowEvent: false });
            }
            else {
                // Allow send.
                asyncResult.asyncContext.completed({ allowEvent: true });
            }
        });
}

若要详细了解如何将收件人添加到抄送行、验证电子邮件在发送时是否包主题行,以及查看可以使用的 API,请参阅 Outlook-Add-in-On-Send 示例。 已充分注释代码。

调试使用 on-send 的 Outlook 加载项

有关如何调试 on-send 加载项的说明,请参阅 在 Outlook 外接程序中调试函数命令

提示

如果在用户运行加载项且动态定义加载项的事件处理程序时出现错误“回调函数无法访问”,则必须创建存根函数作为解决方法。 有关详细信息 ,请参阅动态定义事件处理程序

另请参阅