メール作成用 UI を作成アクションで拡張する

Gmail のメッセージを読んでいるときにカードベースのインターフェースを提供するだけでなく、Gmail を拡張する Google Workspace アドオンでは、ユーザーが新しいメッセージを作成したり、既存のメッセージに返信したりするときに別のインターフェースを提供できます。これにより、アドオンはユーザーのメール作成タスクを自動化できます。

Google Workspace アドオンの作成 UI にアクセスする

アドオンのコンポーザ UI を表示する方法は 2 つあります。1 つ目の方法は、アドオンが開いている状態で新しい下書きの作成または返信を開始することです。2 つ目の方法は、下書きの作成中にアドオンを起動する方法です。

いずれの場合も、アドオンは、アドオンのマニフェストで定義されている対応するコンポーズ トリガー関数を実行します。コンポーズ トリガー関数は、そのコンポーズ アクションのコンポーズ UI を構築します。この UI は Gmail によってユーザーに表示されます。

作成アドオンを構築する

アドオンに作成機能を追加する一般的な手順は次のとおりです。

  1. アドオン スクリプト プロジェクトのマニフェストgmail.composeTrigger フィールドを追加し、マニフェストのスコープを更新して、作成アクションに必要なスコープを含めます。
  2. トリガーが起動したときに Compose UI をビルドする Compose トリガー関数を実装します。Compose トリガー関数は、単一の Card オブジェクト、または Compose アクションの Compose UI を形成する Card オブジェクトの配列を返します。
  3. ユーザーの Compose UI 操作に応答するために必要な関連するコールバック関数を実装します。これらの関数は、作成アクション自体(作成 UI の表示のみを引き起こす)ではありません。作成 UI のさまざまな要素が選択されたときに何が起こるかを制御する個々の関数です。たとえば、ボタンを含む UI カードには、通常、ユーザーがそのボタンをクリックしたときに実行されるコールバック関数が関連付けられています。下書きメッセージのコンテンツを更新するウィジェットのコールバック関数は、UpdateDraftActionResponse オブジェクトを返す必要があります。

トリガー関数を構成する

アドオンの作成 UI は、アドオンのメッセージ UI と同じ方法で構築されます。Apps Script の カードサービスを使用してカードを構築し、ウィジェットを配置します。

マニフェストで定義した gmail.composeTrigger.selectActions[].runFunction を実装する必要があります。コンポーズ トリガー関数は、単一の Card オブジェクトか、そのアクションのコンポーズ UI を形成する Card オブジェクトの配列のいずれかを返す必要があります。これらの関数はコンテキスト トリガー関数と非常によく似ており、同じ方法でカードをビルドする必要があります。

トリガー イベント オブジェクトを構成する

作成アクションが選択されると、対応する作成トリガー関数が実行され、イベント オブジェクトがパラメータとして関数に渡されます。イベント オブジェクトは、アドオンのコンテキストと作成中の下書きに関する情報をトリガー関数に渡すことができます。

イベント オブジェクトでの情報の配置方法について詳しくは、イベント オブジェクトの構造をご覧ください。イベント オブジェクトに含まれる情報は、gmail.composeTrigger.draftAccess マニフェスト フィールドの値によって部分的に制御されます。

  • gmail.composeTrigger.draftAccess マニフェスト フィールドが NONE であるか、含まれていない場合、イベント オブジェクトには最小限の情報しか含まれません。

  • gmail.composeTrigger.draftAccessMETADATA に設定されている場合、作成トリガー関数に渡されるイベント オブジェクトには、作成中のメールの受信者のリストが入力されます。METADATA 下書きアクセスを使用するには、アドオン マニフェストに https://www.googleapis.com/auth/gmail.addons.current.message.metadata Gmail スコープを含める必要があります。

アクティブな下書きにコンテンツを挿入する

通常、アドオンのコンポーズ UI には、メッセージの作成に役立つユーザー オプションとコントロールが用意されています。これらのユースケースでは、ユーザーが UI で選択を行うと、アドオンが選択内容を解釈し、現在の作業中のメールの下書きをそれに応じて更新します。

現在のメールの下書きを簡単に更新できるように、カードサービスが次のクラスで拡張されました。

通常、アドオンの作成 UI には、ユーザーがクリックして UI での選択を完了し、選択した内容を作成中のメールに追加したいことを示す「保存」または「挿入」ウィジェットが含まれています。このインタラクティビティを追加するには、ウィジェットに Action オブジェクトを関連付ける必要があります。このオブジェクトは、ウィジェットがクリックされたときに特定コールバック関数を実行するようアドオンに指示します。これらのコールバック関数を実装する必要があります。各コールバック関数は、現在のメールの下書きに加える変更の詳細を示す UpdateDraftActionResponse オブジェクトを返す必要があります。

例 1

次のコード スニペットは、現在のメールの下書きの件名、宛先、Cc、Bcc の受信者を更新する Compose UI を構築する方法を示しています。

/**
 * 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 UI を作成する方法を示しています。

/**
 * 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;
}