みなさん、こんにちは!
タカハシ(@ntakahashi0505)です。
Google Apps Scriptで特定のメールの添付ファイルをGoogleドライブに保存するツールを作っています。
前回の記事はコチラ。
Gmailの添付ファイルをGoogleドライブに保存する方法をお伝えしました。
…これで完成じゃん?
と思うかもしれませんが、そうはいきません。
というのも、スクリプトを何度か実行してみればわかりますが、過去に取得してドライブに保存しているファイルが、実行のたびに何度でも保存されてしまいます。
それを防ぐために、「一度処理をしたメールは処理をしない」ようにする必要があります。
その方法として、今回は「スター」に注目してみたいと思います。
ということで、Google Apps ScriptでGmailのメッセージにスターがついているかを判定する方法、そしてスターを付与する方法です。
では行ってみましょう!
前回のおさらい
前回までで作成したスクリプトはこちらです。
var FOLDER_ID = 'XXXXXXXXXXXXXXXXX'; //保存するフォルダ var SEARCH_TERM = 'subject:(添付ファイルテスト) '; function fetchFile(){ var myFolder = DriveApp.getFolderById(FOLDER_ID); //フォルダを取得 var myThreads = GmailApp.search(SEARCH_TERM, 0, 30); //条件にマッチしたスレッドを検索して取得 var myMessages = GmailApp.getMessagesForThreads(myThreads); //スレッドからメールを取得し二次元配列で格納 for(var i in myMessages){ for(var j in myMessages[i]){ var attachments = myMessages[i][j].getAttachments(); //添付ファイルを取得 for(var k in attachments){ myFolder.createFile(attachments[k]); //ドライブに添付ファイルを保存 } } } }
Gmailで件名に「添付ファイルテスト」を含むメールを30件抽出して、そのメールの添付ファイルをGoogleドライブの指定のフォルダに作成するという内容です。
しかし、冒頭にもお伝えした通り、このスクリプトを複数回実行すると、以下のように同じファイルが大量生産されています。
この状態を避けるべく、「一度処理をしたメッセージに関しては処理をしないようにする」必要があります。
判定に「スター」を使うべき理由
以前、別の記事ではその判定として「未読かどうか」を基準として活用しました。
Gmailの検索コマンドに「is:unread」を入れて検索すれば、未読のメッセージだけを抽出できるというわけです。
この方法も良いのですが、まだ添付ファイルを保存していないメッセージについて、うっかり自分でメッセージを閲覧してしまうと困ります。
そのメッセージは既読になりますから、スクリプトの対象となりませんので、保存すべき添付ファイルも保存できません。
そんなこともありますので、今回は「スター」を使ってみたいと思います。
スターは本来
Gmail では重要なメールにスターのマークを付けることができます。後でメールを確認するときに便利です。
というような使い方をするものですが、スクリプト処理の目印としても活用することができます。
スターはユーザーが付与、解除をすることでのみ操作ができ、「重要」のようにGmailが勝手に付与することもありません。
「ラベル」という手も思いつくのですが、ラベルはスレッド単位で付与される、つまりメッセージ単位では操作ができません。つまり、既にラベルが付与されるスレッドに追加されたメッセージは、新規のものであっても処理対象とならなくなってしまいます。
結果、消去法的にスターを使うのが良いということになります。
starメソッドでメッセージにスターを付与する
Google Apps Scriptでメッセージにスターを付与するのには、その名もstarメソッドを使います。
書き方はこうです。
シンプルですね。
前述のスクリプトの場合は、添付ファイルをドライブに保存した後の17行目に
myMessages[i][j].star();
としてあげればOKですね。
実行すると、各メッセージの添付ファイルがドライブに保存されるとともに、以下のように処理されたメッセージにはサクっとスターが付与されます。
Gmail検索コマンドでの除外ではダメな理由
あとは、スターが付与されているメッセージは処理をしないようにすればよいですね。
まず思いつくのは、Gmailの検索コマンドに「スターがない」という条件を意味する「-label:starred」を付与してあげる方法です。
例えば、このようなコマンドです。
しかし、実際にやってみるとわかるのですが、この方法には問題があります。
以下のように、Gmail検索コマンドはスレッド単位で検索をしてしまいます。
スレッド内でスターが付与されていないメッセージが一つでもあれば、検索結果のスレッドとして上がってきます。
そして、スレッドに含まれるメッセージ全てについて処理がなされるので、その中にスター付のメッセージが含まれていれば、それも処理されてしまいます。
そして、Googleドライブに重複して保存されるファイルが出てきてしまうということになります。
ということで、別の手段を考案しなければなりません。
isStarredメソッドでスターの付与を判定する
そこで、登場するのが、メッセージにスターが付与されているかどうかを判定するisStarredメソッドです。
そのものズバリですね。
書き方はコチラ。
メッセージにスターが付与されていればTrue、そうでなければFalseを返します。
ですから、このisStarredメソッドを使って、メッセージごとに判定を行えばよいということになります。
以上を踏まえたスクリプトはこちらです。
var FOLDER_ID = 'XXXXXXXXXXXXXXXXX'; //保存するフォルダ var SEARCH_TERM = 'subject:(添付ファイルテスト) '; function fetchFile(){ var myFolder = DriveApp.getFolderById(FOLDER_ID); //フォルダを取得 var myThreads = GmailApp.search(SEARCH_TERM, 0, 100); //条件にマッチしたスレッドを検索して取得 var myMessages = GmailApp.getMessagesForThreads(myThreads); //スレッドからメールを取得し二次元配列で格納 for(var i in myMessages){ for(var j in myMessages[i]){ if(!myMessages[i][j].isStarred()){ //スターがないメッセージのみ処理をする var attachments = myMessages[i][j].getAttachments(); //添付ファイルを取得 for(var k in attachments){ myFolder.createFile(attachments[k]); //ドライブに添付ファイルを保存 } myMessages[i][j].star(); //処理済みのメッセージにスターする } } } }
これで、一度処理したメッセージについては、スターが付与されて処理の対象から除外することができます。
まとめ
Google Apps ScriptでGmailのメッセージのスターを判定する方法またスターを付与する方法についてお伝えしました。
GASでのGmailの取り扱いでは、スレッド単位なのかメッセージ単位なのかというところが、けっこう落とし穴になることがあります。
ここの理解があやふやだとドツボにハマることもありますので、やりたいことの単位がスレッドなのかメッセージなのかを、意識しながら進めると良いと思います。
これでツールの本体は出来上がったのですが、せっかくなので次回、チャットワークに通知を送るところまで実装しますね。
お楽しみに!