【GAS】Gmailに送られた過去のメールから特定条件のメールを検索して取得する

みなさん、こんにちは!
タカハシ(@ntakahashi0505)です。

みなさん、問い合わせメールの集計・分析ってしていますか?

問い合わせフォームからの問い合わせが毎月どれだけあって、どんな内容のものが、どれだけあって、どれだけ受注したか…なんて、記録とっていたら便利ですよね?

さて、ということで今回から何回かに分けて、以下のようなツールを作っていきたいと思います。

  1. 過去の問い合わせメールをスプレッドシートに取り込んで整理する
  2. 問い合わせフォームから送信されたメールをスプレッドシートに追加していく

初回の今回は、Google Apps Scriptで過去の問い合わせメールを特定条件で検索して取り出す方法です。

では、行ってみましょう!

スポンサーリンク

Gmailで受信さえしていればGoogle App Scriptで色々できる

まずGmailを使っているというのが前提です。

Gmailであれば、Google Apps Script(GAS)を使って様々な操作をすることができます。

以下の記事は、Gmailを操作してメールを送る方法ですね。

初心者でも簡単!Google Apps ScriptでGmailを操作してメールを送る方法
Google Apps Scriptでメールマガジンを送るシステムを作りたいと思います。シリーズ初回の今回は、Google Apps ScriptでGmailを操作してメールを送る方法です。

逆にGmailに届いたメールであれば取得をしてくることができます。

会社のアドレスなどドメインがgmail.comでなくとも、Gmailをメーラーとして使うことができます。

1つのGmailアカウントで複数のメールアドレスをまとめて使えるようにする方法
会社、プライベートなどの複数のメールアドレス…実は1つのGmailアカウントでまとめて管理できます。別のメールアドレスをGmailで送受信する設定をする方法について、とってもわかりやすくお伝えします。

とにかくGmailで受信していればGoogle Apps Scriptでアレコレできるってわけです。

ぜひ、Gmailを使いましょう。

Gmailの問い合わせのメールのみを抽出する

さて、今回のお題ですが、Gmailに蓄積されている数々のメールの中から、サイトの問い合わせフォームから送られたもののみを選んで抽出します。

たとえば弊社の場合は、WordPressのプラグインContact Form 7を問い合わせフォームに使っていまして、以下のような内容で管理者宛にメールが送られます。

Contact Form 7からの問い合わせ通知メール

このメールのうち、以下の部分は必ず含まれているので、抽出条件として使わせてもらおうと思います。

このメールは 株式会社プランノーツ (http://plannauts.co.jp) のお問い合わせフォームから送信されました

例えばGmailの検索窓で以下のように入力して検索します。

“このメールは 株式会社プランノーツ http://plannauts.co.jp のお問い合わせフォームから送信されました”

すると、以下のように検索結果が表示されました。

Gmailで特定条件でメールを検索した結果

ちなみに、スペースを含む文字列で検索したい場合はダブルクォーテーションで囲めばOKです。

これと同様の検索をGASで実現できれば良いということですね。

特定の文字列を含むメールを取り出すスクリプト

GASで特定の文字列を含むメールを取り出すスクリプトを作ってみました。

function searchContactMail() {
 
  const query = '"このメールは 株式会社プランノーツ http://plannauts.co.jp のお問い合わせフォームから送信されました"';
  const start = 0;
  const max = 10;
 
  const threads = GmailApp.search(query, start, max);
  const messagesForThreads = GmailApp.getMessagesForThreads(threads);
 
  for(const messages of messagesForThreads){
    console.log(messages[0].getSubject());
  }
 
}

ひとまずこれだけ…簡単そうですね。

以下解説をしていきますね。

searchメソッドでGmailから特定条件でスレッドを検索する

Gmailから特定条件のスレッドを検索するにはGmailApp.searchメソッドを使います。

書式はこちらです。

GmailApp.search(検索条件, 開始スレッドのインデックス, 最大取得数)

開始スレッドのインデックスですが、今回はすべてのメールを検索してきたいので、0を指定しています。

最大取得数ですが、仕様上500スレッドが最大になっていますが、以下記事の通り、1日あたりのGmailの読み取り制限がありますので、抑えめに設定をしておくのが望ましいです。

429 Too Many Requests

なお、GmailApps.searchメソッドで取得できるものはスレッドの集まりになります。

getMessagesForThreadsでスレッドから個別のメールを取得する

Gmailをスレッド表示にしている方はご存知だと思いますが、Gmailではメールの一連の流れを「スレッド」というかたまりで管理してくれています。

最初のメールに対する返信、またそれに対する返信…といったやり取りは基本的に全部同じスレッドに紐づくことになります。

ですから、スレッドはいくつかのメール(メッセージといいます)の集まりになります。

スレッドの集まりからメッセージをまとめて取得するにはGmailApp.getMessagesForThreadsメソッドを使います。

書き方はこちらです。

GmailApp.getMessagesForThreads(スレッドの集まり)

メソッド名の通り、スレッドの集まりから含まれるメッセージを全て取得できるのですが、メッセージは二次元配列に格納されます。

例えば今回のスクリプトの例ではmessagesForThreadsが二次元配列になります。

つまり、以下のような内容になります。

  • messagesForThreads[0][0] →1番目のスレッドの1番目のメッセージ
  • messagesForThreads[0][1] →1番目のスレッドの2番目のメッセージ(たぶん1回目の返信?)
  • messagesForThreads[1][0] →2番目のスレッドの1番目のメッセージ

for…of文でループする

for…of文は、以下の構文で、配列などに含まれる要素をひとつずつ取り出して処理をするものです。

for (const 定数 of 配列) {
 //処理
}

今回の場合は、ループ毎に取り出す要素は、ひとつのスレッドに含まれるメッセージの集まりによる一次元配列です。

その構成は、以下のようになりますから、インデックス0を取り出してくれば、最初の問い合わせの通知メッセージを取り出してくれるはずです。

  • message[0] →スレッドの1番目のメッセージ
  • message[1] →スレッドの2番目のメッセージ(たぶん1回目の返信?)

実行結果

getSubjectメソッドはその名のとおり、メッセージの件名を取得できます。

メッセージから色々と取得するのは、次回以降詳しく解説をしたいと思います。

本スクリプトでは各スレッドの配列番号0、つまり1番目のメッセージの件名をログ出力するというものです。

実行してみますと、以下のようにログが出力されます。

Gmailから抽出したメッセージの件名をログ出力

まとめ

Google Apps Scriptで過去のGmailに送られたメールの中から特定の条件のメールを検索して取得する方法についてお伝えしました。

スレッドの考え方さえ理解できちゃえば簡単かなと思います。

さて、次回はログ出力ではなくてスプレッドシートに出力をしていきたいと思います。

429 Too Many Requests

どうぞお楽しみに!

連載目次:GASでGmailに届いた問い合わせメールを収集する

お仕事の現場では日々様々なメールが届きます。その中で重要なのが「問い合わせメール」ですね。このシリーズでは、Webサイトからの問い合わせメールを自動でスプレッドシートに取り込んだり、チャットワークに送る方法についてお伝えしていきます。

  1. 【GAS】Gmailに送られた過去のメールから特定条件のメールを検索して取得する
  2. 【GAS】Gmailからメールを検索してスプレッドシートに書き出す方法
  3. 【GAS】Gmailのメッセージから返信先とパーマリンクを取得する方法
  4. 【GAS】新たな問い合わせメールをGmailで取得しスプレッドシートに随時追加する
  5. 【GAS】Gmailに来た問い合わせをChatworkに通知してかつタスク追加する
  6. Google Apps ScriptにおけるGmailの読み取り件数の制限とその対処法

コメント

  1. カッコウ より:

    こちらのおかげでスクリプトによる出力ができました。
    ありがとうございます。

    一つ質問なのですが、期間指定をして検索をしたところ一部検索からメールが漏れてしまう事象が発生しています。
    原因に心当たり等ありましたらご回答いただけると幸いです。

    • カッコウさん

      コメントありがとうございます。

      一つ質問なのですが、期間指定をして検索をしたところ一部検索からメールが漏れてしまう事象が発生しています。
      原因に心当たり等ありましたらご回答いただけると幸いです。

      そうですね…
      例えば、考えられるのは、Gmailの検索はスレッド単位であって、メッセージ単位ではないので、漏れているように見えるとかというのはあるかも知れませんが…
      違いますかね?

  2. 綾鷹 より:

    こちらのスクリプトを参考にして、今スクリプトを作成しております。
    「○○を含まない」で検索すると、「○○を含む」で検索されてしまうのですが
    いかがでしょうか…?

  3. 綾鷹 より:

    タカハシさん

    早速コメントいただきありがとうございます。
    詳細を記載せずに失礼いたしました。

    例えば、メールを検索する際に件名が「りんごとみかん」「みかん」がある場合、
    「みかん」のみを抽出し、「りんごとみかん」を省きたいのです。

    スクリプト内で
    var strTerms = ‘(“-りんご” “みかん” “-in:chats” )’;
    と記載して動作を試みるも、「りんごとみかん」のみが表示されるという
    正反対な結果となり、どうしたらいいものかと悩んでおります。
    ※実際のGmail上で「-りんご みかん -in:chats」と検索すると「みかん」のみが
    表示されます。

    こちら分かるようでしたら、お手数ですが、教えていただけますと幸いです。

    • ご返信ありがとうございます。

      まだ正確にやりたいことを理解できていないかもしれないのですが、それであれば以下のようにstrTermsに設定すればよいのではないかと思います。

      var strTerms = '-"りんご" "みかん" -in:chats';
      

      たぶん、ダブルクォーテーションの中にハイフンを入れているのが原因かなと。あと、“-in:chats”も良くない気がします。
      ダブルクォーテーションは完全一致を表しますので。

  4. 綾鷹 より:

    ご教示いただきました方法で設定しましたら、成功しました。
    この度はご相談にのっていただき、本当にありがとうございました。

  5. のりお より:

    こちらの記事、大変参考になっております。
    ひとつ、以前のコメントでも話題が出ておりますが「スレッド単位での検索」ではなく「メール単位での検索」ができると、もっと実用性が増すかと思います。

    https://asatte.biz/gmail-line/

    ↑他サイトのリンクになりますが、こちらでメール単位での取得について多少触れているみたいです。

    • のりさん

      コメントありがとうございます。
      厳密にいうと、Gmailの検索はスレッド単位でしかできないのですが、getMessagesForThreadsメソッドでメッセージを取り出してif文などを使って絞り込むという方法を使う方法になるかと思います。

      ご提示いただいたリンク先もおそらく同じ方法なのかなと思います。

タイトルとURLをコピーしました