本記事は内容が古くなっています。いろいろ改修したものはこちらにあります。
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;
}