Guide
Gmail API のページネーションと同期を解説
Gmail の REST API では、ページネーショントークン、履歴 ID、部分同期の状態を自分で扱う必要があります。本ガイドでは nextPageToken と historyId の仕組みを、各パターンの動作するコードとともに解説します。Gmail、Outlook、Exchange、Yahoo、iCloud、IMAP に対応。
Written by Prem Keshari Senior SRE
Reviewed by Nick Barraclough
Gmail API の nextPageToken と maxResults はどう動くのか?
Gmail API の maxResults パラメータは、users.messages.list が 1 ページで返すメッセージ ID の件数を制御し、最大値は 500 です。一致するメッセージがさらに存在する場合、レスポンスには nextPageToken が含まれます。そのトークンを次のリクエストで pageToken として渡し、レスポンスにトークンが含まれなくなるまで繰り返します。
よく検索される gmail api nextPageToken maxResults というクエリについて言えば、重要なルールは maxResults があくまでページサイズであり、結果全体の上限ではないという点です。一致するメッセージが 10,000 件あるメールボックスでは、リクエストの繰り返し、トークンの永続化、リトライ処理、さらに各メッセージ本文を取得するための messages.get 呼び出しが依然として必要です。
Gmail API のページネーションの仕組み
Gmail API のページネーションは、大きな結果セットを複数の HTTP レスポンスに分割します。各レスポンスには nextPageToken が含まれ、呼び出し側はそれを渡して次のバッチを取得します。messages.list エンドポイントは 1 リクエストあたり最大 500 件しか返さないため、10,000 通の受信トレイを最後までページングするには少なくとも 20 回の連続した API 呼び出しが必要です。
Gmail API の messages.list ドキュメントによると、各呼び出しのコストは 5 クォータユニットで、既定のページサイズは 100(maxResults で最大 500 まで設定可能)です。すべてのリクエストには有効な OAuth2 アクセストークンが必要です。以下のループは、このパターンを Python で示したものです — messages.list を繰り返し呼び出してメッセージ ID を集め、nextPageToken がなくなったら終了します:
from googleapiclient.discovery import build
service = build("gmail", "v1", credentials=creds)
all_messages = []
page_token = None
while True:
response = service.users().messages().list(
userId="me",
maxResults=500,
pageToken=page_token,
).execute()
all_messages.extend(response.get("messages", []))
page_token = response.get("nextPageToken")
if not page_token:
break
print(f"Fetched {len(all_messages)} message IDs")メッセージ ID を集めるだけで 18 行です。件名、送信者、本文を取得するには、さらに各 ID に対して messages.get を呼び出す必要があり、現行の Gmail クォータ表では 1 回あたり 20 ユニットの追加コストがかかります。
Gmail の増分同期の仕組み
Gmail の増分同期は、単調増加する historyId でメールボックスの変更を追跡し、前回の同期以降に変わったものだけを取得する仕組みです。10,000 通の受信トレイを全件再ページングすると messages.list の呼び出しだけで少なくとも 100 クォータユニットかかるため、そのオーバーヘッドを避ける手段として、新規・削除・ラベル変更されたメッセージだけを返す history.list エンドポイントが用意されています。
前回の同期時の historyId を保存しておきます。次の実行では、startHistoryId を付けて history.list を呼び出し、それ以降の変更だけを取得します。Gmail の同期ガイドは、ローカルコピーを同期し続けるための第一の方法としてこれを推奨しています。historyTypes パラメータで変更の種類を絞り込めます:messageAdded、messageDeleted、labelAdded、labelRemoved です。history.list の呼び出しコストは 1 回あたり 2 クォータユニットで、5 ユニットの messages.list より 60% 安価です。以下の Python 関数は、ページネーションされた履歴レコードをループで処理し、変更を収集して次回同期用の最新 historyId を返します:
def get_changes_since(service, start_history_id):
"""Fetch all mailbox changes since the given historyId."""
changes = []
page_token = None
while True:
response = service.users().history().list(
userId="me",
startHistoryId=start_history_id,
historyTypes=["messageAdded", "messageDeleted"],
pageToken=page_token,
).execute()
changes.extend(response.get("history", []))
page_token = response.get("nextPageToken")
if not page_token:
break
new_history_id = response.get("historyId")
return changes, new_history_idひとつ落とし穴があります:履歴 ID はおよそ 30 日で期限切れになります。保存している historyId が古すぎると、history.list は 404 Not Found(場合によっては 410 Gone)を返すため、フル同期にフォールバックする必要があります。コードは両方のパスを処理しなければなりません。
自前で実装する場合の問題点
本番品質の Gmail 同期クライアントを構築するということは、OAuth2 トークンのライフサイクル、期限切れ履歴のフォールバック、レート制限、部分的な失敗のすべてを、自分で保守するコードで扱うということです。20 行のページネーションループとして始まったものは、トークン更新コールバック、429 レスポンスへの指数バックオフ、差分同期とフル同期の二重コードパスを加えると 80〜120 行に膨らみます。エッジケースは積み上がっていきます:
- OAuth2 トークン管理 — Gmail のアクセストークンは 3,600 秒ごとに期限切れになります。同期ループは期限切れトークンを検出し、リフレッシュトークンで更新し、失敗したリクエストを再試行する必要があります。つまり、トークン更新コールバック、エラー処理、リトライロジックが必要です。
- 期限切れ historyId のフォールバック —
history.listが 404 を返したら、差分同期をあきらめてフルページネーション同期を実行する必要があります。コードパスは 2 つあり、どちらも正しく動かなければなりません。 - レート制限 — 新規の Gmail API プロジェクトには、プロジェクトごと・ユーザーごとに毎分 6,000 クォータユニットが与えられます。
messages.listの呼び出しは 5 ユニット、messages.getは 20 ユニット、history.listは 2 ユニットです。大きなメールボックスを同期するなら、クライアント側のスロットリングと429 Too Many Requestsへの指数バックオフが必要です。 - ページ途中での失敗 — ページネーションの途中でネットワークエラーが起きると、結果は半分しか手元にありません。最初からやり直すのか、最後のページトークンから再開するのか?状態の追跡が必要になります。
- Gmail API のセットアップ負担 — Gmail API を呼び出すコードを書く前に、Google Cloud プロジェクト、OAuth 同意画面、クライアント ID とシークレット、そして console.cloud.google.com で設定するリダイレクト URI が必要です。ウェブフォームをクリックして回る作業に 15〜20 分かかります。
この 5 つの課題をすべてカバーする信頼できる同期ループは、ロギング、永続化、マルチアカウント対応を加える前の時点で、Python で 80〜120 行になります。
関連する API ページネーションとメールワークフローのガイド
Gmail のページネーションは、隣接するインテグレーション作業と並んで登場することがほとんどです。Calendar のイベント同期、プロバイダー非依存の受信トレイ一覧、Webhook 配信、API クォータの計画、エージェントから安全に使えるメールアクセスなどです。より具体的な実装パスが必要なときは、この一覧表を活用してください。
| 必要なこと | 使うガイド | 内容 |
|---|---|---|
| カレンダーのページネーション | Google Calendar API のページネーション | events.list、nextPageToken、syncToken、定期イベントの同期 |
| Gmail API のセットアップなしで受信トレイを一覧表示 | コマンドラインから Gmail のメールを一覧表示 | 検索、フィルター、JSON 出力、OAuth セットアップ、ターミナルからの受信トレイ読み取り |
| 検索クエリの例 | Gmail API 検索クエリの例 | q、ラベル、カテゴリ、日付フィルター、添付ファイル、rfc822msgid |
| エージェントに安全な API の選択 | AI エージェント向けメール API の比較 | Gmail、Microsoft Graph、IMAP、プロバイダー非依存 API のエージェント向けトレードオフ |
| Gmail API の障害モード | Gmail API が AI エージェントを壊す理由 | OAuth プロンプト、ページネーション状態、クォータ圧迫、MIME 解析のリスク |
| クォータの計画 | 2026 年の Gmail API クォータ | メソッドごとのコスト、プロジェクト上限、ユーザーごとの上限、リトライ計画 |
| イベント駆動の同期 | メール Webhook をローカルでテスト | ローカル Webhook レシーバーの構築、トンネルでのテスト、サンプルペイロード、署名チェック |
1 コマンドで Gmail のメールを一覧表示
Nylas CLI は、OAuth2 トークンの更新、レート制限、複数ページの取得を内部で処理する 1 つのターミナルコマンドで、ページネーションと同期のスタック全体を置き換えます。Gmail API のアプローチでは 80〜120 行の Python と Google Cloud での 15〜20 分の Gmail API セットアップが必要なところ、CLI なら 1 行と 2 分のインストールで済みます。
次の 3 つのコマンドはよくあるパターンを示しています:最近のメッセージの一覧、件名での絞り込み、送信者での絞り込みです。それぞれは内部で単一の API 呼び出しとして実行され、プロバイダーのレスポンスをまたぐページネーションは CLI が管理します:
# List the 50 most recent emails
nylas email list --limit 50 --json# Filter by subject
nylas email search "invoice" --json# Filter by sender
nylas email list --from "boss@company.com" --jsonCLI は裏側で Gmail API をページングし、期限切れの OAuth2 トークンを自動で更新し、結果を JSON で返します。登録する Gmail API プロジェクトも、同意画面も、リダイレクト URI も不要です。CLI を初めて使う場合は、スタートガイドでインストールと初回認証を解説しています。
検索とフィルター
Nylas CLI は、messages.list が使うのと同じ Gmail の q パラメータに対応する全文検索とフィールド単位のフィルターを、ページネーションループや OAuth2 の配線なしでサポートします。Gmail の API では検索・ページング・本文取得に少なくとも 3 回の連続した API 呼び出しが必要ですが、CLI はそれを 1 コマンドにまとめます。
以下の 3 つの例は、最もよく使う検索パターンをカバーします:キーワード検索、未読の絞り込み、日付範囲の絞り込みです。日付フィルターは nylas email search の --after と --before で指定し、YYYY-MM-DD 形式の日付を取り、すべてに一致するクエリとして "*" を受け付けます。各例は件名・送信者・本文を含む完全なメッセージ JSON を返します:
# Full-text search
nylas email search "quarterly report" --json# Unread emails only
nylas email list --unread --json# Emails received in the last 7 days
nylas email search "*" --after 2026-06-02 --jsonGmail API で同等のことをするには、クエリ文字列を組み立てて messages.list に渡し、nextPageToken で結果をページングし、返ってきた各メッセージ ID に messages.get を呼び出して件名と本文を取得します。4 ステップ、1 ページあたり最低 10 クォータユニットです。
ID だけでなくメッセージの中身を読む
Gmail API の messages.list エンドポイントが返すのはメッセージ ID だけで、件名・送信者・本文は決して返しません。実際の内容を読むには、集めたすべての ID に対して messages.get を呼び出すことになり、1 回ごとに 20 クォータユニットの追加コストがかかります。10,000 通をページングした後にはさらに 10,000 回の API 呼び出しが発生し、合計 200,000 クォータユニット — 2026 年のユーザーごとプロジェクト上限では、ユーザー 1 人あたり 33 分超に相当するクォータを消費します。
CLI はこの 2 ステップを 1 コマンドにまとめます。nylas email read <id> は本文を含むメッセージを 1 回の呼び出しで取得します。nylas email search はサーバーサイドのクエリを実行し、一致したメッセージを内容ごと同じレスポンスで返します。どちらもグローバルな --format フラグで 3 つの出力モード — table、json、yaml — に対応し、--json は JSON モードの省略形です。messages.get が format=raw で返す生の RFC822 ソースが必要なら、nylas email read に --mime を渡してください。JSON 出力はそのまま jq にパイプでき、後続のシェル処理に使えます。
# Read a single message
nylas email read 18b9a3f2cd47e102 --json
# Search and return full bodies in one round-trip
nylas email search "urgent" --from boss@example.com --jsonメッセージではなくスレッドをページングする
Gmail はメッセージを会話スレッドにまとめており、threads.list エンドポイントは messages.list とは別のページネーション対象リソースです。10,000 通の受信トレイは、会話の密度にもよりますが通常 2,000〜4,000 スレッドに収まるため、スレッド単位の一覧は総ページ数を 60〜80% 削減します。各スレッドレスポンスは messages.list と同じ nextPageToken の契約に従い、加えて会話内の全メッセージを含む threads[].messages[] 配列を持ちます。
CLI のスレッド系コマンドは、メッセージ系と対をなす 5 つのコマンドで構成されます。nylas email threads list はスレッドをページングします。nylas email threads show は ID で単一スレッドを取得します。nylas email threads search は Gmail 形式のクエリ文字列を取ります。nylas email threads mark はスレッド内の全メッセージの既読状態を一度に変更します。nylas email threads delete は会話全体を削除します。
# Paginate threads in pages of 50
nylas email threads list --limit 50 --json
# Mark a whole conversation as read in one command
nylas email threads mark <thread-id> --read特定のラベルやフォルダー内でページングする
Gmail はメッセージをラベルで整理します — INBOX、SENT、STARRED、UNREAD、SPAM、TRASH といったシステムラベルに加え、ユーザーが作成したラベルです。Microsoft Graph と IMAP のプロバイダーは代わりにフォルダーを使います。Gmail の messages.list エンドポイントは、システムラベル用の labelIds 配列、またはカスタムラベル用に label:Receipts のような検索構文を使う q パラメータを受け付けます。ページネーショントークンはフィルターのスコープを保持するため、1 つのラベルに絞った 50,000 通のアーカイブは、それに比例して少ないページ数を返します。
nylas email search は --in でクエリを 1 つのラベルまたはフォルダーに絞れます — その中の全メッセージに一致させるにはクエリとして "*" を渡します。nylas email folders list は接続済みアカウントのすべてのラベルまたはフォルダーを返すため、同じフラグが Gmail のラベル、Outlook のフォルダー、IMAP のフォルダー名に対して構文を変えずに機能します。検索コマンドのフラグには --unread、--starred、--has-attachment もあります。
# List every label or folder on the connected account
nylas email folders list --json
# Paginate only inside the Receipts label
nylas email search "*" --in Receipts --limit 100 --json
# Combine label scope with a query
nylas email search "stripe" --in Receipts --json複数アカウントをまたいでページングする
本番の同期クライアントは、複数の接続済みメールボックスを扱うことが少なくありません — 4 つの共有受信トレイを集約する営業オペレーション、5 つのユーザーアカウントを操作する AI エージェント、ワークスペース内の全アカウントからメールシグナルを収集する CRM などです。Gmail API のクォータは OAuth グラント単位で適用されるため、10 アカウントの並列同期はアカウント間のスロットリングなしで動きますが、アプリケーションコードは 10 個のリフレッシュトークン、10 個のトークン期限タイマー、10 個の historyId チェックポイントを管理しなければなりません。
CLI ではグラントが第一級の概念です。nylas auth list は接続済みアカウントをすべて表示します。nylas auth whoami は次のコマンドが使うグラントを表示します。nylas auth switch はアクティブなグラントを切り替えます。メールとカレンダーのコマンドはグラント ID を省略可能な位置引数として受け取るため、アクティブ状態を切り替えずに 1 つのシェルスクリプトでグラントを順に処理できます。
# Show every connected grant as JSON
nylas auth list --json
# Run the same sync across every Google grant
for grant in $(nylas auth list --json | jq -r '.[] | select(.provider == "google") | .id'); do
nylas email search "*" "$grant" --after 2026-05-01 --json
doneCI・cron ジョブ・ヘッドレス環境での同期
Gmail API の OAuth2 ブラウザポップアップは、CI、Docker コンテナ、AI エージェントのサンドボックスをはじめとする無人環境では決定的なブロッカーです。Google のオフラインアクセスフローでは、一度きりの対話的セットアップ中にアプリケーションがリフレッシュトークンを取得し、シークレットマネージャーに保管してプログラムで更新し続ける必要があります。推奨される代替手段(ドメイン全体の委任を持つサービスアカウント)は Google Workspace の管理者に限定され、ワークスペースレベルの設定変更が必要です。
Nylas CLI は API キー認証でブラウザを完全に回避します。nylas auth config --api-key はブラウザに触れずにキーをローカルに保存します。nylas auth token は後続の API 呼び出し用にスコープ付きベアラートークンを生成します。nylas auth status は現在の認証状態を報告します — コンテナ化されたデプロイのヘルスチェックに便利です。
# In a GitHub Action or cron job — no browser needed
export NYLAS_API_KEY="nyk_..."
nylas auth config --api-key "$NYLAS_API_KEY"
nylas email search "*" --after $(date -u -v-1d +%Y-%m-%d) --json > /var/log/digest.jsonブラウザのない Manus や Replit などの AI エージェントサンドボックスでも同じフローが使えます — エージェントが一度キーをプロビジョニングして環境に保存すれば、以降のすべてのコマンドは対話的なステップなしで実行されます。
ポーリングの代わりに Webhook を使う
Gmail の受信トレイを 5 分ごとにポーリングすると、受信トレイ 1 つあたり 1 日 288 回の API 呼び出しが発生します。接続ユーザーが 1,000 人なら毎日 288,000 回で、その大半は新着メッセージゼロを返します。Gmail には Cloud Pub/Sub によるプッシュ通知という選択肢があります:Pub/Sub トピックを作成し、gmail-api-push@system.gserviceaccount.com に pubsub.publisher ロールを付与し、各メールボックスで users.watch を呼び出し、Google が失効させるため 7 日ごとに watch を更新します。セットアップコストは高く、更新を 1 回逃すと同期は静かに壊れます。
CLI の Webhook は Pub/Sub トピックなしで動きます。nylas webhook create は HTTPS エンドポイントとトリガーのリストを登録します。nylas webhook list は登録済みの内容を表示します。nylas webhook triggers はサポートされる全イベントタイプ(message.created、message.updated、thread.replied、加えてカレンダーと連絡先のイベント)を出力します。nylas webhook test send はサンプルペイロードをエンドポイントに送信し、本番投入前にレシーバーを検証できます。nylas webhook verify は受信ペイロードの HMAC 署名を検証します。
# Register a webhook for new message events
nylas webhook create \
--url https://example.com/hooks/nylas \
--triggers message.created \
--json
# Verify a payload from your receiver
nylas webhook verify \
--payload-file ./incoming.json \
--signature "$X_NYLAS_SIGNATURE" \
--secret "$WEBHOOK_SECRET"Webhook は実際のイベントでのみ発火し、平均的なユーザーなら受信トレイ 1 つあたり 1 日 100 件未満です。1 日 288,000 回のポーリング負荷は、同じ 1,000 個の受信トレイでおよそ 1 日 100,000 イベントに縮小し、新着メッセージの到着からアプリケーションが検知するまでのレイテンシは最大 5 分からおよそ 1 秒に短縮されます。
他のメールプロバイダーはページネーションをどう扱うか
理解しておく価値のあるページネーション契約を持つのは Gmail だけではありません。Microsoft Graph(Outlook と Exchange Online)は @odata.nextLink — クライアントがそのまま辿る完全な URL — を使います。IMAP(Yahoo Mail、iCloud Mail、ホスティング IMAP)は従来の意味でのページネーションを行いません:UID SEARCH は一致する全 UID を 1 レスポンスで返すため、大きなメールボックスでは遅くなり得ますが、クライアント側のカーソルロジックは不要になります。Exchange Web Services(EWS、旧来の Exchange デプロイで使用)は IndexedPageItemView と BasePoint オフセットによるインデックスページングを使います。
| プロバイダー | ページネーション方式 | カーソルの種類 | 最大ページサイズ |
|---|---|---|---|
| Gmail API | nextPageToken | 不透明な文字列 | 500 |
| Microsoft Graph | @odata.nextLink | 完全な URL | 1,000 |
| IMAP(Yahoo、iCloud、ホスティング) | UID SEARCH + 範囲フェッチ | シーケンス番号 | ページ上限なし |
| EWS(レガシー Exchange) | IndexedPageItemView | 数値オフセット | 1,000 |
プロバイダーごとのガイドでは、同じページネーション問題をそれぞれの契約に沿って解説しています:コマンドラインから Outlook のメールを一覧表示、Exchange のメールを一覧表示、Yahoo のメールを一覧表示、iCloud のメールを一覧表示、IMAP のメールを一覧表示。同じ nylas email list コマンドが、すべてのプロバイダーに対して同一のフラグで動作するとドキュメント化されています。
上記の Outlook、Exchange、Yahoo、iCloud、IMAP のプロバイダー側の挙動は、各プロバイダーの公開ドキュメントに基づくもので、すべてのバックエンドでエンドツーエンドの実行検証を行ったものではありません。プロバイダー固有のワークフローをデプロイする前に、ローカルでテストしてください。
Gmail 受信トレイの同期にかかる時間は?
テスト用メールボックスに対する合成ベンチマーク(Google サーバーへの中央値レイテンシ約 150 ms の家庭用ブロードバンド回線で実施)は、手動ページネーションと単一の CLI コマンドのコスト差を示しています。Python ループの列には、429 レスポンスへの指数バックオフ付きの messages.list + messages.get 呼び出しが含まれます。CLI の数値には、同じ内部呼び出しをバッチ化・並列化したものが含まれます。
| 受信トレイのサイズ | Python messages.list + messages.get | Nylas CLI | Gmail クォータコスト |
|---|---|---|---|
| 1,000 通 | 約 12 秒 | 約 3 秒 | 約 6,000 ユニット |
| 10,000 通 | 約 2 分 | 約 30 秒 | 約 60,000 ユニット |
| 50,000 通 | 約 12 分(バックオフ込み) | 約 3 分 | 約 300,000 ユニット |
| 100,000 通 | 約 25 分(バックオフ込み) | 約 6 分 | 約 600,000 ユニット |
クォータコストは Gmail の呼び出し単価で決まるもので、クライアント側では変えられません。CLI が messages.list の呼び出しを安くすることはできませんが、ページネーションとリトライの挙動をアプリケーションコードの外に出すことはできます。素朴な Python ループで 10,000 件の本文を全件取得すると、messages.get の呼び出しだけで約 200,000 クォータユニットを消費します。新規のフル同期を計画する際にはこれらの数値の把握が重要です。バッチ処理と並列度を制御するフラグは nylas email list を参照してください。
よく使うレシピ
メールのページネーションを標準的な UNIX ツールと組み合わせた 4 つのシェルパターンです。いずれも JSON 出力の解析に jq を、機械可読なフォーマットに --json を使います。
未読メールをすべて数える
nylas email list --unread --json を jq 'length' にパイプすると、数値が 1 つ得られます。スクリプト化したダッシュボードやオンコールのアラートに便利です。watch -n 60 と組み合わせれば、1 分ごとに更新されるライブカウンターになります。JSON 出力のページネーションは自動なので、ラッパー側で nextPageToken を扱う必要はありません。
nylas email list --unread --json | jq 'length'日次ダイジェストの cron ジョブ
cron で 1 日 1 回実行するダイジェストスクリプトは、nylas email search の --after に昨日の日付を指定し、JSON を一時ファイルに書き出して、メッセージごとの 1 行サマリーを mail にパイプします。cron を実行するマシンでは nylas auth login を nylas auth config --api-key に置き換えれば、ブラウザは不要です。
# /etc/cron.daily/email-digest.sh
yesterday=$(date -u -v-1d +%Y-%m-%d)
nylas email search "*" --after "$yesterday" --json > /tmp/digest.json
jq -r '.[] | "\(.from) - \(.subject)"' /tmp/digest.json \
| mail -s "Daily digest" you@example.com特定の送信者からの添付ファイル付きメールをすべて見つける
nylas email search と nylas email attachments list を連結すると、1 つのパイプラインで特定の送信者からのすべての添付ファイルを見つけられます。email search は --from と --has-attachment のフィルターをサーバーサイドで適用し、続いて attachments list が各一致を列挙します。ファイルをディスクに保存したいときは nylas email attachments download にパイプしてください。
nylas email search "*" --from billing@stripe.com --has-attachment --json \
| jq -r '.[].id' \
| xargs -I{} nylas email attachments list {} --json最近のログインメールから OTP コードを自動抽出する
昨日以降に受信したログイン関連のメールをすべて取得し、本文から 6 桁の数字を抽出して、最初の一致を出力します。キーワードクエリ verification は最も一般的なトランザクションメールの件名を捉えます。他の送信者をカバーするには OTP や code で再実行してください。これを単体で発展させたものが専用の OTP 抽出ガイドです。単純なカウントを超える受信トレイ分析には nylas email ai analyze を参照してください。PowerShell ユーザーは PowerShell メールレポートでこれらのパターンを応用できます。
nylas email search "verification" \
--after "$(date -u -v-1d +%Y-%m-%d)" \
--json \
| jq -r '.[].body' \
| grep -oE '[0-9]{6}' \
| head -1並べて比較
以下の表は、本番で重要になる 9 つの観点で Gmail API の Python アプローチと Nylas CLI を比較したものです。最大の違いはセットアップ時間です:Gmail API の道筋ではコンソール設定に 15〜20 分と 80〜120 行のコードが必要ですが、CLI はインストールと認証で 2 分ほどです。
| 観点 | Gmail API(Python) | Nylas CLI |
|---|---|---|
| ページネーション | 手動の nextPageToken ループ | 内部で処理 |
| 増分同期 | history.list + historyId の追跡 | 内部で処理 |
| 認証 | GCP プロジェクト + OAuth 同意画面 + トークン更新 | nylas auth login(1 回のみ) |
| トークンの期限切れ | 3,600 秒 — コールバックでの手動更新 | 自動更新 |
| レート制限 | 新規プロジェクトは 6,000 ユニット/分/ユーザー/プロジェクト — 手動スロットリング + バックオフ | 内部で管理 |
| エラー復旧 | 404、410、429、トークンエラーを処理 | リトライロジック内蔵 |
| 検索 | q パラメータ + ページネーションループ | nylas email search "query" |
| セットアップ時間 | 15〜20 分(GCP コンソール)+ 80〜120 行のコード | 2 分のインストール + 認証 |
| マルチプロバイダー | Gmail のみ | Gmail、Outlook、Exchange、Yahoo、iCloud、IMAP |
よくある質問
Gmail API の nextPageToken とは?
messages.list を呼び出すと、Gmail API は 1 ページあたり最大 500 件の結果を返します。さらにメッセージが存在する場合、レスポンスには nextPageToken 文字列が含まれます。そのトークンを次のリクエストの pageToken パラメータとして渡すと、続きのページを取得できます。レスポンスに nextPageToken が含まれなくなるまでループを続ければ、終端に到達したことになります。
Gmail の増分同期は historyId でどう動くのか?
Gmail メールボックスのあらゆる変更(新着メッセージ、削除、ラベル変更)には、単調増加する historyId が付きます。前回の同期時の historyId を保存しておき、startHistoryId を付けて history.list を呼び出せば、それ以降の変更だけを取得できます。履歴 ID はおよそ 30 日で期限切れになります。保存した ID が古すぎると API は 404 を返すため、フル同期へのフォールバックが必要です。
Gmail API をセットアップせずに Gmail のメールを一覧表示できる?
はい。Nylas CLI は OAuth2 とプロバイダー認証を内部で処理します。nylas email list --limit 50 --json を実行すれば、Google Cloud での Gmail API クライアント登録、OAuth 同意画面の設定、アクセストークンの管理なしで Gmail の受信トレイを一覧表示できます。CLI は 6 つのプロバイダーで同じように動きます。
CLI は Gmail API のレート制限を処理してくれる?
はい。Gmail API は新規プロジェクトにプロジェクトごと・ユーザーごとに毎分 6,000 クォータユニットを与え、messages.list の呼び出しは 5 ユニットです。CLI はレート制限、ページネーション、トークン更新、リトライロジックを内部で管理します。クォータ追跡やバックオフのコードを一切書かずに結果が得られます。
メッセージではなく Gmail のスレッドをページングできる?
はい。nylas email threads list は messages.list の代わりに threads.list エンドポイントをページングします。一般的なメールボックスではメッセージ 3〜4 件につきスレッドはおよそ 1 件なので、ページ数は 60〜80% 少なくなります。nylas email threads mark と組み合わせれば、会話内の全メッセージを 1 コマンドで既読にできます。
特定の Gmail ラベルのメールだけを一覧表示するには?
nylas email search の --in にラベル名を渡します。nylas email search "*" --in Receipts --json というコマンドは、Receipts ラベルの付いたメッセージだけを返します。アカウント上のすべてのラベルまたはフォルダーを確認するには nylas email folders list を使います。同じフラグが Outlook のフォルダー、Yahoo の IMAP フォルダー、iCloud のフォルダーに対して構文を変えずに機能します。
OAuth のポップアップなしで cron ジョブから Gmail を同期できる?
はい。nylas auth login の代わりに nylas auth config --api-key を使います。API キーのフローはブラウザを開かないため、ヘッドレスなマシン、Docker コンテナ、CI パイプライン、Manus のような AI エージェントサンドボックスでも動きます。キーは cron ジョブを実行する環境のシークレットとして保管してください。
直近 24 時間のメールだけを同期するには?
nylas email search に --after を渡します。直近 24 時間なら:nylas email search "*" --after $(date -u -v-1d +%Y-%m-%d) --json。このフラグは YYYY-MM-DD 形式の日付を取り、CLI がそれを基盤プロバイダーのフィルター構文に変換します — Gmail の場合は API に対する q=after: クエリになります。
CLI は Outlook、Yahoo、iCloud でも同じように動く?
はい。同じ nylas email list、nylas email search、nylas email read コマンドが、Gmail、Outlook、Exchange、Yahoo、iCloud、IMAP で動作します。このツールは各コマンドをプロバイダー固有の API 呼び出し — Gmail の REST API、Microsoft Graph、IMAP の UID SEARCH、EWS — に変換します。プロバイダーごとの解説は Outlook のメールを一覧表示、IMAP のメールを一覧表示、Exchange のメールを一覧表示にあります。
historyId が 30 日より古いとどうなる?
Gmail は history.list から 404 を返すため、フルページネーション同期にフォールバックしなければなりません。CLI はこのフォールバックを自動で処理します — 404 を目にすることも、2 つのコードパスを書く必要もありません。ETag ベースの同時実行制御と If-Match の扱いは Gmail API の If-Match と ETag の扱いで解説しています。
ポーリングの代わりにプッシュ通知を受け取れる?
はい。nylas webhook create は、Cloud Pub/Sub トピックも Google Workspace 管理者も必要とせずに、message.created や thread.replied といったイベント用の HTTPS エンドポイントを登録します。サポートされる全イベントタイプは nylas webhook triggers で確認できます。
次のステップ
Gmail のページネーションと増分同期は、API インテグレーションで最もよくある課題のうちの 2 つですが、課題はそれだけではありません。以下の関連ガイドは、メール送信、ETag ベースの同時実行制御、CLI コマンドの全体像など、隣接するワークフローをカバーしています。
- コマンドラインから Gmail のメールを一覧表示 — 送信者、件名、日付、既読状態で絞り込む
- コマンドラインから Gmail を送信 — Gmail API クライアントコードや SMTP 設定なしの Gmail 専用送信
- Gmail API 検索クエリの例 —
q、ラベル、カテゴリ、添付ファイル、CLI での同等コマンド - historyId と ETag による Gmail API の増分同期 — ETag、If-Match、412 処理の詳細解説
- 2026 年の Gmail API クォータ — 現行のクォータユニット、メソッドごとのコスト、課金しきい値、エージェントに安全なパターン
- Gmail API が AI エージェントを壊す理由 — OAuth プロンプト、ページネーション状態、MIME 解析、クォータ圧迫
- AI エージェント向けメール API の比較 — Gmail、Microsoft Graph、IMAP、プロバイダー非依存 API のトレードオフ
- Google Calendar API のページネーションと同期 — 同じパターンを
events.listとsyncTokenに適用 - メール Webhook をローカルでテスト — ポーリングループを置き換える前にイベント駆動の同期を検証
- コマンドラインから Outlook のメールを一覧表示 —
@odata.nextLinkによる Microsoft Graph のページネーション - コマンドラインから IMAP のメールを一覧表示 —
UID SEARCHによる Yahoo、iCloud、ホスティング IMAP - ターミナルからメールを送信 — bash、zsh、クロスプラットフォームの送信ワークフロー
- メールから OTP コードを抽出 — スクリプトで認証コードの取得を自動化
- PowerShell メールレポート — 同じページネーションパターンを Windows シェル向けに応用
- スタートガイド — インストール方法(Homebrew、シェルスクリプト、PowerShell、Go)と初回認証
- 完全なコマンドリファレンス — すべてのフラグとサブコマンドを網羅