Skip to content
Documentation
Command

/start-10-4

Lesson command

From plugin
ai-agent-camp
345200 skills8 agents200 commands
Install
$ npx -y skills add minicoohei/ai-agent-camp --agent claude-code

How 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.md
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 に「

Read more
Ships withai-agent-camp

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

Get the whole plugin