ビジネスや日常のタスク管理を効率化するために、Gmailを受信した際に自動でGoogleカレンダーにタスクを登録できたら便利ですよね。本記事では、Google Apps Script (GAS) を使って、GmailのメールをトリガーにGoogleカレンダーにイベントを自動追加する方法を詳しく解説します。
タスク管理をしたかった経緯
私のチームではグループアドレス宛に送られてきたメールをメンバーに振り分けて仕事をしています。メンバーごとにある程度の役割分担をしているので、基本的には同じ人が同じ仕事をすることになります。
人間が判断することですので勘違いやうっかりなどで作業漏れが発生する可能性があり、業務中よく確認するGoogleカレンダーにタスクとして登録できれば漏れが防げると考えました。
グループアドレス宛に送られてくるメールは従業員が手書きしたものもありますが、社内システムやGoogleフォームからの申請等、メールのフォーマットが決まっているものがあり、今回はこれらの定型的なメールをターゲットにします。
当初やりたかったこと
Gmailを受信したときにメール件名に特定の文字が含まれていたらタスクに登録する。タスクの期限は内容によって異なるため、メール受信日時にして後から手作業で本来の期限に変更する。
ということで、これをGASで実装しようとすると次のような流れになります。
- トリガーをメール受信時にする。
- 受信したメールの件名に指定した文字列が含まれていたら
- メールの受信日時でタスクを作成する。
早速コーディングをしてみようとしましたが思っていた通りにはいきませんでした。
最終的に実装した内容
トリガーをメール受信時にする。
トリガーで設定できるイベントのソースには時間主導型とカレンダーからしか選べませんでした。ということで考え方を変えて時間主導型で定期的にメールボックスを監視する設計に変更しました。
しかし、ここでは2つの問題にぶち当たりました。まず考えたのが仮にトリガー間隔を1時間としたときにトリガー実行時から1時間(+数分)前まで遡って受信したメールを検索することです。これは一度監視したメールを次のトリガータイミングで再度監視しないことで無駄を省くための仕組みです。トリガー間隔の1時間はあくまでも仮の値なので将来的に変更したときにも対応できるようにGASのコードからトリガー間隔を取得してその値を採用して遡る時間を算出しようと考えました。
GASのリファレンスではgetProjectTriggersが戻り値としてトリガーの配列Trigger[]を返すのでこれが使えそうと考えました。
https://developers.google.com/apps-script/reference/script/script-app?hl=ja#getprojecttriggers
しかしどうやらTrigger[]はトリガー間隔を返してくれないため諦めざるを得ませんでした。結局トリガー間隔を1時間で定義して1時間前から検索することにしました。受信したメールの件名に指定した文字列が含まれていたら
GmailAppクラスのsearch関数が使えそうです。
https://developers.google.com/apps-script/reference/gmail/gmail-app?hl=ja#searchquery
これならメールの件名を指定しつつ、日時も指定できそうです。
こちらを参考にすると
https://support.google.com/mail/answer/7190?hl=ja
subject:指定したい件名 after:YYYY/MM/DD HH:MM:SS
をコーディングしてみましたが、どうも時間の指定が効いていないようです。再度リファレンスを確認すると日付しか指定できないことに気づきました。。。このまま突き進むとトリガーが動作するたびに1日分のメールが検索されてしまいます。別にいいといえばいいのですが私のプライドがそれを許せず、次のように変更しました。まずはGmailのフィルター機能で特定の件名のメールを受信したら未処理というラベルを付けます。これはGASの構築とは関係ありません。GASは定期的に未処理ラベルを監視します。- メールの受信日時でタスクを作成する。
未処理が見つかったらメールの受信日時でタスクを作成します。ここでまた問題が。
タスクの生成はリファレンスからは読み取れないのですが、タスクの情報にDueを指定すると期限が指定できます。
https://developers.google.com/tasks/reference/rest/v1/tasks/insert?hl=ja
しかし、これも日時が指定できず日付のみの指定しかできないため、受信日でタスクを作ることにしました。そして、タスクから元のメールに返信ができるようにタスクにメールのリンクを追加しました。 - 未処理ラベルを外してタスク済ラベルを付ける。
これはGASが監視する監視対象の未処理ラベルを外すことで次のトリガータイミングで同じメールを処理しないための工夫です。
そしてなぜタスク済ラベルを付けたかというと未処理の子ラベルとしてタスク済ラベルを入れたかったためです。
コードの解説のため未処理としましたが、実際に使うときは例えばやることといったラベル名にするつもりです。
やることが外れたタイミングでそのメールはラベルなしの通常のメールと混ざってしまい、メーラー内での管理がしにくくなるためです。
それではようやく本題に入ります。
必要な準備
- Gmailアカウント
- Googleカレンダー
- Google Apps Script (GAS) の基本操作
スクリプトの作成手順
以下は、受信したGmailの件名と本文を使ってGoogleカレンダーにイベントを登録するスクリプトの例です。
ステップ1:Gmailで特定の件名に未処理ラベルを付ける
ステップ2:タスクサービスを有効化する
サービスの右隣の+をクリックし、Google Tasks API を選択し、追加ボタンをクリックします。
ステップ3:新しいプロジェクトを作成
- Google Apps Script にアクセスし、新しいプロジェクトを作成します。
- プロジェクト名を「createTaskFromGmail」に設定します。
- コードに次のロジックをコピペします。
function createTaskFromGmail() { // listTaskLists(); return; var taskListId = 'ここにタスクリストIDを入れる'; // タスクを追加するタスクリスト // ラベル名を指定(例: "Important" ラベル) var searchlabelName = '未処理'; var addlabelName = 'タスク済'; // 親ラベルの下に子ラベルを配置する場合は'親ラベル/子ラベル'の形式にする. addlabelName = [searchlabelName, addlabelName].join("/"); // ラベルオブジェクトを取得 var label = GmailApp.getUserLabelByName(searchlabelName); // ラベルが存在しない場合は終了 if (!label) { return; } // 追加するラベルを指定 var addLabel = GmailApp.getUserLabelByName(addlabelName); // ラベルがついたスレッドを取得 var threads = label.getThreads(); // 各スレッドに対して処理を実行 for (var i = 0; i < threads.length; i++) { var messages = threads[i].getMessages(); var message = messages[0]; var taskTitle = message.getSubject(); var taskNotes = 'From: ' + message.getFrom() + '\n' + 'Message: ' + message.getPlainBody(); // メールの送信日時を期日として設定(ISO 8601形式) var taskDueDate = new Date(message.getDate()).toISOString(); // 送信日時を期日として設定 // メールへのリンクを作成 var messageLink = 'https://mail.google.com/mail/u/0/#inbox/' + message.getId(); // メールリンクをタスク詳細の先頭に追加(URLとして表示) var taskNotesWithLink = 'Link to email: ' + messageLink + '\n\n' + taskNotes; // タスクを作成するためのオブジェクト var task = { title: taskTitle, notes: taskNotesWithLink, // メールリンクをタスクの詳細に追加(先頭に配置) due: taskDueDate }; var createdTask = Tasks.Tasks.insert(task, taskListId); // 抽出用のラベルを削除し、処理済みのラベルを付与 threads[i].removeLabel(label); threads[i].addLabel(addLabel); } } function listTaskLists() { // Google Tasks API を使用してタスクリストを取得 var taskLists = Tasks.Tasklists.list(); // すべてのタスクリストのタイトルと ID をログに表示 if (taskLists.items) { for (var i = 0; i < taskLists.items.length; i++) { Logger.log('Task list: ' + taskLists.items[i].title + ', ID: ' + taskLists.items[i].id); } } else { Logger.log('No task lists found.'); } }
- タスクリストIDがわからないため、2行目のコメントを外します。
// listTaskLists(); return;
この状態でGASを実行すると実行ログの欄にタスクリストIDが表示されます。赤枠の部分を3行目にコピペします。
2行目は不要になるので再度コメントに戻してください。
- トリガーを作ります。タイミング等はお好みで設定してください。
以上が受信したメールをタスク登録するためのGASになります。