前回の内容について、具体的に説明します。
まず、スクリプトを作成します。GSuite Developer Hubを開き、新しくプロジェクトを作成します。
https://script.google.com/home
左にある「新規スクリプト」をクリックすると空のスクリプトファイル「コード.gs」が1つある「無題のプロジェクト」が開きますので、とりあえずは下記のプログラムをコピーし、貼り付けてください。
(なお、このプログラムは、JavaScriptをまともに書いたことがない人間が作成したものですので、変なところがあるはずです。改善案や問題点があれば、ぜひコメントをお寄せください!)
// Slackで得た送信用URL var postUrl = "https://hooks.slack.com/services/XXXXXXXX/XXXXXXXX/XXXXXXXXXXXXXXXX"; // メイン処理 (トリガーで定期的に呼ばれる) function gmailToSlack() { // Gmailのメールボックスの検索条件 (未読のメール・1時間以内のメール) var threads = GmailApp.search("is:unread newer_than:1h"); // 条件を満たすスレッドの数を確認 なければ終了 var count = threads.length; if (count == 0) return; // 定義ファイルの取得 var mailDataDefinitions = getDefinitionFileFromGoogleDrive(); if (mailDataDefinitions == null) return; for (var i = 0; i < count; i++) { var thread = threads[i]; // スレッド内の最後のメールが処理対象 var numberOfMessageInThread = thread.getMessages().length; var targetMessage = thread.getMessages()[numberOfMessageInThread - 1]; var mailSubject = targetMessage.getSubject(); // メールの題名から、メール定義情報を探す var jsonMailData = findMailData(mailDataDefinitions, mailSubject); if (jsonMailData == null) continue; // Slackに送信する内容は、「メールタイトル + 条件に従って抽出した本文」 とする var mailBody = mailSubject + "\n" + extractMailBody(targetMessage.getPlainBody(), jsonMailData); postToSlack(jsonMailData, mailBody); // Slackに送信した後、既読にして捨てる thread.markRead(); thread.moveToTrash(); } } // GoogleDriveにあるメール定義のファイルを取得し、JSON形式のデータを返す function getDefinitionFileFromGoogleDrive() { // 定義ファイルがあるかどうかを確認 var files = DriveApp.getFilesByName("MailData.json"); if (files == null) return null; // 定義ファイルの内容を読み込み、JSONとして解釈して返す var file = files.next(); var data = file.getBlob().getDataAsString(); return JSON.parse(data); } // メールのタイトルから、メール定義を探す function findMailData(mailDataDefinitions, mailSubject) { var result = null; mailDataDefinitions.forEach(function (value) { if (mailSubject.indexOf(value.title) != -1) result = value; }); return result; } // 本文の指定された範囲を抽出する function extractMailBody(mailBody, jsonMailData) { var foundStartLine = false; var foundEndLine = false; var splitMailBody = mailBody.split('\n'); var exractedMailBody = ""; // 開始文字列が空文字列の場合には、先頭からすべてを対象とする if (jsonMailData.fromText == "") foundStartLine = true; splitMailBody.forEach(function (line) { // 終了文字列以降はすべて無視する if (foundEndLine) return; // 開始文字列をまだ見つけていない場合には、開始文字列かどうかの判定 if (foundStartLine == false) { if (line.indexOf(jsonMailData.fromText) != -1) { foundStartLine = true; } return; } // 終了文字列を含むかどうかの判定 if (line.indexOf(jsonMailData.toText) != -1) { foundEndLine = true; return; } // 抽出対象の本文に追加 exractedMailBody += line + "\n"; }); return exractedMailBody; } // Slackに送信する function postToSlack(jsonMailData, message) { // Slackで定義されているデータを作成 var jsonData = { "channel": jsonMailData.channel, "username": jsonMailData.username, "text": message }; var payload = JSON.stringify(jsonData); // 送信用データの作成 var options = { "method": "post", "contentType": "application/json", "payload": payload }; // Slackに送信 UrlFetchApp.fetch(postUrl, options); // 荷物お届けの場合のみ、LINEに送信 if (jsonMailData.channel == "荷物お届け") { //後日、別記事で公開するかも... } }
なお、上記のスクリプトは、以下のページのスクリプトをベースに作成しました。この場をお借りしてお礼申し上げます。
https://github.com/comefigo/gmail-to-slack/blob/master/Main.gs
このスクリプトの先頭行の内容は、Slackのアプリの「Incoming Webhook」で取得しなければなりません。Slackの設定画面を開き、アプリの「Incoming Webhook」をインストールしてください。設定画面の「インテグレーションの設定」にある「Webhook URL」から取得できますので、そのまま貼り付けてください。
(このURLを、自分自身以外が知ることがないようにしてください。)
入力後に、保存して下さい。今回は、プロジェクト名を「GmailToSlack」としてあります。
次に、Slackに飛ばすメールの情報を定義した、JSONファイルを作成します。メモ帳などのテキストエディタを起動し、下記の内容を貼り付けてください。(中身については別途説明します。)
[ { "username" : "テスト", "channel" : "#general", "title" : "テストサンプル", "fromText" : "", "toText" : "dummy" } ]
このファイル名を「MailData.json」として保存後、Google Driveを開き、このファイルを配置してください。配置する場所はどこでもかまいません。以下のURLからGoogle Driveに入り、Webブラウザにファイルをドラッグ&ドロップして配置できます。
https://drive.google.com/drive/my-drive
これで最低限の準備が完了しました。動作確認のためのメールが必要となるので、Gmailで自分自身宛のメールを作成し、タイトルを「テストサンプル」とし、適当に本文を記入して送信してください。すぐに自分自身が受信しますが、開封(既読)にしないでください。
再度、Google Apps Scriptに戻り、上部のメニューから「実行」→「関数を実行」→「gmailToSlack」を実行してください。スクリプトからGmailアカウントおよびGoogle Driveのファイルを参照するために、権限を付与することが必要です。「アカウントの選択」画面が表示されるので利用しているGmailのアカウント選択します。「このアプリは確認されていません」の画面が表示されるはずですが今回は自分が作ったものなので、画面下の「詳細」をクリックし、「GmailToSlack(安全ではないページ)に移動」を選択してください。
すべてがうまくいっていれば、Slackに投稿され、メール自体は既読になりゴミ箱に移動します。Slack側でログを保存する前提ですが、そうでなければメールをアーカイブしてもよいと思います。
// Slackに送信した後、既読・アーカイブを行う thread.markRead(); thread.moveToArchive();
なお、下記のページにあるように、メールの取得数制限(1日2万通以内)やスクリプトの動作時間制限(1日90分以内)があります。
https://developers.google.com/apps-script/guides/services/quotas
2万通というとそんなにメールは来ない、と思うかもしれませんが、これはあくまでも1日の処理数です。例えば、1分に1回スクリプトを動作するように設定し、処理対象外のメールが受信トレイに50通残っているとすると、1分ごとに50通のメールを取得して判定し、1日では50通x60分x24時間=72000通、ということで制限を超えてしまいます。
この制限に引っかからないようにすることと、処理時間を短くするために、Gmail側のフィルタで直近1時間以内のメールのみを取得するようにしました。
明日は、定義ファイルの具体的な内容と、トリガーとして定期的に実行する方法を投稿します。
2019/7/23追記
その後、運用する中でJavaScriptの内容を改善していたので、サンプルを差し替えました。
(今は、「荷物お届け」の場合のみ、妻のLINEにも通知する機能も増えています)
はじめまして。
こちらを参考に挑戦しましたが、
SyntaxError: Unexpected token: %
となり処理出来ません。調べてみたものの全く解らずです。アドバイスお願いできませんか??
コメントありがとうございました。
が、すいません、いただいたエラーの内容からは、何が原因か推測できません。
もし、JavaScriptのコード内に「%」の文字があるか、コメント化されていない日本語文字(行の先頭に//がない)があれば、それが原因と思います。
また、JSONの定義ファイル側に問題があるか、文字コードが不適切などで発生する可能性もありそうな気がするので、MailData.jsonファイルをいったん削除して実行してみると、どうでしょうか?
これでエラーが消えるようであれば、MailData.jsonファイルの中身に問題がある可能性があり、エラーが消えないならばJavaScript側に問題がありそうです。
追伸:
この記事のコードは、その後運用を経て改良しています。後ほど内容を更新します!