GASでGmailを取り扱う方法の説明です。
今回もメール検索の方法教えてと言われたので、サクッとまとめてみました。
これまで何度かGmailを送る方はこの記事でも紹介してきました。一般的にシートのデータを共有したり、情報をまとめて送ったりすることの方が多いかもしれません。メール送付側の記事は以下をご参照ください。
逆に受信したメールを検索する側ももちろんGASで対応できます。今回はこの検索する側の方法をメインに解説していきます。
Gamilサービスの概要
Gmailサービスは主に以下のようなクラスを有しています。
クラス | 概要 |
GmailApp | Gmailサービスのグローバルオブジェクト。SpreadsheetのSpreadsheetAppのイメージ |
GmailThread | スレッドを操作するための機能を提供するクラス |
GmailMessage | メッセージを操作をするための機能を提供するクラス |
スレッドという概念が少しわかりにくいかもしれないのですが、メールチェーン自体をスレッドと読んでいます。メッセージ1個でもスレッド経由でメッセージにアクセスする必要があるのが難点でしょうか。もちろんメッセージID(uniqueID)を把握していれば直接取得できますが、基本検索することになるのであまりピンポイントでメッセージIDで取得するというケースは少ないかと思います。
ざっとしたイメージは以下の画像でご確認ください。

要は、GmailApp-> Threadリスト取得 ->Threadの取得 -> Messageのリスト取得 -> Message取得という流れになります。
検索での取得〜処理の流れ〜
基本的な検索方法は、以下のようなものになります。
①検索する条件を作成する
②該当するメッセージ(GmailMessage)のリストを取得する
③メッセージリストからメッセージを取得する(2次元配列->1次元配列に変更)
④1次元のメッセージ配列から1つ目の要素を取得
⑤メッセージから内容を取得する
検索での取得〜サンプルコード〜
function search_email() {
//①検索する条件を作成
const start = 0;
const max = 10;
const query = "after:2020/05/21 before:2020/05/26"
var threads = GmailApp.search(query, start, max)
//②該当するメッセージ(GmailMessage)のリストを取得する(今回は単一スレッド検索)
var messageForThds = GmailApp.getMessagesForThreads(threads)
//③メッセージリストからメッセージを取得する(2次元配列->1次元配列に変更)
for(var message of messageForThds){
//④1次元のメッセージ配列から1つ目の要素を取得
let message_data = message[0];
//⑤メッセージから内容を取得する(今回は題名とメッセージIDを取得する)
Logger.log(message_data.getSubject());
Logger.log("messageId:", message_data.getId());
}
}
メソッドとして重要なのは、スレッドリストを取得するための,getmessagesForThreads()メソッドとなります。この2つが検索でメールを取り扱う場合の基本的な使用メソッドです。
また、スレッドリストからスレッドを取り出す方法については、今回はfor .. of ..で実施しています。後ほどのカテゴリ別の方では、foeEachを使った方法を紹介しています。個人的にはforEachの方が慣れているのですが、for .. of..の方が説明がわかりやすいので、こちらを先に紹介します。
注:ちなみにですが、GASでforEashは非推奨です。
スレッド検索の肝:検索クエリ設定について
スレッド検索の肝となるクエリについては、上の例では、日付で設定しています。
const query = "after:2020/05/21 before:2020/05/26"
この部分はもちろん日付以外にも文字列でも可能です。特定の文書が絶対に入っているメールスレッドを検索したければ特定の文字列を入れれば大丈夫です。
また、このクエリはgmailブラウザの検索ウィンドウで利用可能な検索クエリが使用可能です。
複数の検索クエリを利用したい場合
複数の検索クエリを利用したい場合は、上のサンプルで示したように、条件式を半角スペースで連結していけば何個でも追加可能です。
追加できるクエリの種類は先ほど紹介したリンクからご確認ください。
例えば、5月21日〜5月26日の間にaaa@aaa.comから受信したメールを検索したい場合は、以下のようになります。サンプルコードにfrom:を追加しただけです。
const query = “after:2020/05/21 before:2020/05/26 from:aaa@aaa.com”
カテゴリ別で取得〜処理の流れ〜
スター付きのメールやtrashメールなどは、Gmail上で別にinbox内の別カテゴリに区分されています。GamilAppで利用可能なカテゴリ別は以下のようなものがあります。
それぞれ全メールスレッド取得とstart/maxを引数に指定する(件数指定)方法が存在します。件数をしていない場合、全メールスレッド取得となります。
メソッド | 対応カテゴリ |
getInboxThreads() getInboxThreads(start, max) | inboxに含まれているメールスレッドを取得 |
getPriorityInboxThreads() getPriorityInboxThreads(start, max) | プライオリティinboxに含まれているメールスレッドを取得 |
getSpamThreads() getSpamThreads(start, max) | スパムのカテゴライズされたメールスレッドを取得 |
getStarredThreads() getStarredThreads(start, max) | スター付きにカテゴライズされたメールスレッドを取得 |
getTrashThreads() getTrashThreads(start, max) | ゴミ箱にカテゴライズされたメールスレッドを取得 |
カテゴリ別の取得をみてもらえればわかる通り、メールボックスのカテゴリに含まれているものを取得するだけなので、実は検索で同様の条件を設定すれば事足りる話でもあります。また、検索クエリを含めることはできないメソッド群です。
処理の流れは以下のような形です。検索条件を設定するクエリを使う場合に比べて、少し手順が増える形です(メッセージのリストをスレッドのリストから取得する必要があるため)
①スター付きのスレッドリストを取得する
②スレッドリストからスレッドを取得する
③スレッドからメッセージリストを取得する
④メッセージリストからメッセージを取得する
カテゴリ別で取得〜サンプルコード〜
function search_starred_email() {
//①スター付きのスレッドリストを取得する
const messageStarThreads = GmailApp.getStarredThreads();
//②スレッドリストからスレッドを取得する
//③スレッドからメッセージリストを取得する
messageThreads.forEach(function(thread){
④メッセージリストからメッセージを取得する
let messages = thread.getMessages();
messages.forEach(function(message){
Logger.log(message.getSubject());
Logger.log("messageId:", message.getId());
})
})
}
今回はforEachで書いています。個人的にはこっちの方が慣れていて使いやすいのですが、検索編で紹介したFor.. of.. の方が読みやすいので、forEachの方法紹介は後回しにしています。
Gmail検索の留意点
メールを直接検索したいと思いますし、できると思うかもしれませんが、実は単純にはできません。
問題の根幹は検索が、厳密には「メールに対する検索」ではなく、「スレッドに対する検索」しか行えないことにより生じます。
つまり特定の条件でメールを検索しても、返されるのは実はスレッドで、そのスレッド内に検索したいメール以外が含まれていた場合、余分なメールも一緒に取得されてしまいます。
スレッドから特定のメールを検索したい場合、自分でフィルタを作成する必要があるので、頭の片隅においておいてもらえるといいかと思います。
まとめ
数ヶ月ぶりにGASを書いた気がします。結構いろんなことを忘れてますね汗
習慣化と継続学習が一番大切ということで、GASでメールを検索して色々やっていきたいと思います。今想定しているのは以下のような内容です。
第1回(今回):概要・基本的な検索による取得方法・カテゴリ別の取得
第2回:取得したメールをスプレッドシートに書き込む
第3回:検索クエリでよく使う検索演算子と正規表現
第4回:スレッドフィルターではなくメール単位のフィルターの作り方
第5回:messageID(unique ID)を使って新規メールだけシートに追加していく方法
それではいいGASライフを。