freeeに関係ない話題ですが、Google Apps Script(以下GAS)でできる効率化の例として番外編としてfreee API以外のGASでの活用に関しても記事にしています。
今回は、「Gmailでスターを付けたメールの受信をSlackに通知する」に挑戦したいと思います。
前回の記事では、Todoist APIでタスクを新たに作成するスクリプトを作成しました。
Incoming Webhooksを利用してシンプルにSlack通知する
公式ドキュメントを確認すると、Slack APIは多機能で色々なことができます。ただ今回は、受信メールから抜粋した情報(テキスト)をシンプルに指定のチャンネルに投稿できるだけでOKです。
こうした指定チャンネルへのシンプルなテキストの投稿には、Incoming Webhooksを使うと便利です。
Incoming Webhookは指定したURLに定められた形式のJSON文字列をPOSTするとSlack側がそれを解釈して、URLに紐付けられたチャンネルに投稿してくれる機能です。
Incoming Webhooksを利用するための流れは以下の通りです。
- アプリの作成
- 権限スコープを設定する
- ワークスペースへのアプリのインストール
- Incoming Webhooksを利用する
これらの詳細は、Slackのビギナー向けのチュートリアルで確認できます。
Slackアプリの作成
まず、ワークスペースにログインした状態で、https://api.slack.com/ にアクセスしてCreate an appをクリックします。

続いて、アプリ名前を決め、使用するワークスペースを選択します。

Create Appをクリックすると以下の画面が出てきます。アプリの設定をどのような方法で行うか?という選択画面ですが、From an app manifestはまだBETAということで、From scratchを選択します。

権限スコープの設定
アプリを作成するとBasic Informationの画面に遷移します。まずアプリに許可する操作権限のスコープ(範囲)を設定する必要がありますので、Add features and functionalityの欄のPermissionsをクリックします。

続いてScopesの欄で、作成したアプリの権限を設定します。今回はincoming webhookのみを追加します。

Botの表示名を設定する
作成したアプリを自分のワークスペースにインストールするには、Bot Nameを設定する必要があります。Basic Informationに戻り、Add features and functionalityの欄のBotsをクリックします。

Your App’s Presence in Slackの欄のApp Display Nameの右側のEditをクリックします。

アプリの表示名とユーザー名を設定しましょう。

Incoming WebhookのURLを発行する
続いて、投稿内容をPOSTする先のIncoming WebhookのURLを発行します。
Basic Informationに戻り、Add features and functionalityの欄のIncoming Webhooksをクリックします。

Incoming Webhooksが有効化されていることを右上のスイッチボタンで確認の上、Add New Webhook to Workspaceをクリックします。

するとワークスペースへのアクセス許可を求められる画面に遷移します。

ここで投稿したいチャンネルを指定して許可します。

これで指定したチャンネルに紐付けられたIncoming WebhookのURLが発行されました。このURLをGASのスクリプトで使用するので、控えておきます。
サンプルリクエストを送ってみる
公式ドキュメントのチュートリアルを確認し、サンプルリクエストを送信します。

ごくシンプルなJSON文字列ですね。これをGASに読み替えて実行します。
function testPost2Slack() {
const postText = 'Hello, world.';
const webhookUrl = '指定チャンネルのWebhook URL';
const params = {
method: 'post',
contentType: 'application/json',
payload: JSON.stringify({ text: postText }) // JSON形式の文字列に変換
};
UrlFetchApp.fetch(webhookUrl, params);
}

無事POSTが成功しSlackの指定チャンネルにアプリが投稿できました。
おまけ:アプリのアイコンを設定しよう
botユーザーのアイコンが、デフォルトのままだとちょっとさみしいので、Basic Informationに戻ってアイコンも設定します。下部にDisplay Informationという欄があり、ここでアイコンを設定することができます。

スター付きメールからSlackに通知する
いよいよフィナーレです。先程のtestPost2Slack()関数をアレンジして、引数に投稿したい文字列とwebhook URLを渡すとSlack投稿してくれるpostText2Slack_(postText, webhookUrl)関数を作成します。
function postText2Slack_(postText, webhookUrl) {
const params = {
method: 'post',
contentType: 'application/json',
payload: JSON.stringify({ text: postText }) // JSON形式の文字列に変換
};
UrlFetchApp.fetch(webhookUrl, params);
}
前回の記事で紹介しいたスター付きメールからTodoistタスクを作成するnewStarredMails2Task()関数の新着メール配列の要素に対するループ処理内にSlackに投稿する処理を追加します。
function starredMails2TaskSlack() {
// Gmailの検索演算子:1日以内に受信したスター付きのメール
const query = 'is:starred newer_than:1d';
// 検索演算子の条件に該当するメールが含まれるスレッドのすべてのメールを取得
const aryAllMessages = new GmailSearch(query).allMessages;
// 取得すべきメッセージがなければ処理を中止
if (aryAllMessages.length === 0) { return };
// isStarred()メソッドでスター付きのメールのみに絞り込み
const aryStarredMessages = aryAllMessages.filter(message => message.isStarred());
// プロパティストアからメール絞り込みの起算日時を取得
const dateLastMail = new Date(PropertiesService.getScriptProperties().getProperty('LAST_DATE_STAR'));
// 起算日時以降のメールのみに絞り込み
const aryNewMessage = aryStarredMessages.filter(message => message.getDate() > dateLastMail);
// 取得すべきメッセージがなければ処理を中止
if (aryNewMessage.length === 0) { return };
// GmailMessageクラスのメソッドを利用してメールから必要な情報を取得してTodoistでタスク作成&Slackに通知
aryNewMessage.forEach(messageNew => {
const subject = messageNew.getSubject();
const plainBody = messageNew.getPlainBody();
const sender = messageNew.getFrom();
const dateMail = messageNew.getDate();
const tomorrowAM1000 = new Date(dateMail.getFullYear(), dateMail.getMonth(), dateMail.getDate() + 1, 10, 0, 0); // 翌日のAM10:00のDateオブジェクト
const rfc3339TomorrowAM1000 = Utilities.formatDate(tomorrowAM1000, 'UTC', "yyyy-MM-dd'T'HH:mm:ssXXX"); // RFC3339形式(タイムゾーン:UTC)の文字列に変換
const payload = {
content: sender + '|' + subject,
description: plainBody,
project_id: getProjectIdByName_('Inbox'),
due_datetime: rfc3339TomorrowAM1000
};
createTodoistTask_(payload); // Todoistに新しいタスクを作成
const postText = sender + '|' + subject + '\n\n' + plainBody; // Slackへの投稿テキスト
const webhookUrl = PropertiesService.getScriptProperties().getProperty('SLACK_CHANNEL'); // 投稿先チャンネルのWebhookURLはプロパティストアに格納
postText2Slack_(postText, webhookUrl); // Slackの指定チャンネルに投稿
Utilities.sleep(300); // APIへの負荷軽減のためスリープ処理を追加
});
// 起算日時以降のメールを日付で降順に並び替え
aryNewMessage.sort((a, b) => b.getDate() - a.getDate());
// 最新のメールから受信日時を取得してプロパティストアに次回の起算日時として保存
const messageLast = aryNewMessage[0];
const dateLast = messageLast.getDate();
PropertiesService.getScriptProperties().setProperty('LAST_DATE_STAR', dateLast);
}
この部分ですね。
投稿内容は、送信者|件名 + 改行x2 + メール本文 としました。webhook URLはプロパティストアに格納しています。
const postText = sender + '|' + subject + '\n\n' + plainBody;
const webhookUrl = PropertiesService.getScriptProperties().getProperty('SLACK_CHANNEL');
postText2Slack_(postText, webhookUrl);
トリガー実行
最後に、あらためてstarredMails2TaskSlack()関数をトリガー による定期実行を設定します。15分おきや1時間おきなど、業務の都合に合わせて設定しましょう。
おわりに
今回は、「Incoming Webhooksを使ってSlackに通知する」を紹介しました。これで、連載のゴールである「Gmailのスター付きメールからTodoistのタスクを作成&Slackに通知する」が完成しました。
Incoming WebhooksはSlack APIの機能のなかでも認証などが必要なく、ライトに使えるのでシンプルに通知したいだけといった今回のようなケースにはとても便利ですね。
さて全4回にわたってご紹介した「Gmailのスター付きメールからTodoistのタスクを作成&Slackに通知する」スクリプトの作り方、いかがだったでしょうか。
もし実際に活用された方がいらっしゃったらTwitterなどで感想いただけると嬉しいです。
シリーズ目次
- Gmailのスター付きメールからTodoistのタスクを作成&Slackに通知する その1 – isStarred()メソッドを使って、未処理のスター付きメールのみを絞り込む
- Gmailのスター付きメールからTodoistのタスクを作成&Slackに通知する その2 – Todoist APIの認証を通す
- Gmailのスター付きメールからTodoistのタスクを作成&Slackに通知する その3 – Todoist APIでタスクを新たに作成する
- Gmailのスター付きメールからTodoistのタスクを作成&Slackに通知する その4 – Incoming Webhooksを使ってSlackに通知
Google Apps Scriptを勉強したい方へ
この記事を見て、GASを勉強したいなと思われた方はぜひノンプログラマーのためのスキルアップ研究会(通称 ノンプロ研)にご参加ください。私も未経験からこの学習コミュニティに参加し、講座を受講したことでGASが書けるようになりました。
学習コミュニティ「ノンプログラマーのためのスキルアップ研究会」
挫折しがちなプログラミングの学習も、コミュニティの力で継続できます。ノンプロ研でお待ちしております!