見出し画像

GASを使ってgmailの特定のラベルが付いたメールを定期削除する

もうね、ココを見て下さい、で全て終わりなんですけども(素敵な記事をありがとうございます)。自分でやってみた雑感とかコツとかのメモをチョコチョコと。

googleさんの容量制限がちょいと厳しくなってきたじゃないですか。なんで、今まで無尽蔵に保存していたメルマガとかメルマガとかメルマガとか諸々の通知メールとか、その辺をごっそり消そうと思ったんですが手作業でやるの死ぬほど面倒だったので、自動化しちまえ~~~~と。思いまして。

やり方は、

・定期的に削除したいメールに自動でラベルが付くようにしておく(「gmail ラベル 自動」とかで検索するとよろしいかと(ココはもう自力でサクサク出来るので、操作説明は他力本願))
・Googleドライブ内に新しくスプレッドシート(などのGASが仕込める適当なAPPのファイル)を作って、「ツール>スクリプトエディタ」からAppsScriptを新規作成
・コードを数行書く
・権限設定をする
・スケジュール設定して定期稼働するようにする
・完成!

と非常に簡単。上記の記事を見ながらやったら、コードを書くところまで5分で終わりました。(既にGASを使い慣れてるせいもあるけど)

と言うわけでAppsScriptファイルを作るところまでは冒頭の記事が非常に丁寧なので、割愛。

ここから先は記事だけだとちょっと躓いた箇所をぼちぼちメモ。(とはいえリファレンス探すところからやっても15分で動くようになりましたィェィ)

コードを書く

function myFunction() {

 deleteMail(GmailApp.search("label:0_auto_delete older_than:30d"));
 
}

function deleteMail(deleteThreads){
 
 for(let i in deleteThreads){
   let deleteThread = deleteThreads[i];
   // console.log(deleteThread.getFirstMessageSubject());
   deleteThread.moveToTrash();
   // console.log(deleteThread.isInTrash());
 }
 
}

デバッグ用のコード含めて、書いたのはこれだけ。これだけで「0_auto_deleteラベルが付いている30日以上前のメールをぜーんぶ消す」が可能です。

ラベル名に0_が付いているのは、手動で「後で消す」ラベル付けたいときに、該当ラベルがラベル一覧の先頭に来て作業が楽になるからです。

forはちょっとかっこよくfor...in文に置き換えてみましたが、やってることは同じです。(javascriptのfor...in文って、あくまでもオブジェクトのキーを取るだけなので、結局配列のキー指定して取らないといけないから、forの所ちょっとスッキリ書ける程度の違いしかないのだった~)

GmailApp.search()の引数について

GmailApp.search()に渡している引数("label:0_auto_delete older_than:30d")は、gmailの画面のメール検索ウインドウに入力する様式をそのまま使えます、っていうのが公式リファレンスのぱっと視界に入る範囲には書いてなくて、ちょっと「何が使えるんやろ??」って彷徨いましたが、gmailの画面のメール検索ウインドウに使える検索演算子をそのまま使えるそうです。

これ。

一回gmailの検索ウインドウに打ち込んでみて、正しく検索結果が得られることを確認してからコードに貼り付けると良さそうです。

この検索って、実はフィルタを使ってラベルを自動付与する時と同じ処理なので、「Gmail側で検索条件に該当するスレッドにラベルを付与」「GAS側でラベルを検索して削除」じゃなくても、「GAS側で検索条件に該当するスレッドを削除」っていきなり出来ちゃったりするんですが、メール画面見たときに「このラベル付いてる奴はそのうち消える」って分かったほうが直感的かなと。消したくないメールだけ手動でラベル外しておくことも出来ますし。

デバッグ用コードのせつめい

deleteThread.getFirstMessageSubject()で、「スレッドの最初のメール」の件名を取得しています。

ここのdeleteThreadには、GmailApp.search()で取ってきたメールの一覧(deleteThreads)のi番目のスレッド(GmailThreadオブジェクト)が入っていますね。

GmailApp.search()の戻り値はGmailThreadオブジェクトの配列です。
スレッドの配列です。
スレッドが取れます。
つまり、該当のメールに返信がいくつも連なっている場合、メール単体ではなくスレッド全てが処理される様子です。が、今回やりたい「要らんメールの定期削除」の場合、概ね向こうから勝手に届くメルマガなどの処理なので、深く考えなくて大丈夫でしょう。件名取りたかったらgetFirstMessageSubject()なんだなって思っといてください。

deleteThread.isInTrash()では、ちゃんとゴミ箱に入ったかどうかをチェックしています。戻り値はBooleanです。コメントアウトを外せばTrue/Falseが表示されます。ちゃんと処理できていればTrueがでるはず。

そのほか、スレッドに対して可能な操作はこちらのリファレンスが参考になります。英語だけど、そんな難しいこと書いてないです。

ついでに、GmailAppクラスのリファレンスはこっち。

英語のリファレンスをサラサラ読めるようになりたいものです。

あれれ~、isInTrashはTrueなのにGmailの画面で見るとゴミ箱に入ってないぞ~?

ってなって暫く躓いたんですが、ラベル間の移動ではなく画面のリロード(ブラウザ側でのリロード)をしたら消えました。画面外からの操作に対しては、Gmail画面内の移動ではキャッシュが更新されなくて残っちゃうみたい。

6分の壁

GASのアプリは一回の連続起動時間6分間までという鉄の掟があるので、溜まりに溜まった10000通のメールマガジンを一括削除しようとしたりすると、途中で落ちてしまいます。

私の環境でやってみたところ、50通削除するのに16秒掛かりました。一通の削除に0.32秒。どうも1000通くらいで限界を迎えそうです。こりゃ遅いなぁ……

今削除したいメルマガが一万通くらいあるんですが、別のラベルを用意して、地道に1000通ずつ削除していくとかするのが良いのかなー。

6分で落ちないように、予め処理する件数を絞るには、

deleteMail(GmailApp.search("label:0_auto_delete older_than:30d",0,500));

って感じでsearchの引数に二つ数字を追加すると良さそう。
最初の0が、何件目から取得するかを指定し、次の500が最大何件までを取得するかを指定しています。最大値は500らしい。1000件取得しようとしたら怒られた(´・ω・`)

ちなみに読み出しは無料アカウントでも一日20000回(※読み/書き(下書き)合計なので注意)まで可能らしいので、一日のうちに何回もプログラムぶん回しても、10000通くらいならAPI利用上限の方は大丈夫そうです。

(メールの自動送信を考え始めるとAPI利用上限が気になってくるのですが、まあ、メールの大量自動送信をしたい場面って大半ろくでもない使い方と想定されるので、無料アカウントでの送信数制限は仕方が無いところでしょう)


この記事が気に入ったらサポートをしてみませんか?