Gmailで、Thunderbirdの「メールのグループ化」みたいなことをやるスクリプト
本記事は内容が古くなっています。いろいろ改修したものはこちらにあります。
pslabo.hatenablog.com
Thunderbird ではフォルダの表示を「グループ化」にすると「今日・昨日・1週間以内・2週間以内・それ以前」の5つに分類してくれます。
それと同じような分類を Gmail で自動処理するためのスクリプトを Google Apps Script で組んでみました。(JavaScript はあまり得意じゃないのでコードが綺麗でないのはご勘弁を。)
Thunderbird とは違い、あくまで「すべてのメール」に対して前述の振り分けを行うだけですが、iPhone や iPad で Gmail を読むときにちょいと便利かも。
また、ついでの実装ではありますが、以下2つの実装も入れています。
「受信トレイに存在しないメールはすべて既読にする(ただしデフォルトで無効)」
「mail from のドメイン名、メールアドレスで階層化したラベルを振る」
メールソフトによっては、メールを読まずにアーカイブする際に既読にしないことがありますが、そういう場合でも自動で既読にしてくれます。この処理は setReadWithoutInbox() で実装しています。
ドメイン名、メールアドレスで階層化したラベルを振るのは、いまどきのメッセンジャーアプリのような挙動を想定しています。
実際の利用時は、cron10min や cron1day をトリガーで定期的に実行するように設定します。
// Gmail で、様々なラベル振り分けを動的に行うスクリプト // // このスクリプトでは以下の処理を実装しています。 // // ・「1日以内」「1週間以内」「2週間以内」のメールにラベルをつけます // ラベルは初期値では INBOX の下に作られます。 // // ・上記期間から外れるメールからは自動でラベルを外します // // ・受信トレイにないメールを自動で既読にします。 // ※この機能は処理が重いため、初期値では無効にしています。 // 有効にする場合は、"in:anywhere -in:inbox is:unread" の条件で // ヒットするメールを Gmail の UI で予め既読にしてください。 // // ・メールの差出元ドメイン毎にラベルをつけます。 // メールは以下のようにラベルわけされます。 // MailFrom // MailFrom/example.com // MailFrom/example.com/foo@example.com // // 使用方法: // 1. 自動設定対象のラベル名定義を適当に調整してください。 // なお、ラベルを事前に Gmail 側で作成する必要はありません。 // このスクリプトが自動で作成します。 // // 2. 送信元別ラベルを付ける、つけないの設定を調整してください。 // // 3. トリガーで cron10min, cron1day を定期的に実行する設定としてください。 // ラベル名定義 LABEL_1DAY = "INBOX/直近1日以内"; LABEL_1WEEK = "INBOX/直前1週間以内"; LABEL_2WEEK = "INBOX/直前2週間以内"; LABEL_MAILFROM_BASE = "MailFrom" // 差出元ドメイン毎の振り分けを行うかどうか ENABLE_MAILDOMAIN_LABEL=true; // 差出ドメイン毎のラベル振り分けを行う際に // 同時に差出人毎の振り分けも行う ENABLE_MAILADDDRESS_LABEL=true; // 受信トレイに無いメールを既読扱いにするかどうか ENABLE_READED_WITHOUT_INBOX=false; // 数分ごとに実施するバッチ function cron10min() { // 「直近1日」のラベルをつける処理。 setLabel_1day(); } // 日次バッチ。 function cron1day() { // ラベルの範囲外となったメールからラベルを外す。 cleanUpOver1day(); cleanUpOver1Week(); cleanUpOver2Week(); // 受信トレイに存在しないメールを自動で既読にする setReadWithoutInbox(); } // 受信トレイに存在しないメールを自動で既読にする function setReadWithoutInbox() { // ENABLE_READED_WITHOUT_INBOX が true 以外ならそのまま終了。 if ( ENABLE_READED_WITHOUT_INBOX != true ) { return; } // すべてのメールで、受信トレイになく、未読のメールを探す var searchString = "in:anywhere -in:inbox is:unread"; Logger.log(searchString); var threads = GmailApp.search( searchString ); // 見つかったスレッドを対象に、ラベルをつける for (var i = 0; i < threads.length; i++) { Logger.log( "[" + i + "] " + threads[i].getLastMessageDate() + " " + threads[i].getFirstMessageSubject() ); // 既読にする threads[i].markRead() // 処理が速すぎるとエラーが出るので適度に休む //Utilities.sleep(10); } } // 「直近1日」のラベルをつける処理。 // トリガーで数分ごとに実行する想定です。 function setLabel_1day() { _setLabel_nday(1); } // テストコード function setLabel_XXday() { _setLabel_nday(13); } // 「直近 n 日」のラベルをつける処理。 function _setLabel_nday(daysBefore) { // ラベル文字列を label オブジェクトに変換する。 var label1day = _createLabel( LABEL_1DAY ); // ラベル名 LABEL_1DAY がないメールを、直近 daysBefore 日分のメールから探す var dateWithin1day = new Date(); dateWithin1day.setDate(dateWithin1day.getDate() - daysBefore); var searchString = Utilities.formatDate( dateWithin1day, "GMT+9", "yyyy/MM/dd" ); searchString = "after:" + searchString + " -label:" + LABEL_1DAY; Logger.log(searchString); var threads = GmailApp.search( searchString ); _createLabel( LABEL_MAILFROM_BASE ); // 見つかったスレッドを対象に、ラベルをつける for (var i = 0; i < threads.length; i++) { Logger.log( "[" + i + "] " + threads[i].getLastMessageDate() + " " + threads[i].getFirstMessageSubject() ); // 直近1日、1週間、2週間というラベルをつける threads[i].addLabel(label1day); // メールの差出元ドメインごとにラベルを振る var messages = threads[i].getMessages(); for ( var j = 0 ; j < messages.length; j++ ) { if ( ENABLE_MAILDOMAIN_LABEL == true ) { // mail from からドメイン名を抽出する var mailFromDomain = _getDomainFromMailaddress( messages[j].getFrom() ); var labelString = LABEL_MAILFROM_BASE + "/" + mailFromDomain; var labelDomain = _createLabel(labelString); // スレッドにドメイン名のラベルを付ける threads[i].addLabel(labelDomain); Logger.log( "[" + i + "." + j + "] addLabel: " + labelString ); } if ( ENABLE_MAILDOMAIN_LABEL == true && ENABLE_MAILADDDRESS_LABEL == true ) { // メールアドレス毎のラベルも作る。 var mailFromAddress = _getMailaddressFromMailaddress( messages[j].getFrom() ); var labelString = LABEL_MAILFROM_BASE + "/" + mailFromDomain + "/" + mailFromAddress; var labelDomain = _createLabel(labelString); // スレッドにメールアドレス毎のラベルもつける threads[i].addLabel(labelDomain); Logger.log( "[" + i + "." + j + "] addLabel: " + labelString ); } Logger.log( threads[i].getLabels() ); } } } function cleanUpOver1day() { var label = LABEL_1DAY; _removeLabel(label, 1, "before:" ); } function cleanUpOver1Week() { var label = LABEL_1WEEK; _removeLabel(label, 7, "before:" ); _removeLabel(label, 1, "after:" ); _setLabel_week(LABEL_1WEEK, 7, 1); } function cleanUpOver2Week() { var label = LABEL_2WEEK; _removeLabel(label, 14, "before:" ); _removeLabel(label, 7, "after:" ); _setLabel_week(LABEL_2WEEK, 14, 7); } // 指定期間でラベルをつける処理。 function _setLabel_week(labelString, dateAfter, dateBefore) { // ラベル文字列を label オブジェクトに変換する。 var labelObject = _createLabel( labelString ); // dateAfter, dateBefore を現在日付基準の日付に変換 var dayAfter = new Date(); dayAfter.setDate(dayAfter.getDate() - dateAfter); var dayBefore = new Date(); dayBefore.setDate(dayBefore.getDate() - dateBefore); // Gmail の検索条件文字列を生成 var searchAfter = Utilities.formatDate( dayAfter, "GMT+9", "yyyy/MM/dd" ); var searchBefore = Utilities.formatDate( dayBefore, "GMT+9", "yyyy/MM/dd" ); var searchString = "after:" + searchAfter + " before:" + searchBefore + " -label:" + labelString; Logger.log(searchString); var threads = GmailApp.search( searchString ); // 見つかったスレッドを対象に、ラベルをつける for (var i = 0; i < threads.length; i++) { Logger.log( "[" + i + "] " + threads[i].getLastMessageDate() + " " + threads[i].getFirstMessageSubject() ); // 指定されたラベルをつける threads[i].addLabel(labelObject); // 処理が速すぎるとエラーが出るので適度に休む // Utilities.sleep(10); } } // 指定期間のラベルを抜く処理。 function _removeLabel(labelString, delayDays, afterbefore ) { // ラベル文字列を label オブジェクトに変換する。 var label = _createLabel(labelString); // 削除基準の日付(現在日時から delayDays 日前)をセットする。 var dateWithin1day = new Date(); dateWithin1day.setDate(dateWithin1day.getDate() - delayDays); // 指定ラベルの中から削除対象のものを抽出する var searchString = Utilities.formatDate( dateWithin1day, "GMT+9", "yyyy/MM/dd" ); searchString = afterbefore + searchString + " label:" + labelString Logger.log( searchString ); var threads = GmailApp.search( searchString ); // 取得されたスレッドを対象に、削除を実行する。 for (var i = 0; i < threads.length; i++) { Logger.log( "[" + i + "] " + threads[i].getLastMessageDate() + " " + threads[i].getFirstMessageSubject() ); // メールをゴミ箱へ // threads[i].moveToTrash(); // メールからラベルを外す threads[i].removeLabel(label); // 処理が速すぎるとエラーが出るので適度に休む // Utilities.sleep(10); } } // 以下のようなパターンの文字列からメールアドレスだけ抜く // foo bar <foo@example.com> // foo@example.com function _getMailaddressFromMailaddress(mailaddress_raw) { var mailAddress = mailaddress_raw; var mailAddress_return; Logger.log ( "_getMailaddressFromMailaddress input: " + mailAddress ); // メールアドレスが <> で囲まれているかどうかの判定 if ( mailAddress.indexOf("<") >= 0 && mailAddress.lastIndexOf(">") >=0 ) { mailAddress.match("<(.+)>"); mailAddress_return = RegExp.$1; } else { mailAddress_return = mailaddress_raw; } Logger.log ( "_getMailaddressFromMailaddress " + mailAddress_return); return mailAddress_return; } // メールアドレスからドメイン名を抜く function _getDomainFromMailaddress(mailaddress_raw) { var mailAddress = _getMailaddressFromMailaddress(mailaddress_raw); Logger.log ( "_getDomainFromMailaddress " + mailAddress); // メールアドレスからドメイン部分を抜く mailAddress.match("^(.+)@(.+)$"); var mailDomain = RegExp.$2; Logger.log ( "_getDomainFromMailaddress " + mailDomain); return mailDomain; } function _createLabel(labelString) { labelDomain = GmailApp.getUserLabelByName(labelString); // ドメイン名のラベルが無い場合は作る if ( labelDomain == null ) { labelDomain = GmailApp.createLabel(labelString); } return labelDomain; }