GASでGmailの長文メールを
AIで3行に自動要約する方法
毎日届く長文メールを、GmailApp(GASからGmailを操作する標準機能)とClaude API(Anthropic社の生成AI)を組み合わせ、 要点だけの3行に自動要約してスプレッドシートに記録する方法を、そのまま動くコードで解説します。
Table of Contents
なぜメールの要約を自動化するのか
結論から言うと、長文メールの「読んで要点をつかむ」作業は、 GAS(Google Apps Script。Googleサービスを操作する無料のプログラム実行環境)とAIで自動化できます。 受信メールをAIに渡し、要点だけの3行に要約してスプレッドシートに並べておけば、 一覧をざっと見るだけで内容を把握できます。
手作業でメールを開いて読む運用と比べ、次のようなメリットがあります。
一覧で把握できる
1通ずつ開かなくても、要約が並んだシートで全体を見渡せる
見落としを減らす
長文に埋もれた重要な依頼や締め切りを要点として拾える
共有しやすい
要約シートをチームで共有すれば、対応状況を全員で追える
検索・集計できる
シート上のデータなので、あとから絞り込みや件数集計ができる
この記事では、Gmailの未読メールを取得し、Anthropic社のClaude APIで3行に要約してシートへ記録する、という一連の流れを実装します。
準備:Gmail連携とAPIキーの保管
必要なのは2つだけです。1つ目はGmailへのアクセス許可。GAS標準のGmailAppを初めて使うと承認画面が出るので、承認すれば連携できます。2つ目はClaude APIのキーです。 このキーは料金が発生する権限そのものなので、コードに直書きしてはいけません。GASの「スクリプトプロパティ」(PropertiesServiceで読み書きする、スクリプト単位の設定保存領域)に入れておき、コードからはキー名で読み出します。
// 一度だけ実行してAPIキーを安全に保存する
function saveApiKey() {
// 実行後、この関数のキー文字列は削除しておく
PropertiesService.getScriptProperties()
.setProperty("ANTHROPIC_API_KEY", "sk-ant-xxxxxxxx");
}
// コードからはキー名で読み出す(直書きしない)
function getApiKey() {
const key = PropertiesService.getScriptProperties()
.getProperty("ANTHROPIC_API_KEY");
if (!key) throw new Error("APIキーが未設定です。saveApiKeyを実行してください。");
return key;
}saveApiKeyを一度だけ実行したら、キー文字列はコードから消しておきましょう。以降はどの関数からもgetApiKey()で安全に取り出せます。あわせて、要約を書き込む「メール要約」という名前のシートを作っておきます。
Claude APIで3行要約を作る
まずはテキストを渡すと3行の箇条書きを返す関数を作ります。要約を安定させるコツは、 プロンプト(AIへの指示文)で形式を具体的に指定することです。「3つの箇条書き」「各行40文字以内」「前置きは書かない」と明示し、 さらに返ってきたテキストを改行で分割して先頭3行だけ使う後処理で、行数のぶれを抑えます。
// 渡したテキストを「3行の箇条書き」に要約して返す
function summarize3Lines(text) {
const url = "https://api.anthropic.com/v1/messages";
const prompt =
"次のメール本文を、日本語で3つの箇条書きに要約してください。\n" +
"・各行は40文字以内で、要点だけを簡潔に。\n" +
"・記号「・」で始め、3行ちょうどにする。\n" +
"・前置きや結びの文は書かない。\n\n" +
"本文:\n" + text;
const payload = {
model: "claude-haiku-4-5",
max_tokens: 300,
messages: [{ role: "user", content: prompt }]
};
const options = {
method: "post",
contentType: "application/json",
headers: {
"x-api-key": getApiKey(),
"anthropic-version": "2023-06-01"
},
payload: JSON.stringify(payload),
muteHttpExceptions: true // エラー時も例外にせずレスポンスを受け取る
};
const res = UrlFetchApp.fetch(url, options);
const code = res.getResponseCode();
if (code !== 200) {
throw new Error("API エラー (" + code + "): " + res.getContentText());
}
const answer = JSON.parse(res.getContentText()).content[0].text.trim();
// 改行で分割し、空行を除いて先頭3行だけ採用する(行数のぶれ対策)
const lines = answer.split("\n").map(function (s) {
return s.trim();
}).filter(String);
return lines.slice(0, 3).join("\n");
}返答はcontent配列の先頭textに入ります。muteHttpExceptions: trueを付けると、エラー時も例外で止まらず自分でステータスコードを確認できます。モデルは軽量なclaude-haiku-4-5から始め、要約品質を上げたいときに高性能なclaude-opus-4-8へ差し替えるだけで切り替えられます。
長文をトークン上限に収める切り詰め
AIには一度に扱える文字数(トークン。AIが文章を区切って数える単位)に上限があります。 長いメールをそのまま送ると上限を超えてエラーになったり、料金が無駄にかさんだりします。 そこで、本文を送る前に先頭で切り詰めておきます。あわせて、返信メールにありがちな 「行頭が>の引用部分」を落とすと、要約の精度も上がります。
// 長文はトークン上限に収まるよう先頭で切り詰める
function trimForApi(text, maxChars) {
maxChars = maxChars || 4000;
if (!text) return "";
// 引用部分(行頭が「>」の返信引用)を除いてノイズを減らす
const withoutQuote = text.split("\n").filter(function (line) {
return line.indexOf(">") !== 0;
}).join("\n");
if (withoutQuote.length <= maxChars) return withoutQuote;
return withoutQuote.slice(0, maxChars) + "\n(以下省略)";
}ここでは先頭4000文字を目安にしています。要約は本文全体の細部までは必要としないため、 先頭の主要部分だけでも要点は十分に拾えます。メールの傾向に合わせてmaxCharsを調整してください。
Gmailから取得して要約・記録する
いよいよ本体です。GmailApp.search()で未読メール(is:unread)を取得し、本文を切り詰めてから要約し、シートに1行ずつ追記します。1回の実行では最大10件に絞り、 実行時間制限に配慮します。
// 未読メールを取得し、要約してシートに記録する
// シート構成: A=処理日時, B=送信者, C=件名, D=3行要約, E=メールID
function summarizeUnreadMails() {
const sheet = SpreadsheetApp.getActive().getSheetByName("メール要約");
// すでに処理済みのメールIDを集合として読み込む(二重記録防止)
const doneIds = readDoneIds(sheet);
// 未読メールを最大10件だけ取得(実行時間制限への配慮)
const threads = GmailApp.search("is:unread", 0, 10);
threads.forEach(function (thread) {
thread.getMessages().forEach(function (msg) {
const id = msg.getId();
if (doneIds[id]) return; // 記録済みはスキップ
const body = trimForApi(msg.getPlainBody(), 4000);
if (!body) return;
const summary = summarize3Lines(body);
sheet.appendRow([
new Date(), // A: 処理日時
msg.getFrom(), // B: 送信者
msg.getSubject(), // C: 件名
summary, // D: 3行要約
id // E: メールID(次回の重複判定に使う)
]);
doneIds[id] = true;
Utilities.sleep(300); // 連続呼び出しの間隔をあける
});
});
}
// E列に記録済みのメールIDを { id: true } の形で返す
function readDoneIds(sheet) {
const lastRow = sheet.getLastRow();
const map = {};
if (lastRow < 2) return map; // ヘッダーのみ
const ids = sheet.getRange(2, 5, lastRow - 1, 1).getValues(); // E列
ids.forEach(function (row) {
if (row[0]) map[row[0]] = true;
});
return map;
}getPlainBody()は、HTMLメールから装飾を除いた本文テキストだけを取り出します。要約にはこの方が向いています。appendRow()でシートの末尾に追記していくので、実行のたびに要約が下へ積み上がっていきます。
同じメールを二重に処理しない仕組み
定期実行するなら、二重記録の防止が欠かせません。上のコードでは、各メールが持つ一意のID(getId()で取得できる文字列)をE列に記録し、次回実行時にreadDoneIds()で読み込んで照合しています。すでに記録済みのIDはスキップするので、同じメールを何度も要約しません。
「未読」を条件にしているため、要約したメールをmarkRead()で既読にしたり、addLabel()で「要約済み」ラベルを付けたりして、検索条件からも外す方法も有効です。IDによる照合とラベル運用を 組み合わせると、より確実に重複を防げます。
トリガーで定期実行を自動化する
最後に、時間主導トリガー(決まった間隔で関数を自動実行するGASの仕組み)を設定すれば、 人が手を動かさなくても要約が回り続けます。15分おきに新着メールをチェックする例です。
// 15分おきに自動要約を回す時間主導トリガーを設定する
function createSummaryTrigger() {
ScriptApp.newTrigger("summarizeUnreadMails")
.timeBased()
.everyMinutes(15)
.create();
}なお、1回の実行で扱う件数が多いと、GASの実行時間制限(無料枠で6分)に達することがあります。 上のコードではsearch("is:unread", 0, 10)で1回10件に区切っています。件数が多い場合は、続きを次のトリガーで再開する分割実行にすると安定します。 実装の詳細は関連記事で解説しています。
まとめ
GmailとClaude APIをGASでつなぐと、長文メールの要点把握を自動化できます。ポイントは4つです。 APIキーはスクリプトプロパティで安全に保管し、要約は形式指定+後処理で行数のぶれを抑え、 長文は切り詰めてトークン上限を回避し、メールIDの照合で二重処理を防ぐ——この型を押さえれば、 要約に限らず、優先度の判定・返信の下書き生成といったAI活用にも同じ流れで応用できます。
よくある質問
特別な外部ライブラリは不要です。GAS標準のGmailApp.search()で条件に合うスレッドを取り出し、getMessages()・getPlainBody()で本文を取得できます。初回実行時にGmailへのアクセス許可を求められるので、承認すれば動きます。
AIの出力は自然文なので、指示だけでは行数がぶれることがあります。プロンプトで「必ず3つの箇条書きで、各行は40文字以内」と明示し、返ってきたテキストを改行で分割して先頭3行だけ使う後処理を入れると安定します。本文でこの実装を紹介しています。
多くはトークン上限の超過が原因です。AIは一度に扱える文字数(トークン)に上限があります。本文を先頭数千文字で切り詰めてから送る、または署名や引用部分を削ってから送ると回避できます。本文で切り詰めのコードを紹介しています。
処理済みのメールID(getId()で取得できる一意の文字列)をスプレッドシートに記録し、次回以降はそのIDが記録済みかを照合してスキップします。Gmail側で処理済みラベルを付ける方法も有効です。両方を本文で解説しています。
要約は比較的軽い処理なので、まずはコストを抑えられる軽量モデル claude-haiku-4-5 で品質を確認し、要約の精度をさらに上げたい場合に高性能な claude-opus-4-8 へ切り替えるのがおすすめです。モデルはリクエストのmodelフィールドの文字列を差し替えるだけで変更できます。
引っかかる可能性があります。GASには1回の実行あたり6分(Workspaceは30分)の制限があります。1回で処理する件数を区切り、続きは時間主導トリガーで再開する分割実行にすると安定します。関連記事で分割実行の実装を解説しています。
関連するサービス・記事
AI×GASの業務自動化を
相談する。
メール要約のほかにも、問い合わせ分類・優先度判定・返信下書きの自動生成など、 AI APIとGASを組み合わせた自動化をご相談いただけます。既存のGmail・スプレッドシート運用にも組み込めます。