GASでMailの内容を読み取って処理したい時
GASでMailの内容を読み取って処理したい時:
Gmailに届いたメールをパースしてPDFに整形するサービスを作ったのですが、処理済みのメールを無視するのに少し手間取りました。ここでは現時点でベストと思う結論についてシェアしたいと思います。
メールの取得は次のように行います。
ここで取得出来るのはthreadであってmailでは無いのがポイントです。これが色々とややこしい事態を生み出しているのですが、困った事に短期間で受信された同じタイトルのメールはthreadとしてバンドルされてしまいます。例えば別のメールでも同じタイトルだと、まとめちゃうおじさんがどこからともなくやってきて、一つのthreadにまとめられてしまいます(伝わる人いるかな、、、)。
さて、これを前提に色々と検討してみます。
Archiveすると
プログラムを見れば分かりますが、Archiveはthreadに対して実行します。従って、threadのメールを全て処理した後にArchiveする必要があります。この処理中に新しいメールがバンドルされたら、、、
ただ、やはりArchiveは使えません。何故かと言うと、Archiveしたthreadに新しいメールがバンドルすると受信箱に戻ってきてしまうからです(未練がましいですね)。そうするとまた
削除すれば
Archiveと違ってファイルに適用されるので、使いやすいです。ただし、moveToTrashしか出来ず、完全に削除するメソッドはありません。その為か新しいメールでバンドルされた場合はゾンビのように蘇ってきます。従って、同じ件名のメールがバンバン飛んでくる環境では使えません。また当然、メールを削除出来ない案件では使えません。
これも案件によっては使えない可能性がありますが、今の所ベストな方法です。ここでは処理済みのメールに特定のラベルを付けます。ラベルはThreadに付けるので、メールが個別に持つメールIDをラベルに入れます。こうする事で、同じスレッド無いで処理ずみと未処理のメールを分ける事が出来ます。
ただし、labelの名前は2000までという制限があるようです。前述した通り、受信する時間に間隔がある場合はbundleされませんので、ラベル付けから一日たったメールは"HOGE"という名前にしています。今の所はこれでうまくいっています。
要件を許せば削除が一番簡単です。私も別の個人プログラムでは採用しています。ただしthread bundle問題を回避するのはlabelしか思いつきませんでした。なお、labelを使う場合は、受信したアカウントから別のアカウントに転送してから処理しています。そうすればラベルを気にしなくて良いですし、件名でフィルタリングすればメールの件数も減りますので。
もしもっと良い方法があったらコメント頂けると嬉しいです。
はじめに
Gmailに届いたメールをパースしてPDFに整形するサービスを作ったのですが、処理済みのメールを無視するのに少し手間取りました。ここでは現時点でベストと思う結論についてシェアしたいと思います。
メールの取得方法
メールの取得は次のように行います。var threads = GmailApp.getInboxThreads(0,100); var tlen = threads.length; for (var i = 0; i < tlen; i++) { /* Do Something */ }
さて、これを前提に色々と検討してみます。
Archiveを使う
ArchiveするとgetInboxThreads
で取得されません。次は公式から持ってきたArchiveの例です。var firstThread = GmailApp.getInboxThreads(0,1)[0]; firstThread.moveToArchive();
firstThread.refresh()
が使えそうです。ややこしいですが。ただ、やはりArchiveは使えません。何故かと言うと、Archiveしたthreadに新しいメールがバンドルすると受信箱に戻ってきてしまうからです(未練がましいですね)。そうするとまた
getInboxThreads
で取得出来てしまいます。従って、処理したいメールのタイトルが毎回違って、同じタイトルでメール受信する事がほとんどない場合は使えると思います。ただリフレッシュしないと問題は結構面倒だと思います(試してないですが)。
削除する
削除すればgetInboxThreads
で取得されません。次のように行います。function deleteById(id) { const m = GmailApp.getMessageById(id); m.moveToTrash(); }
ラベルを使う
これも案件によっては使えない可能性がありますが、今の所ベストな方法です。ここでは処理済みのメールに特定のラベルを付けます。ラベルはThreadに付けるので、メールが個別に持つメールIDをラベルに入れます。こうする事で、同じスレッド無いで処理ずみと未処理のメールを分ける事が出来ます。var threads = GmailApp.getInboxThreads(0,100); var tlen = threads.length; for (var i = 0; i < tlen; i++) { const messages = threads[i].getMessages(); const mlen = messages.length; for (var j = 0; j < mlen; j++) { var m = messages[i]; if (isValid(m)) { /* Do Something*/ var label = GmailApp.getUserLabelByName("HOGE_" + m.getId()); threads[i].addLabel(label); } } }
まとめ
要件を許せば削除が一番簡単です。私も別の個人プログラムでは採用しています。ただしthread bundle問題を回避するのはlabelしか思いつきませんでした。なお、labelを使う場合は、受信したアカウントから別のアカウントに転送してから処理しています。そうすればラベルを気にしなくて良いですし、件名でフィルタリングすればメールの件数も減りますので。もしもっと良い方法があったらコメント頂けると嬉しいです。
コメント
コメントを投稿