在发送邮件之前自动检查附件
再也不会错过将重要文档或照片附加到邮件中。 使用基于事件的加载项时,邮件在发送前会自动检查附件,以便你可以放心地始终发送完整版本。
以下部分介绍如何开发实现 智能警报 来处理事件的 OnMessageSend
基于事件的外接程序。 在本演练结束时,加载项将自动检查邮件中提及的附加文档或图片,并在发送邮件之前提醒你是否缺少该文档或图片。
注意
OnMessageSend
和 OnAppointmentSend
事件在要求集 1.12 中引入。 其他功能和自定义选项也添加到了后续的要求集。 若要验证 Outlook 客户端是否支持这些事件和功能,请参阅 支持的客户端和平台 以及描述要实现的功能的特定部分。
设置环境
在开始演练之前,请验证 Outlook 客户端是否支持智能警报功能。 有关指导,请参阅 支持的客户端和平台。
然后,完成 Outlook 快速入门,该快速入门使用 Office 加载项的 Yeoman 生成器创建加载项项目。
配置清单
若要配置清单,请选择要使用的清单类型的选项卡。
打开 manifest.json 文件。
将以下 对象添加到“extensions.runtimes”数组。 关于此标记,请注意以下几点:
- 邮箱要求集的“minVersion”设置为“1.12”,因为 支持的事件表 指定这是支持该
OnMessageSend
事件的要求集的最低版本。 - 运行时的“id”设置为描述性名称“autorun_runtime”。
- “code”属性具有设置为 HTML 文件的子“page”属性,以及设置为 JavaScript 文件的子“script”属性。 稍后的步骤将创建或编辑这些文件。 Office 使用这些值之一或另一个值,具体取决于平台。
- 经典 Outlook on Windows 在仅限 JavaScript 的运行时中执行事件处理程序,该运行时直接加载 JavaScript 文件。
- Outlook 网页版、Mac 和 Windows 上的新 Outlook 在浏览器运行时中执行处理程序,这将加载 HTML 文件。 该文件又包含一个
<script>
用于加载 JavaScript 文件的标记。 有关详细信息,请参阅 Office 外接程序中的运行时。
- “lifetime”属性设置为“short”,这意味着运行时在触发事件时启动,并在处理程序完成时关闭。 (在某些情况下,运行时在处理程序完成之前关闭。请参阅 Office Add-ins.) 中的运行时
- 有一个操作可运行
OnMessageSend
事件的处理程序。 你将在后面的步骤中创建处理程序函数。
{ "requirements": { "capabilities": [ { "name": "Mailbox", "minVersion": "1.14" } ] }, "id": "autorun_runtime", "type": "general", "code": { "page": "https://localhost:3000/commands.html", "script": "https://localhost:3000/launchevent.js" }, "lifetime": "short", "actions": [ { "id": "onMessageSendHandler", "type": "executeFunction", "displayName": "onMessageSendHandler" } ] }
- 邮箱要求集的“minVersion”设置为“1.12”,因为 支持的事件表 指定这是支持该
将以下“autoRunEvents”数组添加为“extensions”数组中的 对象的属性。
"autoRunEvents": [ ]
将以下 对象添加到“autoRunEvents”数组。 关于此代码,请注意以下几点:
- 事件对象使用事件的统一清单名称“messageSending”将处理程序函数
OnMessageSend
分配给事件 (,如 支持的事件表) 中所述。 “actionId”中提供的函数名称必须与前面步骤中“actions”数组中对象的“id”属性中使用的名称匹配。 - “sendMode”选项设置为“softBlock”。 这意味着,如果消息不符合加载项设置的发送条件,则用户必须先执行操作,然后才能发送邮件。 但是,如果加载项在发送时不可用,则会发送该项目。
{ "requirements": { "capabilities": [ { "name": "Mailbox", "minVersion": "1.12" } ], "scopes": [ "mail" ] }, "events": [ { "type": "messageSending", "actionId": "onMessageSendHandler", "options": { "sendMode": "softBlock" } } ] }
- 事件对象使用事件的统一清单名称“messageSending”将处理程序函数
提示
- 有关和
OnAppointmentSend
事件的可用OnMessageSend
发送模式选项的列表,请参阅可用的发送模式选项。 - 若要了解有关 Outlook 外接程序清单的详细信息,请参阅 Office 外接程序清单。
实现事件处理
必须对所选事件实现处理。
在此方案中,你将添加用于发送邮件的处理。 加载项将在消息中检查某些关键字。 如果找到这些关键字中的任何一个,它将为任何附件检查。 如果没有附件,外接程序将建议用户添加可能缺少的附件。
注意
本演练中的事件处理程序实现 errorMessageMarkdown 属性。 此属性目前以 Outlook 网页版 和 Windows (新) 和经典) 提供预览版。 不应在生产加载项中使用预览版功能。我们邀请你在测试或开发环境中试用此功能,并欢迎通过 GitHub 提供有关体验的反馈 (请参阅本页末尾的反馈部分) 。
若要在经典 Outlook on Windows 中测试此功能,必须安装版本 2403 (内部版本 17330.10000) 或更高版本。 然后,加入 Microsoft 365 预览体验计划 ,并在 Outlook 客户端中选择 “Beta 频道 ”选项以访问 Office beta 版本。
在同一个快速入门项目中,在 ./src 目录下创建名为 startvent 的新文件夹。
在 ./src/startvent 文件夹中,创建一个名为 launchevent.js的新文件。
在代码编辑器中打开文件 ./src/startvent/launchevent.js 并添加以下 JavaScript 代码。
/* * Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. * See LICENSE in the project root for license information. */ function onMessageSendHandler(event) { Office.context.mailbox.item.body.getAsync( "text", { asyncContext: event }, getBodyCallback ); } function getBodyCallback(asyncResult){ const event = asyncResult.asyncContext; let body = ""; if (asyncResult.status !== Office.AsyncResultStatus.Failed && asyncResult.value !== undefined) { body = asyncResult.value; } else { const message = "Failed to get body text"; console.error(message); event.completed({ allowEvent: false, errorMessage: message }); return; } const matches = hasMatches(body); if (matches) { Office.context.mailbox.item.getAttachmentsAsync( { asyncContext: event }, getAttachmentsCallback); } else { event.completed({ allowEvent: true }); } } function hasMatches(body) { if (body == null || body == "") { return false; } const arrayOfTerms = ["send", "picture", "document", "attachment"]; for (let index = 0; index < arrayOfTerms.length; index++) { const term = arrayOfTerms[index].trim(); const regex = RegExp(term, 'i'); if (regex.test(body)) { return true; } } return false; } function getAttachmentsCallback(asyncResult) { const event = asyncResult.asyncContext; if (asyncResult.value.length > 0) { for (let i = 0; i < asyncResult.value.length; i++) { if (asyncResult.value[i].isInline == false) { event.completed({ allowEvent: true }); return; } } event.completed({ allowEvent: false, errorMessage: "Looks like the body of your message includes an image or an inline file. Attach a copy to the message before sending.", // TIP: In addition to the formatted message, it's recommended to also set a // plain text message in the errorMessage property for compatibility on // older versions of Outlook clients. errorMessageMarkdown: "Looks like the body of your message includes an image or an inline file. Attach a copy to the message before sending.\n\n**Tip**: For guidance on how to attach a file, see [Attach files in Outlook](https://www.contoso.com/help/attach-files-in-outlook)." }); } else { event.completed({ allowEvent: false, errorMessage: "Looks like you're forgetting to include an attachment.", // TIP: In addition to the formatted message, it's recommended to also set a // plain text message in the errorMessage property for compatibility on // older versions of Outlook clients. errorMessageMarkdown: "Looks like you're forgetting to include an attachment.\n\n**Tip**: For guidance on how to attach a file, see [Attach files in Outlook](https://www.contoso.com/help/attach-files-in-outlook)." }); } } // 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("onMessageSendHandler", onMessageSendHandler);
重要
- 在经典 Outlook on Windows 中,导入当前在 JavaScript 文件中不受支持,可在其中实现基于事件的激活的处理。
- 为确保加载项在 发生 或 事件时
OnMessageSend
按预期运行,请在实现处理程序的 JavaScript 文件中调用Office.actions.associate
。OnAppointmentSend
这会将清单中指定的事件处理程序名称映射到其 JavaScript 对应名称。 如果此调用未包含在 JavaScript 文件中,并且清单的发送模式属性设置为 软阻止 或未指定,则会阻止用户发送消息或会议。
自定义“不发送”按钮 (可选)
如果邮件项不符合智能警报加载项的条件,则会向用户显示一个对话框,提醒他们在发送项目之前可能需要执行其他操作。 清单中指定的 发送模式选项 确定在对话框中向用户显示的选项。 无论选择哪种发送模式选项,对话框中都会出现“ 不 发送”选项。 默认情况下,选择“ 不发送” 会取消发送操作并关闭对话框。 若要为用户提供有关如何满足加载项条件的进一步指导,请自定义此按钮的文本并对其进行编程以打开任务窗格,可在其中提供其他信息和功能。
修改“不发送”按钮文本和功能
若要修改“ 不要发送 ”按钮的文本或为其分配任务窗格命令,必须在事件处理程序的 event.completed 方法中设置其他选项。
cancelLabel 选项自定义“不发送”按钮的文本。 自定义文本必须最多包含 20 个字符。
commandId 选项指定在选择“不发送”按钮时打开的任务窗格的 ID。 该值必须与外接程序清单中的任务窗格 ID 匹配。 标记取决于外接程序使用的清单类型。
-
仅外接程序清单:
id
表示任务窗格的 <Control> 元素的属性。 - Microsoft 365 的统一清单:“controls”数组中任务窗格命令的“id”属性。
-
仅外接程序清单:
contextData 选项指定要在选中“不发送”按钮时传递给外接程序的任何 JSON 数据。 如果包含此选项,还必须设置
commandId
选项。 否则,将忽略 JSON 数据。提示
若要检索选项的值,必须在任务窗格的
contextData
JavaScript 实现中调用 Office.context.mailbox.item.getInitializationContextAsync 。
导航到 ./src/startvent 文件夹,然后打开 launchevent.js。
将 getAttachmentsCallback 函数替换为以下代码。
function getAttachmentsCallback(asyncResult) { const event = asyncResult.asyncContext; if (asyncResult.value.length > 0) { for (let i = 0; i < asyncResult.value.length; i++) { if (asyncResult.value[i].isInline == false) { event.completed({ allowEvent: true }); return; } } event.completed({ allowEvent: false, errorMessage: "Looks like the body of your message includes an image or an inline file. Attach a copy to the message before sending.", // TIP: In addition to the formatted message, it's recommended to also set a // plain text message in the errorMessage property for compatibility on // older versions of Outlook clients. errorMessageMarkdown: "Looks like the body of your message includes an image or an inline file. Attach a copy to the message before sending.\n\n**Tip**: For guidance on how to attach a file, see [Attach files in Outlook](https://www.contoso.com/help/attach-files-in-outlook).", cancelLabel: "Add an attachment", commandId: "msgComposeOpenPaneButton" }); } else { event.completed({ allowEvent: false, errorMessage: "Looks like you're forgetting to include an attachment.", // TIP: In addition to the formatted message, it's recommended to also set a // plain text message in the errorMessage property for compatibility on // older versions of Outlook clients. errorMessageMarkdown: "Looks like you're forgetting to include an attachment.\n\n**Tip**: For guidance on how to attach a file, see [Attach files in Outlook](https://www.contoso.com/help/attach-files-in-outlook).", cancelLabel: "Add an attachment", commandId: "msgComposeOpenPaneButton" }); } }
保存所做的更改。
在运行时重写发送模式选项 (可选)
当希望加载项实现不同的发送模式选项时,可能会出现一种情况。 例如,你可能希望外接程序对不符合组织信息保护策略的邮件项目强制实施 阻止 选项,但仅让用户应用 提示用户 选项,以便在用户添加不正确的收件人时提供建议。
若要在运行时替代发送模式选项,必须在事件处理程序的 方法中event.completed
设置 sendModeOverride 选项。
导航到 ./src/startvent 文件夹,然后打开 launchevent.js。
将 getAttachmentsCallback 函数替换为以下代码。
function getAttachmentsCallback(asyncResult) { const event = asyncResult.asyncContext; if (asyncResult.value.length > 0) { for (let i = 0; i < asyncResult.value.length; i++) { if (asyncResult.value[i].isInline == false) { event.completed({ allowEvent: true }); return; } } event.completed({ allowEvent: false, errorMessage: "Looks like the body of your message includes an image or an inline file. Would you like to attach a copy of it to the message?", // TIP: In addition to the formatted message, it's recommended to also set a // plain text message in the errorMessage property for compatibility on // older versions of Outlook clients. errorMessageMarkdown: "Looks like the body of your message includes an image or an inline file. Would you like to attach a copy of it to the message?\n\n**Tip**: For guidance on how to attach a file, see [Attach files in Outlook](https://www.contoso.com/help/attach-files-in-outlook).", cancelLabel: "Attach a copy", commandId: "msgComposeOpenPaneButton", sendModeOverride: Office.MailboxEnums.SendModeOverride.PromptUser }); } else { event.completed({ allowEvent: false, errorMessage: "Looks like you're forgetting to include an attachment.", // TIP: In addition to the formatted message, it's recommended to also set a // plain text message in the errorMessage property for compatibility on // older versions of Outlook clients. errorMessageMarkdown: "Looks like you're forgetting to include an attachment.\n\n**Tip**: For guidance on how to attach a file, see [Attach files in Outlook](https://www.contoso.com/help/attach-files-in-outlook).", cancelLabel: "Add an attachment", commandId: "msgComposeOpenPaneButton" }); } }
保存所做的更改。
配置任务窗格 (可选)
如果在本演练中实现了自定义 “不发送 ”按钮或替代发送模式选项的可选步骤,则还需要配置任务窗格。 尽管此实现中需要任务窗格,但不需要自定义“ 不发送 ”按钮的文本或重写发送模式选项。
导航到 ./src/taskpane 文件夹,然后打开 taskpane.html。
选择整个 <正文> 节点 (包括其打开和关闭标记) ,并将其替换为以下代码。
<body class="ms-welcome ms-Fabric"> <header class="ms-welcome__header ms-bgColor-neutralLighter"> <img width="90" height="90" src="../../assets/logo-filled.png" alt="Contoso" title="Contoso" /> <h1 class="ms-font-su">Try out the Smart Alerts sample</h1> </header> <section id="sideload-msg" class="ms-welcome__main"> <h2 class="ms-font-xl">Please <a href="https://learn.microsoft.com/office/dev/add-ins/testing/test-debug-office-add-ins#sideload-an-office-add-in-for-testing">sideload</a> your add-in to see app body.</h2> </section> <main id="app-body" class="ms-welcome__main" style="display: none;"> <p> This sample implements a Smart Alerts add-in that activates when you forget to attach a document or picture that you mention in your message. To learn more, see the <a href="https://learn.microsoft.com/office/dev/add-ins/outlook/smart-alerts-onmessagesend-walkthrough">Smart Alerts walkthrough</a>. </p> <h3 class="ms-font-l">Add an attachment</h3> <p>Add the URL of a file to add it as an attachment.</p> <div class="ms-TextField"> <label class="ms-Label ms-font-l">URL of file:</label> <input id="attachment-url" class="ms-TextField-field" type="text" value="https://localhost:3000/assets/icon-128.png" placeholder=""> </div> <br/> <button class="ms-Button ms-Button--primary"> <span id="add-attachment" class="ms-Button-label">Add as attachment</span> </button> <br/> <h3 class="ms-font-l">Override the send mode option at runtime</h3> <p>Add an inline image to test overriding the send mode option at runtime.</p> <button class="ms-Button ms-Button--primary"> <span id="add-inline-image" class="ms-Button-label">Add an inline image</span> </button> </main> </body>
保存所做的更改。
在同一 个 ./src/taskpane 文件夹中,打开 taskpane.js。
将其内容替换为以下代码。
/* * Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. * See LICENSE in the project root for license information. */ Office.onReady((info) => { if (info.host === Office.HostType.Outlook) { document.getElementById("sideload-msg").style.display = "none"; document.getElementById("app-body").style.display = "flex"; document.getElementById("add-attachment").onclick = addAttachment; document.getElementById("add-inline-image").onclick = addInlineImage; } }); // Adds the specified URL as an attachment to the message. export async function addAttachment() { const attachmentUrl = document.querySelector("#attachment-url").value; Office.context.mailbox.item.addFileAttachmentAsync(attachmentUrl, getFileName(attachmentUrl), (asyncResult) => { console.log(asyncResult); }); } // Gets the file name from a URL. function getFileName(url) { const lastIndex = url.lastIndexOf("/"); if (lastIndex >= 0) { return url.substring(lastIndex + 1); } return url; } // Adds an inline image to the body of the message. export async function addInlineImage() { const mailItem = Office.context.mailbox.item; const base64String = "iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAMAAADVRocKAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAnUExURQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN0S+bUAAAAMdFJOUwAQIDBAUI+fr7/P7yEupu8AAAAJcEhZcwAADsMAAA7DAcdvqGQAAAF8SURBVGhD7dfLdoMwDEVR6Cspzf9/b20QYOthS5Zn0Z2kVdY6O2WULrFYLBaLxd5ur4mDZD14b8ogWS/dtxV+dmx9ysA2QUj9TQRWv5D7HyKwuIW9n0vc8tkpHP0W4BOg3wQ8wtlvA+PC1e8Ao8Ld7wFjQtHvAiNC2e8DdqHqKwCrUPc1gE1AfRVgEXBfB+gF0lcCWoH2tYBOYPpqQCNwfT3QF9i+AegJfN8CtAWhbwJagtS3AbIg9o2AJMh9M5C+SVGBvx6zAfmT0r+Bv8JMwP4kyFPir+cswF5KL3WLv14zAFBCLf56Tw9cparFX4upgaJUtPhrOS1QlY5W+vWTXrGgBFB/b72ev3/0igUdQPppP/nfowfKUUEFcP207y/yxKmgAYQ+PywoAFOfCH3A2MdCFzD3kdADBvq10AGG+pXQBgb7pdAEhvuF0AIc/VtoAK7+JciAs38KIuDugyAC/v4hiMCE/i7IwLRBsh68N2WQjMVisVgs9i5bln8LGScNcCrONQAAAABJRU5ErkJggg=="; // Gets the current body of the message. mailItem.body.getAsync(Office.CoercionType.Html, (bodyResult) => { if (bodyResult.status === Office.AsyncResultStatus.Failed) { console.log(bodyResult.error.message); return; } // Inserts the Base64-encoded image to the beginning of the body. const options = { isInline: true, asyncContext: bodyResult.value }; mailItem.addFileAttachmentFromBase64Async(base64String, "sample.png", options, (attachResult) => { if (attachResult.status === Office.AsyncResultStatus.Failed) { console.log(attachResult.error.message); return; } let body = attachResult.asyncContext; body = body.replace("<p class=MsoNormal>", `<p class=MsoNormal><img src="cid:sample.png">`); mailItem.body.setAsync(body, { coercionType: Office.CoercionType.Html }, (setResult) => { if (setResult.status === Office.AsyncResultStatus.Failed) { console.log(setResult.error.message); return; } console.log("Inline image added to the body."); }); }); }); }
保存所做的更改。
更新命令 HTML 文件
在 ./src/commands 文件夹中,打开 commands.html。
紧接 () 结束 头 标记
</head>
之前,为事件处理 JavaScript 代码添加脚本条目。<script type="text/javascript" src="../launchevent/launchevent.js"></script>
重要
“ 不发送 ”按钮自定义和发送模式选项替代功能目前在 Outlook on Mac 中处于预览状态。 如果要在外接程序项目中测试这些功能,则必须在 commands.html 文件中包含对 Office JavaScript API 预览版的引用。
<script type="text/javascript" src="https://appsforoffice.microsoft.com/lib/beta/hosted/office.js"></script>
<script type="text/javascript" src="../launchevent/launchevent.js"></script>
- 保存所做的更改。
更新 webpack 配置设置
打开在项目的根目录中找到的 webpack.config.js 文件,然后完成以下步骤。
plugins
在 对象中找到数组,config
并将此新对象添加到数组的开头。new CopyWebpackPlugin({ patterns: [ { from: "./src/launchevent/launchevent.js", to: "launchevent.js", }, ], }),
保存所做的更改。
试用
在项目的根目录中运行以下命令。 运行
npm start
时,如果本地 Web 服务器尚未运行) 并且加载项将被旁加载,则本地 Web 服务器将启动 (。npm run build
npm start
注意
如果加载项未自动旁加载,请按照 旁加载 Outlook 外接程序 中的说明进行测试,在 Outlook 中手动旁加载加载项。
在首选 Outlook 客户端中,创建新邮件并设置主题。 在正文中,添加一些文本。 例如,“下面是建议的徽标的图片。
发送消息. 此时会显示一个对话框,要求添加附件。 选择 “不发送 ”或 “添加附件”。 可用的选项取决于是否实现了可选步骤来自定义 “不发送 ”按钮。
默认 “不发送 ”按钮。
自定义 “添加附件 ”按钮。
注意
在版本 2410 (内部版本 18031.15000) 之前的受支持版本的经典 Windows 版 Outlook 中,如果将任务窗格分配给“ 不发送 ”按钮,关闭对话框也会打开指定的任务窗格。
向邮件添加附件。 如果实现了可选步骤来自定义“ 不发送 ”按钮,请使用任务窗格添加附件。
发送消息。 这次应该不会有警报。
如果要停止本地 Web 服务器并卸载加载项,请按照适用的说明操作:
若要停止服务器,请运行以下命令。 如果使用
npm start
了 ,则以下命令还应卸载加载项。npm stop
如果手动旁加载加载项,请参阅 删除旁加载加载项。
尝试在运行时重写发送模式选项, (可选)
如果实现了可选步骤以在运行时替代发送模式选项,请执行下列操作来试用。
在项目的根目录中运行
npm start
。 如果本地 Web 服务器尚未运行) 并旁加载加载项,则会启动本地 Web 服务器 (。注意
如果加载项未自动旁加载,请按照 旁加载 Outlook 外接程序 中的说明进行测试,在 Outlook 中手动旁加载加载项。
在首选 Outlook 客户端中,创建新邮件并设置主题。 在正文中,添加一些文本。 例如,“下面是建议的徽标的图片。
在功能区中,选择“ Contoso 外接程序>显示任务窗格”。
在任务窗格中,选择 “添加内联图像”。 图像将添加到邮件正文。
发送消息. 此时会显示一个对话框,建议将图像的副本附加到邮件。
选择“ 仍然发送” 以按原样发送邮件,或在发送邮件前选择“ 附加 副本”以包含副本。
重要
如果实现替代功能的智能警报加载项由于错误而无法完成事件处理,或者在事件发生时不可用,它将使用清单中指定的发送模式选项。