使用 Compose 操作扩展 Compose 界面

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

除了在用户阅读 Gmail 邮件时提供基于卡片的界面之外, Google Workspace 扩展 Gmail 的插件还可以在用户撰写新邮件或回复现有邮件时提供其他界面。这样, Google Workspace插件就可以自动执行为用户撰写电子邮件的任务。

访问插件撰写界面

可通过两种方式查看插件的撰写界面。第一种方法是在插件已打开的情况下开始撰写新草稿或回复。第二种方法是在撰写草稿时启动该插件。

这两种情况都会引起插件执行插件清单中定义的相应 Compose 触发器函数。“组合”触发器函数为该组合操作构建组合界面,然后 Gmail 会向用户显示该界面。

构建 Compose 插件

您可以按照以下常规步骤,将插件功能添加到插件中:

  1. gmail.composeTrigger 字段添加到插件脚本项目清单中,并更新清单范围以包含 Compose 操作所需的范围。
  2. 实现一个 Compose 触发器函数,用于在触发器触发时构建 Compose 界面。Compose 触发器函数会返回单个 Card 对象或一组 Card 对象,后者用于组合 Compose 操作。
  3. 实现所需的响应函数,以响应用户的 Compose 界面互动。这些函数不是组合操作本身(这只会导致组合界面显示);它们是单独的函数,用于管理选择组合界面的不同元素时发生的情况。例如,包含按钮的界面卡片通常具有关联的回调函数,当用户点击该按钮时,系统会执行该函数。用于更新消息草稿内容的 widget 的回调函数应返回 UpdateDraftActionResponse 对象。

Compose 触发器函数

插件的撰写界面的构建方式与插件的消息界面相同,即使用 Apps 脚本的卡片服务构建卡片并为其填充微件

您必须实现您在清单中定义的 gmail.composeTrigger.selectActions[].runFunction。组合触发器函数必须返回一个 Card 对象或一组 Card 对象(构成该操作的合成界面)。这些函数与内容相关触发器函数非常相似,并且应以相同的方式构建卡片。

Compose 触发器事件对象

选择组合操作后,它会执行相应的组合触发器函数,并将事件对象作为参数传递给该函数。事件对象可包含有关插件上下文和草稿到触发器函数的信息。

如需详细了解如何在事件对象中排列信息,请参阅事件对象结构。事件对象中包含的信息在一定程度上受 gmail.composeTrigger.draftAccess 清单字段的值控制:

将内容插入有效草稿

通常情况下, Google Workspace 附加应用撰写界面会提供有助于撰写消息的用户选项和控件。对于这类使用情形,一旦用户在界面中做出选择,插件便会解读所选内容,并相应地更新当前有效的电子邮件草稿。

为了更轻松地更新当前的电子邮件草稿,卡片服务新增了以下类:

通常,插件撰写界面包含一个“保存”或“插入”微件,用户可以点击该微件以表明他们已完成在界面中做出选择,并希望将他们的选择添加到他们正在撰写的电子邮件中。如需添加此互动功能,微件应该具有关联的 Action 对象,该对象会指示插件在点击微件时运行特定的回调函数。您必须实现这些回调函数。每个回调函数都应返回一个构建的 UpdateDraftActionResponse 对象,该对象详细说明要对当前草稿电子邮件进行的更改。

示例 1

以下代码段展示了如何构建用于更新主题以及当前电子邮件草稿的收件人、抄送和密送收件人的撰写界面。

    /**
     * Compose trigger function that fires when the compose UI is
     * requested. Builds and returns a compose UI for inserting images.
     *
     * @param {event} e The compose trigger event object. Not used in
     *         this example.
     * @return {Card[]}
     */
    function getComposeUI(e) {
      return [buildComposeCard()];
    }

    /**
     * Build a card to display interactive buttons to allow the user to
     * update the subject, and To, Cc, Bcc recipients.
     *
     * @return {Card}
     */
    function buildComposeCard() {

      var card = CardService.newCardBuilder();
      var cardSection = CardService.newCardSection().setHeader('Update email');
      cardSection.addWidget(
          CardService.newTextButton()
              .setText('Update subject')
              .setOnClickAction(CardService.newAction()
                  .setFunctionName('applyUpdateSubjectAction')));
      cardSection.addWidget(
          CardService.newTextButton()
              .setText('Update To recipients')
              .setOnClickAction(CardService.newAction()
                  .setFunctionName('updateToRecipients')));
      cardSection.addWidget(
          CardService.newTextButton()
              .setText('Update Cc recipients')
              .setOnClickAction(CardService.newAction()
                  .setFunctionName('updateCcRecipients')));
      cardSection.addWidget(
          CardService.newTextButton()
              .setText('Update Bcc recipients')
              .setOnClickAction(CardService.newAction()
                  .setFunctionName('updateBccRecipients')));
      return card.addSection(cardSection).build();
    }

    /**
     * Updates the subject field of the current email when the user clicks
     * on "Update subject" in the compose UI.
     *
     * Note: This is not the compose action that builds a compose UI, but
     * rather an action taken when the user interacts with the compose UI.
     *
     * @return {UpdateDraftActionResponse}
     */
    function applyUpdateSubjectAction() {
      // Get the new subject field of the email.
      // This function is not shown in this example.
      var subject = getSubject();
      var response = CardService.newUpdateDraftActionResponseBuilder()
          .setUpdateDraftSubjectAction(CardService.newUpdateDraftSubjectAction()
              .addUpdateSubject(subject))
          .build();
      return response;
    }

    /**
     * Updates the To recipients of the current email when the user clicks
     * on "Update To recipients" in the compose UI.
     *
     * Note: This is not the compose action that builds a compose UI, but
     * rather an action taken when the user interacts with the compose UI.
     *
     * @return {UpdateDraftActionResponse}
     */
    function applyUpdateToRecipientsAction() {
      // Get the new To recipients of the email.
      // This function is not shown in this example.
      var toRecipients = getToRecipients();
      var response = CardService.newUpdateDraftActionResponseBuilder()
          .setUpdateDraftToRecipientsAction(CardService.newUpdateDraftToRecipientsAction()
              .addUpdateToRecipients(toRecipients))
          .build();
      return response;
    }

    /**
     * Updates the Cc recipients  of the current email when the user clicks
     * on "Update Cc recipients" in the compose UI.
     *
     * Note: This is not the compose action that builds a compose UI, but
     * rather an action taken when the user interacts with the compose UI.
     *
     * @return {UpdateDraftActionResponse}
     */
    function applyUpdateCcRecipientsAction() {
      // Get the new Cc recipients of the email.
      // This function is not shown in this example.
      var ccRecipients = getCcRecipients();
      var response = CardService.newUpdateDraftActionResponseBuilder()
          .setUpdateDraftCcRecipientsAction(CardService.newUpdateDraftCcRecipientsAction()
              .addUpdateToRecipients(ccRecipients))
          .build();
      return response;
    }

    /**
     * Updates the Bcc recipients  of the current email when the user clicks
     * on "Update Bcc recipients" in the compose UI.
     *
     * Note: This is not the compose action that builds a compose UI, but
     * rather an action taken when the user interacts with the compose UI.
     *
     * @return {UpdateDraftActionResponse}
     */
    function applyUpdateBccRecipientsAction() {
      // Get the new Bcc recipients of the email.
      // This function is not shown in this example.
      var bccRecipients = getBccRecipients();
      var response = CardService.newUpdateDraftActionResponseBuilder()
          .setUpdateDraftBccRecipientsAction(CardService.newUpdateDraftBccRecipientsAction()
              .addUpdateToRecipients(bccRecipients))
          .build();
      return response;
    }

示例 2

以下代码段展示了如何构建一个 Compose 界面,以便将图片插入当前的电子邮件草稿。

    /**
     * Compose trigger function that fires when the compose UI is
     * requested. Builds and returns a compose UI for inserting images.
     *
     * @param {event} e The compose trigger event object. Not used in
     *         this example.
     * @return {Card[]}
     */
    function getInsertImageComposeUI(e) {
      return [buildImageComposeCard()];
    }

    /**
     * Build a card to display images from a third-party source.
     *
     * @return {Card}
     */
    function buildImageComposeCard() {
      // Get a short list of image URLs to display in the UI.
      // This function is not shown in this example.
      var imageUrls = getImageUrls();

      var card = CardService.newCardBuilder();
      var cardSection = CardService.newCardSection().setHeader('My Images');
      for (var i = 0; i < imageUrls.length; i++) {
        var imageUrl = imageUrls[i];
        cardSection.addWidget(
            CardService.newImage()
                .setImageUrl(imageUrl)
                .setOnClickAction(CardService.newAction()
                      .setFunctionName('applyInsertImageAction')
                      .setParameters({'url' : imageUrl})));
      }
      return card.addSection(cardSection).build();
    }

    /**
     * Adds an image to the current draft email when the image is clicked
     * in the compose UI. The image is inserted at the current cursor
     * location. If any content of the email draft is currently selected,
     * it is deleted and replaced with the image.
     *
     * Note: This is not the compose action that builds a compose UI, but
     * rather an action taken when the user interacts with the compose UI.
     *
     * @param {event} e The incoming event object.
     * @return {UpdateDraftActionResponse}
     */
    function applyInsertImageAction(e) {
      var imageUrl = e.parameters.url;
      var imageHtmlContent = '<img style=\"display: block\" src=\"'
           + imageUrl + '\"/>';
      var response = CardService.newUpdateDraftActionResponseBuilder()
          .setUpdateDraftBodyAction(CardService.newUpdateDraftBodyAction()
              .addUpdateContent(
                  imageHtmlContent,
                  CardService.ContentType.MUTABLE_HTML)
              .setUpdateType(
                  CardService.UpdateDraftBodyType.IN_PLACE_INSERT))
          .build();
      return response;
    }