こんにちは。フロントエンドエンジニアの松岡です。

外部サービスとの連携のために Slack ワークフローのフォーム入力内容をメールで送信したいなーと思うことがありました。Slack ワークフローをトリガーにしたメール送信は Zapier などのツールを使えば実現できるようですが、社内で GAS(Google Apps Script) を使った自動化処理がいくつかあったので、同じように Slack&GAS の連携で作ることにしました。当記事ではその手順を紹介します。

フロー

おおまかな手順は以下の通りです。

  • Slack ワークフローを作成 ※
  • GAS のスクリプトを作成
  • Slack Outgoing WebHook を設定
  • Slack Incoming WebHook を設定

※ 記事執筆時点では有料プランのみワークフローの機能を利用できます。Slack 料金プラン

完成イメージ

Slack ワークフローのフォームを送信する。

フォームの入力内容がチャンネルに投稿される。

スプレッドシートにログが書き込まれる。

メールが送信される。

完了メッセージが投稿される。

Slack ワークフローを作成

メール送信内容を入力するためのワークフローを作成します。

  1. ワークフロービルダー でワークフローを新規作成します。
  2. 開始する方法は任意ですがここでは ショートカット にします。
  3. 最初のステップで フォームを送信する を選択します。
  4. メッセージ送信 のステップを追加します。

追加したワークフローは以下のようになります。右上の「公開する」ボタンで公開します。

この設定により、ワークフローのフォームを送信すると SlackToMail というプレフィクスに続き タイトル::値,, というフォーマットでフォームに入力した項目がチャンネルに投稿されます。

SlackToMail,,title::{@可変テキスト},,body::{@可変テキスト},,requester::{@可変ユーザー}

GAS のスクリプトを作成

Google Apps Script を使うと、API リクエストのエンドポイントを作成できます。ここではフォームの入力内容を受け取るエンドポイントを作成します。

  1. Google ドライブを開いて Google Apps Script を追加します。
  2. 編集エディター が開きます。
  3. プロジェクト名を 変更 します。
  4. デフォルトのコードを消して スクリプト を貼り付けます。
  5. Google Drive に任意のスプレッドシートを作成して ファイルを識別する ID とシート名 をコピーします。
  6. GAS の config に貼り付けます。
  7. GAS の config を実際のメールアドレスに置き換えます。送信元はスクリプト所有者の Google アカウントにする必要があります。

作成したプロジェクトは後から プロジェクト一覧 で検索できます。

スクリプトのコードの説明

冒頭の configs は設定値を宣言しています。★マークのついた部分は環境に合わせて変更する必要があります。

const configs = {
  slackMessageTrigger: "slackToMail",
  slackAcceptedMessage: "受け付けました",
  slackIncomingWebhookUrl: "",    // ★
  spreadSheetFileId: "",          // ★
  spreadSheetSheetName: "シート1", // ★
  mailTo: "to@example.co.jp",     // ★
  mailFrom: "from@example.co.jp", // ★
  mailSubjectPrefix: "【テスト】",
};

emailSectionMap はフォームの項目とメール本文の見出し部分のマッピングです。フォームに新しい項目を追加した時はここに ["{キー}", "{ラベル}"] を追加するとメール本文に記載されます。

const emailSectionMap = [
  ["title", "タイトル"],
  ["body", "本文"],
  ...
];

doPost は GAS のエンドポイントが POST メソッドでリクエストされた時に実行される固定の関数です。 引数 e でリクエスト内容を受け取ります。

function doPost(e) {
  ...
  return ContentService.createTextOutput("処理が完了しました");
}

convertPostMessageToPayload は Slack から受け取った文字列をパースします。フォーマットは token=xx&channel_id=xx&text=SlackToMail,,title::yy,,body::yy,,requester::yy のようにアンパサンドで合成された文字列です。 text= の部分にワークフローがチャンネルに投稿した文字列が入ります。

function convertPostMessageToPayload(postMessage) {
  const textField = postMessage
    .split("&")
    .map(v => v.split("="))
    .find(v => v[0] === "text")
  ;
  ...
}

writeSpreadSheet はスプレッドシートにログを書き込みます。

function writeSpreadSheet(spreadSheetFileId, spreadSheetName, payload) {
  const sheet = SpreadsheetApp
    .openById(spreadSheetFileId)
    .getSheetByName(spreadSheetName)
  ;
  ...
  sheet.getRange(1, 1, 1, values.length).setValues([values]);
}

sendEmail はメール送信を実行します。

function sendEmail(mailTo, mailFrom, mailSubjectPrefix, payload) {
  const subject = `${mailSubjectPrefix}${payload.title}`;
  ...

  GmailApp.sendEmail(mailTo, subject, body, options);
}

sendToSlackAcceptedMessage は後述する Incoming WebHooks のエンドポイントをリクエストして Slack に完了のメッセージを投稿します。

function sendToSlackAcceptedMessage(url, message) {
  ...

  const options = {
    method: "post",
    contentType: "application/json",
    payload,
  };

  UrlFetchApp.fetch(url, options);
}

編集後のエディターは以下のようになります。

デプロイ

  1. スクリプトを保存して 新しいデプロイ を実行します。
  2. ウェブアプリとして デプロイ します。
  3. スプレッドシートなど GAS から外部にアクセスするための 認証 が表示されるので許可します。

デプロイが完了するとエンドポイントの URL が発行されます。

Slack Outgoing WebHooks を設定

Outgoing WebHooks を使うと、Slack で任意のキーワードが投稿されたタイミングで任意のエンドポイントをリクエストできます。この仕組みを使って SlackToMail というキーワードが投稿された時に GAS のエンドポイントをリクエストするように設定します。

  1. Slack - ワークスペース名のメニューから アプリを管理する を呼び出します。
  2. Slack - カスタムインテグレーションで Outgoing Webhook を選択します。アプリをインストールしていない場合は検索します。
  3. Slack - Slack に追加 ボタンで設定の新規追加ができます。追加した設定は後から「設定」タブで検索できます。
  4. GAS - デプロイ > デプロイを管理を開いて エンドポイントの URL をコピーします。
  5. Slack - 追加した Outgoing Webhook の設定画面で URL の欄 に貼り付けます。
  6. Slack - ワークフローを開始したチャンネルで SlackToMail というキーワードに反応するよう 設定 します。
  7. Slack - ページ下に 設定を保存する ボタンがあるので忘れずに保存しましょう。

フォーム送信テスト

ここまでの手順で Slack ワークフローのフォームを送信するとメールが送信されるようになります。ワークフロー を呼び出してフォームを送信してみましょう。

Slack のチャンネルに文字列が投稿されます。

スプレッドシートにログが書き込まれます。列 B の値は Slack から GAS に送信された文字列をデバッグ用に書き込んだものです。

スクリプトの configs > mailTo に設定した宛先にメールが送信されます。

Slack Incoming WebHooks を設定

Incoming WebHooks を使うと、任意の文字列を Slack チャンネルに投稿できます。この仕組みを使ってメール送信完了のメッセージを投稿するように設定します。

  1. Slack - ワークスペース名のメニューから アプリを管理する を呼び出します。
  2. Slack - カスタムインテグレーションで Incoming Webhook を選択します。アプリをインストールしていない場合は検索します。
  3. Slack - Slack に追加 ボタンで設定の新規追加ができます。追加した設定は後から「設定」タブで検索できます。
  4. Slack - 追加した Incoming Webhook の設定画面で投稿するチャンネルを入力し 保存 します。
  5. Slack - 発行された URL をコピーします。
  6. GAS - config に貼り付けます。
  7. GAS - スクリプトを保存して 新しいデプロイ を実行します。

config に設定した Incoming Webhook のエンドポイントは、GAS によってメール送信後にリクエストされます。

フォーム送信テスト

ワークフローを呼び出してフォームを送信してみましょう。

おや、設定したはずの Incoming Webhook から完了のメッセージが返ってきませんね。

GAS ではデプロイごとに新しい URL が発行されます。デプロイごとにエンドポイントが与えられるため Outgoing Webhook で設定した URL を最新リビジョンのものに置き換える必要があります。

  1. GAS - デプロイ > デプロイを管理を開いて最新リビジョンの URL をコピーします。
  2. Outgoing Webhook の設定の URL に貼り付けます。

もういちどワークフローのフォームを送信してみましょう。

今度は完了のメッセージが返ってきました!

おわりに

Slack の投稿が文字列むきだしでやや不細工ですが、よければコピペ・加工してお使いください。 社内でもいろいろ加工して使ってみようと思います。