GASとGemini APIでGmail要約を自動化 メール確認を1日30分短縮するレシピ
朝いちばんの 30 分が、メールを「開いて閉じる」だけで消えていませんか。本レシピは Google Apps Script (以下 GAS) から Google の Gemini API を呼び、前日届いたメールを 1 通 60 字に要約して 1 通のダイジェストにまとめます。Gmail も Gemini も同じ Google なので、追加のアカウント登録は不要です。
- 前日のメールを 1 通 60 字の要約 + 「要対応かどうか」に変換し、朝 7 時に 1 通だけ届く形にする
- Gemini API には 無料枠がある。有料に切り替えても編集部試算で月 30 通 × 30 日 = 約 ¥210
- ただし無料枠は入力内容が Google の製品改善に使われる。取引先の機微情報を流すなら課金必須
- モデルには提供終了日が設定されている。本稿は終了予定が公表されていない現行モデルを既定にし、確認先も示します
- OpenAI 版レシピとの違いは 6 点だけ。エンドポイント・認証ヘッダー・本文の形・応答の取り出し方・出力上限の指定・無料枠の有無
- コードはコピーして設定 4 行を書き換えるだけで動く実物です
編集長の見解: メール処理の自動化というと「返信の自動生成」に目が行きますが、そこは事故のリスクが高く、経営者が最初に手を付ける場所ではありません。効果が大きくて安全なのは 「読むかどうかを決める前段」 です。1 日 30 通のうち、本当にその日のうちに判断が要るのは数通です。残りを開かずに済ませられれば、それだけで朝の 30 分が戻ります。Gemini API を選ぶ理由は 3 つ、無料枠があること、Gmail と同じ Google アカウントで完結すること、そして要約という軽い用途なら最安クラスの小型モデルで十分だからです。一点だけ注意があります。Gemini のモデルには提供終了日が設定されており、単純に「一番安いもの」を選ぶと数か月で動かなくなります。本稿は終了日が公表されていないモデルを既定にしたうえで、後述の表に各モデルの終了日を明記しています。単価が数円安いことより、朝のダイジェストが黙って止まらないことのほうが大事です。
朝のメール確認に消えている時間の正体
取引先メールが 1 日 20〜50 通届く事業者に共通する詰まりを分解します。
- 開かないと判断できない: 件名だけでは「今日中の対応が要るか」が分からず、結局すべて開く
- 1 通あたりの判断が短い: 開いて 20〜60 秒読んで閉じる、が大半を占める
- 見落としが怖くて全部読む: 1 通の見落としが失注や納期遅れに直結するため、削れない
- スマホで二度読みする: 移動中に読み、会社でもう一度開く重複が発生する
- 担当者に共有できない: 「今日の要対応」を一覧で渡す手段がなく、口頭伝達になる
このうち 1 から 4 は「読む前に要点が分かっていれば消える」時間です。次のセクションで、完成する仕組みの全体像を示します。
完成形 (フロー図)
1日1回、時刻を指定した自動実行の仕掛け (トリガー) でGASが起動し、前日分のスレッドだけをまとめて処理する
処理の骨格は GAS × OpenAI API の要約レシピ と同じですが、呼び出し先が変わると書き換えが必要な箇所が出ます。次のセクションで、その差分だけを表にまとめます。
OpenAI API 版から書き換わるのは 6 か所だけ
すでに OpenAI 版を動かしている方は、以下の 6 行だけ直せば移行できます。逆に言うと、それ以外は共通です。
| 項目 | OpenAI API 版 | Gemini API 版 |
|---|---|---|
| エンドポイント | /v1/chat/completions | /v1beta/models/モデル名:generateContent |
| 認証の渡し方 | Authorization: Bearer キー | x-goog-api-key: キー |
| 入力の入れ物 | messages 配列 | contents 配列の中の parts |
| 応答の取り出し | choices[0].message.content | candidates[0].content.parts[0].text |
| 出力上限の指定 | max_tokens | generationConfig.maxOutputTokens |
| 無料枠 | なし (最初から従量課金) | あり (ただし後述の条件つき) |
とくに 4 行目は事故が起きやすい箇所です。Gemini は安全フィルタや出力上限に当たったとき、candidates[0].content.parts そのものが返ってこないことがあります。OpenAI の感覚で parts[0].text を直接読むと、そこで実行が止まります。後述のコードでは必ず存在チェックを挟んでいます。
⚠️ 失敗パターン 1: 応答が空のときに落ちる
candidates[0].content.parts は、出力が上限に達した場合 (finishReason が MAX_TOKENS) や安全フィルタに触れた場合に存在しません。存在チェックなしで書くと「30 通のうち 12 通目で止まり、以降が処理されない」という止まり方をします。しかも GAS のトリガー実行はエラーがメールで届くだけなので、気づくまでに数日かかります。
次は、そのモデルをどれにするか、いくらかかるかの話です。
使うモデルと費用 — 要約なら小型モデルで足りる
Gemini API には複数のモデルがあり、要約という用途では最上位モデルは不要です。2026 年 8 月時点の公式料金表を、提供終了日と本レシピ視点の評価つきで並べます。単価は「100 万トークンあたりの米ドル」です (トークンは AI が文章を数える単位で、日本語ではおおむね 1 文字が 1 トークン前後と考えてください)。
| モデル ID | 入力 | 出力 | 無料枠 | 提供終了日 | 本レシピでの編集部評価 |
|---|---|---|---|---|---|
gemini-3.5-flash-lite | $0.30 | $2.50 | あり | 公表なし | ◎ 要約・仕分けの第一候補。本稿の既定 |
gemini-3.1-flash-lite | $0.25 | $1.50 | あり | 2027-05-07 | ○ 単価は安いが 1 年弱で終了。移行前提なら可 |
gemini-2.5-flash-lite | $0.10 | $0.40 | あり | 2026-10-16 | ✕ 最安だが数か月後に終了。新規採用は避ける |
gemini-2.5-flash | $0.30 | $2.50 | あり | 2026-10-16 | ✕ 同上。既存利用者は移行が必要 |
単価だけを見れば gemini-2.5-flash-lite の $0.10 が最安ですが、公式の提供終了ページはこのモデルに 2026 年 10 月 16 日という終了日を掲示しています。同じ表で gemini-3.1-flash-lite にも 2027 年 5 月 7 日の終了日が付いている点にも注意してください。単価が最安のものと、2 番目に安いものが、どちらも期限付きです。
本稿が既定に選んだのは、Flash-Lite 系で唯一まだ終了日が公表されていない gemini-3.5-flash-lite です。数か月後に朝のダイジェストが黙って止まる仕組みを作る意味はありません。なお公式の提供終了ページは gemini-2.5-flash-lite からの移行先として gemini-3.1-flash-lite を、その gemini-3.1-flash-lite からの移行先として gemini-3.5-flash-lite を案内しています。二段跳びせず、最初から gemini-3.5-flash-lite に置くのが結局いちばん手間がかかりません。
⚠️ 失敗パターン 2: 単価が最安のモデルを選んで数か月後に止まる
Gemini のモデルには提供終了日が設定されます。終了後は同じコードが 404 を返し始めますが、本レシピはトリガーによる自動実行なので画面に何も出ず、ダイジェストが届かなくなるだけです。導入時と、その後は半年に一度、提供終了予定のページで自分が指定したモデル ID を検索してください。同ページには移行先のモデル ID も併記されており、移行は設定 1 行の書き換えで済みます。
有料枠に切り替えた場合の費用を、編集部のシミュレーションで見積もります。1 日 30 通、本文は先頭 4,000 字までを送り、既定の gemini-3.5-flash-lite を使う想定です。
| 項目 | 計算 | 月額の目安 |
|---|---|---|
| 入力トークン | 900 通 × 平均 約 3,000 トークン (上限 4,000 字) = 約 270 万トークン | 約 $0.81 |
| 出力トークン (思考分を含む) | 900 通 × 約 250 トークン = 約 22.5 万トークン | 約 $0.56 |
| Google Apps Script | 実行・トリガーとも無料 | ¥0 |
| 合計 | — | 約 $1.37 (¥155/$ 換算で約 ¥212) |
出力の行に「思考分を含む」と書いたのには理由があります。gemini-3.5-flash-lite は答えを出す前に内部で考える動作が既定で有効になっており、公式料金ページはこの思考トークンも出力トークンと合算して課金されると説明しています。後述のコードでは思考の量を最小に指定していますが、費用を見積もるときは要約本体より多めに見ておくのが安全です。
⚠️ 失敗パターン 3: 無料枠のままで業務メールを流す
Gemini API の公式料金ページは、無料枠について入力・出力とも無償である一方で、送った内容が Google の製品改善に利用される と明記しています。有料枠では利用されません。取引先名・見積金額・個人情報を含む業務メールを扱うなら、上表の月 ¥200 強を惜しまず課金を有効にしてから運用に乗せてください。テストは無料枠、本番は有料枠、という切り分けが現実的です。
💡 コスト圧縮のヒント: 本文を丸ごと送る必要はありません。後述のコードでは先頭 4,000 字で切っています。署名・引用返信・免責文が長いメールほど、この上限が効きます。3,000 字まで下げても要約の質はほとんど落ちません。
無料枠の 1 分あたり・1 日あたりのリクエスト上限 (RPM / RPD) は、公式ドキュメントが「Google AI Studio のレート上限ページで確認する」案内に切り替わっています。自分のプロジェクトの実数値は レート上限のドキュメント から AI Studio に進んで確認してください。ここまでで前提が揃ったので、実際の設定手順に進みます。
設定手順 (45 分)
手順の中で唯一つまずきやすいのが STEP 5 の権限承認です。個人の Google アカウントでは「このアプリは確認されていません」という警告が出ますが、自分で書いたスクリプトなので「詳細」から続行して問題ありません。続いて、貼り付けるコードの全文を示します。
そのまま動くコード
Apps Script エディタの コード.gs を全消しして、以下を貼り付けてください。書き換えるのは冒頭 4 行だけです。
// ===== 設定: ここだけ書き換える =====
var GEMINI_MODEL = 'gemini-3.5-flash-lite'; // 要約用途の第一候補 (終了日の公表なし)
var SEARCH_QUERY = 'newer_than:1d -in:chats -from:me category:primary';
var MAX_THREADS = 30; // 1回あたりの上限件数
var DIGEST_TO = ''; // 空なら自分宛に送る
// ====================================
var GEMINI_ENDPOINT =
'https://generativelanguage.googleapis.com/v1beta/models/' +
GEMINI_MODEL + ':generateContent';
function sendDailyDigest() {
var apiKey = PropertiesService.getScriptProperties()
.getProperty('GEMINI_API_KEY');
if (!apiKey) {
throw new Error('スクリプトプロパティ GEMINI_API_KEY が未設定です');
}
var threads = GmailApp.search(SEARCH_QUERY, 0, MAX_THREADS);
if (threads.length === 0) {
console.log('対象メールなし。ダイジェストは送信しません。');
return;
}
var rows = [];
for (var i = 0; i < threads.length; i++) {
var messages = threads[i].getMessages();
var msg = messages[messages.length - 1]; // スレッド最新の1通
var body = msg.getPlainBody().slice(0, 4000);
var text = callGemini(buildPrompt(msg.getFrom(), msg.getSubject(), body), apiKey, 0);
if (!text) { continue; }
rows.push({
from: msg.getFrom(),
subject: msg.getSubject(),
link: threads[i].getPermalink(),
summary: pickLine(text, '要約'),
action: pickLine(text, '要対応'),
due: pickLine(text, '期限')
});
Utilities.sleep(1500); // 1分あたりの上限に当てないための間隔
}
if (rows.length === 0) {
console.log('要約に成功した件数が0。APIエラーの可能性があるため送信しません。');
return;
}
MailApp.sendEmail({
to: DIGEST_TO || Session.getActiveUser().getEmail(),
subject: '[メール要約] ' +
Utilities.formatDate(new Date(), 'Asia/Tokyo', 'M月d日') +
' 要約 ' + rows.length + '件 / 対象 ' + threads.length + '件',
htmlBody: buildHtml(rows)
});
}
要約を依頼するプロンプトと、応答を安全に取り出す部分です。応答は JSON ではなく行形式にして、余計な構文エラーが起きないようにしています。
function buildPrompt(from, subject, body) {
return [
'あなたは日本の中小企業の経営者アシスタントです。',
'次のメールを読み、下記3行の形式だけで答えてください。前置き不要。',
'',
'要約: 60字以内。何の件で、相手が何を求めているか。',
'要対応: 今日中に返信または作業が必要なら「はい」、不要なら「いいえ」。',
'期限: 本文に明示された期日。なければ「なし」。',
'',
'--- 差出人: ' + from,
'--- 件名: ' + subject,
'--- 本文:',
body
].join('\n');
}
function callGemini(prompt, apiKey, retry) {
var payload = {
contents: [ { parts: [ { text: prompt } ] } ],
generationConfig: {
temperature: 0.2,
maxOutputTokens: 512, // 思考トークンも消費するので余裕を持たせる
thinkingLevel: 'minimal' // 要約に長考は不要。費用と待ち時間を抑える
}
};
var res = UrlFetchApp.fetch(GEMINI_ENDPOINT, {
method: 'post',
contentType: 'application/json',
headers: { 'x-goog-api-key': apiKey }, // キーをURLに載せない
payload: JSON.stringify(payload),
muteHttpExceptions: true
});
var code = res.getResponseCode();
// 429 = レート上限。最大2回まで待って再試行する
if (code === 429 && retry < 2) {
Utilities.sleep(20000);
return callGemini(prompt, apiKey, retry + 1);
}
if (code !== 200) {
console.log('Gemini APIエラー ' + code + ': ' + res.getContentText().slice(0, 300));
return '';
}
var json = JSON.parse(res.getContentText());
var cand = json.candidates && json.candidates[0];
// 安全フィルタや出力上限では parts ごと返らない。ここで必ず止める
if (!cand || !cand.content || !cand.content.parts) {
console.log('応答なし finishReason=' + (cand && cand.finishReason));
return '';
}
return cand.content.parts.map(function (p) { return p.text || ''; }).join('');
}
function pickLine(text, label) {
var m = text.match(new RegExp('^\\s*' + label + '\\s*[::]\\s*(.+)$', 'm'));
return m ? m[1].trim() : '';
}
最後に、届くメールの中身を組み立てる部分です。要対応のものを上に並べます。
function buildHtml(rows) {
rows.sort(function (a, b) {
return (b.action === 'はい' ? 1 : 0) - (a.action === 'はい' ? 1 : 0);
});
var html = ['<table border="1" cellpadding="6" style="border-collapse:collapse">',
'<tr><th>対応</th><th>差出人</th><th>要約</th><th>期限</th></tr>'];
for (var i = 0; i < rows.length; i++) {
var r = rows[i];
html.push(
'<tr>' +
'<td>' + (r.action === 'はい' ? '🔴 要' : '—') + '</td>' +
'<td>' + r.from + '</td>' +
'<td><a href="' + r.link + '">' + r.summary + '</a></td>' +
'<td>' + (r.due || 'なし') + '</td>' +
'</tr>'
);
}
html.push('</table>');
return html.join('');
}
コードは以上です。次に、運用に乗せてから効いてくる注意点を挙げます。
運用前に押さえる 3 つの上限
GAS には無料で使えるかわりに実行上限があります。本レシピで効いてくるのは次の 3 つです。
- 1 回の実行は 6 分まで: 1 通あたり待機 1.5 秒 + 応答 2〜3 秒として、30 通で約 2 分。50 通を超えると危険域に入ります
- トリガー合計の実行時間: 個人アカウントは 1 日 90 分、Google Workspace は 6 時間。1 日 1 回の実行なら余裕があります
- 外部呼び出しの回数: 個人アカウントは 1 日 20,000 回、Workspace は 100,000 回。上限に触れる使い方ではありません
💡 件数が多い場合の対処: MAX_THREADS を 30 に抑えたまま、検索条件を絞るほうが確実です。たとえば SEARCH_QUERY を newer_than:1d is:unread -category:promotions にすると、既読済みと販促メールが外れて対象が一気に減ります。仕分けそのものを先に自動化したい場合は GAS で Gmail を自動ラベル付けするレシピ を先に導入すると相性が良くなります。
導入前後で朝の時間がどう変わるかを、編集部の試算で並べます。
- 受信箱を開く
- 1通ずつ開いて20〜60秒読む
- 対応が要る数通をメモ
- 合計 約35分 / 日
- 朝7時に届く1通を開く
- 要対応の行だけ元メールへ移動
- 3〜4通だけ精読
- 合計 約5分 / 日
編集部のシミュレーション。1日あたり約30分、月20営業日で約10時間の削減に相当します
よくある質問
Q. 要約が的外れなときは何を直せばいいですか。
A. まずプロンプトの「要約: 60字以内」の行に、自社の判断軸を足してください。「金額・納期・先方の要求の 3 点を必ず含める」と書くだけで精度が上がります。それでも足りなければ、設定 1 行目を上位の gemini-3.6-flash に変えて比べてみてください。単価は上がるので、効果を確認してから固定するのが安全です。
Q. 添付ファイルの中身も要約できますか。 A. 本レシピは本文テキストのみが対象です。請求書 PDF などを扱いたい場合は、まず GAS で Gmail 添付を自動保存するレシピ で Drive に落とす仕組みを作るのが先です。
Q. API キーを触るのが不安です。 A. 発行の画面と手順は Google AI Studio の解説記事 に画面単位で整理しています。キーは万一漏れても AI Studio 側でいつでも失効させられます。
Q. Gemini のモデルはどれを選べばいいか分かりません。
A. 本稿の既定である gemini-3.5-flash-lite のまま始めてください。要約と仕分けなら精度は十分で、Flash-Lite 系では唯一まだ提供終了日が公表されていないモデルです。単価の安さだけで gemini-2.5-flash-lite を選ぶと 2026 年 10 月 16 日で止まります。Google の AI をまだ触ったことがない場合は、先に Google AI Studio の解説記事 で画面に慣れておくと迷いません。
出典・参考情報
- Gemini Developer API 料金 (無料枠の扱い・モデル別単価): https://ai.google.dev/gemini-api/docs/pricing
- Gemini API モデル一覧: https://ai.google.dev/gemini-api/docs/models
- generateContent の仕様 (リクエスト形式): https://ai.google.dev/api/generate-content
- Gemini API レート上限: https://ai.google.dev/gemini-api/docs/rate-limits
- API キーの発行 (Google AI Studio): https://aistudio.google.com/apikey
- Apps Script UrlFetchApp リファレンス: https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app
- Apps Script プロパティサービス: https://developers.google.com/apps-script/guides/properties
- Apps Script の割り当てと制限: https://developers.google.com/apps-script/guides/services/quotas
料金・無料枠の条件は変更されることがあります。運用開始前に公式ページで最新の内容をご確認ください。本記事の時間短縮・費用の数値は編集部のシミュレーションであり、効果を保証するものではありません。
Mira / AI経営ラボ 編集長