MENU

GASでGmail検索を小分けに取得する

当ページのリンクには広告(PR)が含まれていることがあります。
GASでGmail検索を小分けに取得する。多くのメール、検索を小分けに、対象の変化を確認の処理例。

Gmailを検索するGASで結果を一度に取得して止まる場合は、検索件数を小さく区切ります。GmailApp.search(query, start, max)を使うと、取得を始める位置と、1回に返してほしい件数を指定できます。

ただし、返されるのはメール1通ずつではなくスレッドです。返信を含む1つのまとまりが1件なので、スレッド数をそのままメールの通数にしないようにします。検索中に結果が増減する場合もあるため、小分け取得だけで漏れのない一覧が保証されるわけではありません。

目次

startは開始するスレッドの位置

公式のGmailAppでは、startは開始スレッドの位置、maxは返すスレッドの最大数です。最初は0から始めます。次の位置は取得した件数を足して進めます。

練習では少数のメールへ「練習対象」というラベルを付けた状態を使います。サンプルの検索語はlabel:練習対象です。件名や本文をログへ出さず、スレッドIDの一覧と重複数だけを返します。IDも共有が必要な人だけが見られるログで扱ってください。

ラベルを付け替えながら同じ検索結果を取得すると、位置がずれやすくなります。この例は読み取りだけにし、検索結果を見ながら既読化・移動・ラベル変更を行う処理は加えません。

最大回数を決めた読み取りコード

次の関数は同じIDが再び現れたら重複として数え、結果へ二重に入れません。最大回数へ達した場合は、続きがあるか不明だという印も返します。

function readThreadPages(search, query, pageSize, pageLimit) {
  if (!Number.isSafeInteger(pageSize) || pageSize < 1 || pageSize > 100 ||
      !Number.isSafeInteger(pageLimit) || pageLimit < 1 || pageLimit > 10) {
    throw new Error('1回の件数と回数を確認してください');
  }
  const seen = new Set();
  const threadIds = [];
  let start = 0;
  let duplicates = 0;
  for (let page = 0; page < pageLimit; page++) {
    const threads = search(query, start, pageSize);
    threads.forEach(function (thread) {
      const id = thread.getId();
      if (seen.has(id)) duplicates++;
      else { seen.add(id); threadIds.push(id); }
    });
    start += threads.length;
    if (threads.length < pageSize) {
      return {threadIds: threadIds, duplicates: duplicates, nextStart: start, moreUnknown: false};
    }
  }
  return {threadIds: threadIds, duplicates: duplicates, nextStart: start, moreUnknown: true};
}

function previewGmailPages() {
  const result = readThreadPages(
    (query, start, max) => GmailApp.search(query, start, max),
    'label:練習対象', 2, 3
  );
  console.log(JSON.stringify(result));
}

1ページ目がT1・T2、2ページ目がT2・T3、3ページ目が空なら、架空の結果はT1・T2・T3の3件、重複数1です。nextStartは取得件数の合計4になります。これは実際のGmailのIDではなく、分岐を確かめる入力例です。

重複がなくても漏れは残り得る

同じ検索語でも、新着メールや削除などで結果の並びや件数が変わると、位置での取得は安定した一覧の写しにはなりません。重複IDを除けたからと、すべての対象を取得できたとは判断しないでください。

対象期間やラベルを事前に決め、検索中の状態変更を減らすと、確認しやすくなります。網羅性が必要なら、対象IDの記録と再照合を別に用意します。moreUnknown:falseも、その時点の取得が指定件数より少なかったという意味で、以後の新着を含めないことを保証する値ではありません。

スレッド内の各メールを使う場合は、GmailThreadのgetMessagesで取り出す段階を分けます。返信まで対象なのか、条件に合うメールだけなのかを改めて決める必要があります。

小分けでも読み過ぎない

ページ数を増やすだけでは、GASの実行時間やGmailの利用制限は解決しません。1回の対象を絞り、次にどこから確認するかを残します。保存した位置は検索結果の変化で意味が変わるため、それだけを再開の根拠にしないようにします。

ローカルでは代用検索で、開始位置、重複、空結果、上限停止、引数不備を確認しました。Gmailへの検索・状態変更・送信は実行していません。Gmail通知の基本と読み取りの機能を分け、失敗は実行履歴とログで確認できる形にします。

この記事を書いた人

Watanabeのアバター Watanabe サイト運営者

2020年よりブログ開始。
SEOが思いのほか性にあっていたようで現在に至る。
モットーは「勝率の高い選択をする」
AIは活用するが吉、最後は人間が息を吹き込む。
アートと科学を追求し、日々精進。
―――
収益:6~7桁をウゴウゴ。
サイト:ペラサイト~中規模サイトまで運営中。
案件:1000円以上の案件をメインに取組中。
打ち手:ブラックSEO~ホワイトSEOまで
―――

目次