/start-10-4
Lesson command
$ npx -y skills add minicoohei/ai-agent-camp --agent claude-codeHow it fires
How this command gets triggered: by you, by Claude, or both.
- Fires itselfClaude auto-loads it when your prompt matches the work.
- You can call itInvoke it directly when you want it.
- Slash command
/start-10-4
Context preview
What this command does when you run it.
Lesson command
Command definition
start-10-4.mddescription: "Lesson command"
chapter: "courses/aiagent/lesson03-core/module10-gas"
duration: "約25分"
prerequisites: ["start-10-1"]
level: "intermediate"
tags: ["gas", "gmail", "sheets", "automation", "clasp"]
nonInteractiveMode: deferred
🎓 Lesson 10-4: GmailAppメール検索・抽出→シート整理
📍 このセッションでやること
**Lesson 10-4: GmailAppメール検索・抽出→シート整理** へようこそ!
| 項目 | 内容 | |------|------| | ゴール | GAS の GmailApp でメールを検索・抽出し、スプレッドシートに自動整理する | | 所要時間 | 約25分 | | 使うスキル | GAS (GmailApp, SpreadsheetApp), clasp | | 前提条件 | Lesson 10-1 完了(clasp 認証済み) |
**このセッションの流れ:** 1. appsscript.json に Gmail スコープ追加 2. GmailApp.search() でメール検索 3. スレッド/メッセージから情報を抽出 4. SpreadsheetApp でシートにデータ書き込み 5. 定期実行トリガーの設定
セッション終了時には、メールを自動で検索・抽出し、スプレッドシートに整理するGASスクリプトが完成しています。
> **💡 ヒント**: AIの応答が途中で止まった場合は「続きを表示して」「止まってるよ」と入力すると再開します。
---
🎯 準備チェック
まずは準備が整っているか確認しましょう。
**AskQuestionの設定:**
{
"title": "🎯 セッション開始前の確認",
"questions": [{
"id": "readiness",
"prompt": "準備はできていますか?",
"options": [
{"id": "ready", "label": "準備OK!始めましょう"},
{"id": "check_prereq", "label": "前提条件を確認したい"},
{"id": "different_lesson", "label": "別のレッスンに移動したい"}
]
}]
}(ready → Step 1へ) (check_prereq → Lesson 10-1 完了確認。`clasp login --status` で認証状態確認) (different_lesson → モジュール一覧を表示)
---
🚀 Step 1: appsscript.json に Gmail スコープ追加
{
"title": "🚀 Step 1: Gmail スコープ追加",
"questions": [{
"id": "step_action",
"prompt": "appsscript.json に Gmail の読み取りスコープを追加します。",
"options": [
{"id": "practice", "label": "このまま進める"},
{"id": "review", "label": "現在の appsscript.json を確認"},
{"id": "skip", "label": "スキップ"}
]
}]
}**選択後の案内(例)**:
`gas-example/appsscript.json` の `oauthScopes` に以下を追加:
{
"timeZone": "Asia/Tokyo",
"dependencies": {},
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8",
"oauthScopes": [
"https://www.googleapis.com/auth/gmail.readonly",
"https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/script.scriptapp"
]
}追加後、`clasp push` でデプロイ:
cd gas-example && npx -y @google/clasp push
**期待される結果**: `appsscript.json` に `gmail.readonly` スコープが追加され、push が成功する。
---
🚀 Step 2: GmailApp.search() でメール検索
{
"title": "🚀 Step 2: メール検索",
"questions": [{
"id": "step_action",
"prompt": "GmailApp.search() を使ってメールを検索する関数を作成します。",
"options": [
{"id": "practice", "label": "このまま進める"},
{"id": "review", "label": "Gmail検索クエリ構文を確認"},
{"id": "skip", "label": "スキップ"}
]
}]
}**選択後の案内(例)**:
`gas-example/Gmail.gs` に `searchEmails` 関数を作成:
function searchEmails(query, maxResults) {
query = query || "is:unread newer_than:7d";
maxResults = maxResults || 50;
var threads = GmailApp.search(query, 0, maxResults);
Logger.log("検索結果: " + threads.length + " スレッド");
return threads;
}**Gmail 検索クエリの例:**
| クエリ | 意味 | |--------|------| | `is:unread` | 未読メール | | `newer_than:7d` | 過去7日以内 | | `from:example@company.com` | 特定の送信者 | | `subject:会議` | 件名に「会議」を含む | | `has:attachment` | 添付ファイル付き | | `is:unread newer_than:3d` | 複合条件 |
`clasp push` → `clasp open` で GAS エディタを開き、`searchEmails` を実行してログを確認。
**期待される結果**: 検索結果のスレッド数がログに表示される。
---
🚀 Step 3: メール情報の抽出
{
"title": "🚀 Step 3: メール情報抽出",
"questions": [{
"id": "step_action",
"prompt": "スレッドからメール情報(送信者・件名・日時・本文)を抽出します。",
"options": [
{"id": "practice", "label": "このまま進める"},
{"id": "review", "label": "GmailMessage の API を確認"},
{"id": "skip", "label": "スキップ"}
]
}]
}**選択後の案内(例)**:
`extractEmailData` 関数を追加:
function extractEmailData(threads) {
var data = [];
threads.forEach(function(thread) {
var messages = thread.getMessages();
var lastMessage = messages[messages.length - 1];
data.push({
subject: lastMessage.getSubject(),
from: lastMessage.getFrom(),
date: lastMessage.getDate(),
body: lastMessage.getPlainBody().substring(0, 200),
isUnread: lastMessage.isUnread(),
messageCount: messages.length
});
});
return data;
}**主要メソッド:**
| メソッド | 取得内容 | |---------|---------| | `getSubject()` | 件名 | | `getFrom()` | 送信者 | | `getDate()` | 日時 | | `getPlainBody()` | 本文(テキスト) | | `isUnread()` | 未読かどうか | | `getMessages().length` | スレッド内メッセージ数 |
**期待される結果**: メール情報がオブジェクト配列として抽出される。
---
🚀 Step 4: スプレッドシートにデータ書き込み
{
"title": "🚀 Step 4: シートに書き込み",
"questions": [{
"id": "step_action",
"prompt": "抽出したメールデータをスプレッドシートに書き込みます。",
"options": [
{"id": "practice", "label": "このまま進める"},
{"id": "review", "label": "SpreadsheetApp の API を確認"},
{"id": "skip", "label": "スキップ"}
]
}]
}**選択後の案内(例)**:
`writeToSheet` 関数と、メイン関数 `extractAndOrganizeEmails` を追加:
function writeToSheet(data, sheetName) {
sheetName = sheetName || "メール一覧_" + Utilities.formatDate(new Date(), "Asia/Tokyo", "yyyy-MM-dd");
var ss = SpreadsheetApp.create(sheetName);
var sheet = ss.getActiveSheet();
// ヘッダー行
var headers = ["件名", "送信者", "日時", "本文(先頭200文字)", "未読", "メッセージ数"];
sheet.getRange(1, 1, 1, headers.length).setValues([headers]);
sheet.getRange(1, 1, 1, headers.length).setFontWeight("bold");
// データ行
if (data.length > 0) {
var rows = data.map(function(item) {
return [
item.subject, item.from,
Utilities.formatDate(item.date, "Asia/Tokyo", "yyyy-MM-dd HH:mm"),
item.body, item.isUnread ? "未読" : "既読", item.messageCount
];
});
sheet.getRange(2, 1, rows.length, headers.length).setValues(rows);
}
Logger.log("シート作成完了: " + ss.getUrl());
return ss.getUrl();
}
function extractAndOrganizeEmails() {
var threads = searchEmails("is:unread newer_than:7d", 50);
var data = extractEmailData(threads);
var url = writeToSheet(data);
Logger.log("処理完了: " + data.length + " 件のメールをシートに整理しました");
}`clasp push` → `clasp open` で `extractAndOrganizeEmails` を実行。
**期待される結果**: Google Drive に「
Read more
description: "Lesson command" chapter: "courses/aiagent/lesson03-core/module10-gas" duration: "約25分" prerequisites: ["start-10-1"] level: "intermediate" tags: ["gas", "gmail", "sheets", "automation", "clasp"] nonInteractiveMode: deferred
🎓 Lesson 10-4: GmailAppメール検索・抽出→シート整理
📍 このセッションでやること
**Lesson 10-4: GmailAppメール検索・抽出→シート整理** へようこそ!
| 項目 | 内容 | |------|------| | ゴール | GAS の GmailApp でメールを検索・抽出し、スプレッドシートに自動整理する | | 所要時間 | 約25分 | | 使うスキル | GAS (GmailApp, SpreadsheetApp), clasp | | 前提条件 | Lesson 10-1 完了(clasp 認証済み) |
**このセッションの流れ:** 1. appsscript.json に Gmail スコープ追加 2. GmailApp.search() でメール検索 3. スレッド/メッセージから情報を抽出 4. SpreadsheetApp でシートにデータ書き込み 5. 定期実行トリガーの設定
セッション終了時には、メールを自動で検索・抽出し、スプレッドシートに整理するGASスクリプトが完成しています。
> **💡 ヒント**: AIの応答が途中で止まった場合は「続きを表示して」「止まってるよ」と入力すると再開します。
---
🎯 準備チェック
まずは準備が整っているか確認しましょう。
**AskQuestionの設定:**
{
"title": "🎯 セッション開始前の確認",
"questions": [{
"id": "readiness",
"prompt": "準備はできていますか?",
"options": [
{"id": "ready", "label": "準備OK!始めましょう"},
{"id": "check_prereq", "label": "前提条件を確認したい"},
{"id": "different_lesson", "label": "別のレッスンに移動したい"}
]
}]
}(ready → Step 1へ) (check_prereq → Lesson 10-1 完了確認。`clasp login --status` で認証状態確認) (different_lesson → モジュール一覧を表示)
---
🚀 Step 1: appsscript.json に Gmail スコープ追加
{
"title": "🚀 Step 1: Gmail スコープ追加",
"questions": [{
"id": "step_action",
"prompt": "appsscript.json に Gmail の読み取りスコープを追加します。",
"options": [
{"id": "practice", "label": "このまま進める"},
{"id": "review", "label": "現在の appsscript.json を確認"},
{"id": "skip", "label": "スキップ"}
]
}]
}**選択後の案内(例)**:
`gas-example/appsscript.json` の `oauthScopes` に以下を追加:
{
"timeZone": "Asia/Tokyo",
"dependencies": {},
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8",
"oauthScopes": [
"https://www.googleapis.com/auth/gmail.readonly",
"https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/script.scriptapp"
]
}追加後、`clasp push` でデプロイ:
cd gas-example && npx -y @google/clasp push
**期待される結果**: `appsscript.json` に `gmail.readonly` スコープが追加され、push が成功する。
---
🚀 Step 2: GmailApp.search() でメール検索
{
"title": "🚀 Step 2: メール検索",
"questions": [{
"id": "step_action",
"prompt": "GmailApp.search() を使ってメールを検索する関数を作成します。",
"options": [
{"id": "practice", "label": "このまま進める"},
{"id": "review", "label": "Gmail検索クエリ構文を確認"},
{"id": "skip", "label": "スキップ"}
]
}]
}**選択後の案内(例)**:
`gas-example/Gmail.gs` に `searchEmails` 関数を作成:
function searchEmails(query, maxResults) {
query = query || "is:unread newer_than:7d";
maxResults = maxResults || 50;
var threads = GmailApp.search(query, 0, maxResults);
Logger.log("検索結果: " + threads.length + " スレッド");
return threads;
}**Gmail 検索クエリの例:**
| クエリ | 意味 | |--------|------| | `is:unread` | 未読メール | | `newer_than:7d` | 過去7日以内 | | `from:example@company.com` | 特定の送信者 | | `subject:会議` | 件名に「会議」を含む | | `has:attachment` | 添付ファイル付き | | `is:unread newer_than:3d` | 複合条件 |
`clasp push` → `clasp open` で GAS エディタを開き、`searchEmails` を実行してログを確認。
**期待される結果**: 検索結果のスレッド数がログに表示される。
---
🚀 Step 3: メール情報の抽出
{
"title": "🚀 Step 3: メール情報抽出",
"questions": [{
"id": "step_action",
"prompt": "スレッドからメール情報(送信者・件名・日時・本文)を抽出します。",
"options": [
{"id": "practice", "label": "このまま進める"},
{"id": "review", "label": "GmailMessage の API を確認"},
{"id": "skip", "label": "スキップ"}
]
}]
}**選択後の案内(例)**:
`extractEmailData` 関数を追加:
function extractEmailData(threads) {
var data = [];
threads.forEach(function(thread) {
var messages = thread.getMessages();
var lastMessage = messages[messages.length - 1];
data.push({
subject: lastMessage.getSubject(),
from: lastMessage.getFrom(),
date: lastMessage.getDate(),
body: lastMessage.getPlainBody().substring(0, 200),
isUnread: lastMessage.isUnread(),
messageCount: messages.length
});
});
return data;
}**主要メソッド:**
| メソッド | 取得内容 | |---------|---------| | `getSubject()` | 件名 | | `getFrom()` | 送信者 | | `getDate()` | 日時 | | `getPlainBody()` | 本文(テキスト) | | `isUnread()` | 未読かどうか | | `getMessages().length` | スレッド内メッセージ数 |
**期待される結果**: メール情報がオブジェクト配列として抽出される。
---
🚀 Step 4: スプレッドシートにデータ書き込み
{
"title": "🚀 Step 4: シートに書き込み",
"questions": [{
"id": "step_action",
"prompt": "抽出したメールデータをスプレッドシートに書き込みます。",
"options": [
{"id": "practice", "label": "このまま進める"},
{"id": "review", "label": "SpreadsheetApp の API を確認"},
{"id": "skip", "label": "スキップ"}
]
}]
}**選択後の案内(例)**:
`writeToSheet` 関数と、メイン関数 `extractAndOrganizeEmails` を追加:
function writeToSheet(data, sheetName) {
sheetName = sheetName || "メール一覧_" + Utilities.formatDate(new Date(), "Asia/Tokyo", "yyyy-MM-dd");
var ss = SpreadsheetApp.create(sheetName);
var sheet = ss.getActiveSheet();
// ヘッダー行
var headers = ["件名", "送信者", "日時", "本文(先頭200文字)", "未読", "メッセージ数"];
sheet.getRange(1, 1, 1, headers.length).setValues([headers]);
sheet.getRange(1, 1, 1, headers.length).setFontWeight("bold");
// データ行
if (data.length > 0) {
var rows = data.map(function(item) {
return [
item.subject, item.from,
Utilities.formatDate(item.date, "Asia/Tokyo", "yyyy-MM-dd HH:mm"),
item.body, item.isUnread ? "未読" : "既読", item.messageCount
];
});
sheet.getRange(2, 1, rows.length, headers.length).setValues(rows);
}
Logger.log("シート作成完了: " + ss.getUrl());
return ss.getUrl();
}
function extractAndOrganizeEmails() {
var threads = searchEmails("is:unread newer_than:7d", 50);
var data = extractEmailData(threads);
var url = writeToSheet(data);
Logger.log("処理完了: " + data.length + " 件のメールをシートに整理しました");
}`clasp push` → `clasp open` で `extractAndOrganizeEmails` を実行。
**期待される結果**: Google Drive に「
AI Agent Training for Non-Engineers - Complete Guide to Claude Code / Cursor / Codex ### ⚠️ Before you clone Official repository (maintained by the authors): Running AI agents from this repo grants them shell, file-write, and external-API permissions on your
Other commands on ai-agent-camp.
- /check-setup.en
Top-level alias — see lesson/check-setup.en.md for the full body.
Open command - /check-setup.es
Alias de nivel superior — el cuerpo completo está en lesson/check-setup.es.md.
Open command - /check-setup
Top-level alias — see lesson/check-setup.md for the full body.
Open command - /check-security.en
Lesson command
Open command - /check-security.es
Lesson command
Open command - /check-security
Lesson command
Open command

