Skip to content
Documentation
Command

/start-10-4.en

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.en

Context preview

What this command does when you run it.

Lesson command

Command definition

start-10-4.en.md
description: "Lesson command"
chapter: "courses/aiagent/lesson03-core/module10-gas"
duration: "~25 min"
prerequisites: ["start-10-1"]
level: "intermediate"
tags: ["gas", "gmail", "sheets", "automation", "clasp"]
nonInteractiveMode: deferred

๐ŸŽ“ Lesson 10-4: GmailApp Email Search/Extraction โ†’ Sheet Organization

๐Ÿ“ What You'll Do

**Lesson 10-4: GmailApp Email Search/Extraction โ†’ Sheet Organization**!

| Item | Details | |------|------| | Goal | Search and extract emails with GAS GmailApp, then automatically organize them in a spreadsheet | | Duration | ~25 min | | Skills used | GAS (GmailApp, SpreadsheetApp), clasp | | Prerequisites | Lesson 10-1 completed (clasp authenticated) |

**Session flow:** 1. Add Gmail scope to appsscript.json 2. Search emails with GmailApp.search() 3. Extract info from threads/messages 4. Write data to a sheet with SpreadsheetApp 5. Set up a scheduled trigger

By the end of this session, you'll have a complete GAS script that automatically searches, extracts, and organizes emails in a spreadsheet.

> **๐Ÿ’ก Hint**: If the AI response stops midway, type "please continue" or "keep going" to resume.

---

๐ŸŽฏ Readiness Check

Let's first check that everything is ready.

**AskQuestion configuration:**

{
  "title": "๐ŸŽฏ Pre-session check",
  "questions": [{
    "id": "readiness",
    "prompt": "Are you ready?",
    "options": [
      {"id": "ready", "label": "Ready! Let's start"},
      {"id": "check_prereq", "label": "Check prerequisites"},
      {"id": "different_lesson", "label": "Go to a different lesson"}
    ]
  }]
}

(ready โ†’ Go to Step 1) (check_prereq โ†’ Verify Lesson 10-1 completion. Check auth status with `clasp login --status`) (different_lesson โ†’ Display module list)

---

๐Ÿš€ Step 1: Add Gmail Scope to appsscript.json

{
  "title": "๐Ÿš€ Step 1: Add Gmail Scope",
  "questions": [{
    "id": "step_action",
    "prompt": "Add the Gmail read scope to appsscript.json.",
    "options": [
      {"id": "practice", "label": "Proceed"},
      {"id": "review", "label": "Review current appsscript.json"},
      {"id": "skip", "label": "Skip"}
    ]
  }]
}

**Guidance after selection:**

Add the following to `oauthScopes` in `gas-example/appsscript.json`:

{
  "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"
  ]
}

After adding, deploy with `clasp push`:

cd gas-example && npx -y @google/clasp push

**Expected result:** The `gmail.readonly` scope is added to `appsscript.json` and the push succeeds.

---

๐Ÿš€ Step 2: Search Emails with GmailApp.search()

{
  "title": "๐Ÿš€ Step 2: Email Search",
  "questions": [{
    "id": "step_action",
    "prompt": "Create a function that searches emails using GmailApp.search().",
    "options": [
      {"id": "practice", "label": "Proceed"},
      {"id": "review", "label": "Review Gmail search query syntax"},
      {"id": "skip", "label": "Skip"}
    ]
  }]
}

**Guidance after selection:**

Create the `searchEmails` function in `gas-example/Gmail.gs`:

function searchEmails(query, maxResults) {
  query = query || "is:unread newer_than:7d";
  maxResults = maxResults || 50;
  var threads = GmailApp.search(query, 0, maxResults);
  Logger.log("Search results: " + threads.length + " threads");
  return threads;
}

**Gmail search query examples:**

| Query | Meaning | |--------|------| | `is:unread` | Unread emails | | `newer_than:7d` | Within the last 7 days | | `from:example@company.com` | From a specific sender | | `subject:meeting` | Subject contains "meeting" | | `has:attachment` | Has attachments | | `is:unread newer_than:3d` | Combined conditions |

Run `clasp push` โ†’ `clasp open` to open the GAS editor, then execute `searchEmails` and check the logs.

**Expected result:** The number of matching threads is displayed in the logs.

---

๐Ÿš€ Step 3: Extract Email Information

{
  "title": "๐Ÿš€ Step 3: Extract Email Info",
  "questions": [{
    "id": "step_action",
    "prompt": "Extract email information (sender, subject, date, body) from threads.",
    "options": [
      {"id": "practice", "label": "Proceed"},
      {"id": "review", "label": "Review the GmailMessage API"},
      {"id": "skip", "label": "Skip"}
    ]
  }]
}

**Guidance after selection:**

Add the `extractEmailData` function:

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;
}

**Key methods:**

| Method | Returns | |---------|---------| | `getSubject()` | Subject | | `getFrom()` | Sender | | `getDate()` | Date/time | | `getPlainBody()` | Body (plain text) | | `isUnread()` | Whether the email is unread | | `getMessages().length` | Number of messages in the thread |

**Expected result:** Email information is extracted as an array of objects.

---

๐Ÿš€ Step 4: Write Data to a Spreadsheet

{
  "title": "๐Ÿš€ Step 4: Write to Sheet",
  "questions": [{
    "id": "step_action",
    "prompt": "Write the extracted email data to a spreadsheet.",
    "options": [
      {"id": "practice", "label": "Proceed"},
      {"id": "review", "label": "Review the SpreadsheetApp API"},
      {"id": "skip", "label": "Skip"}
    ]
  }]
}

**Guidance after selection:**

Add the `writeToSheet` function and the main function `extractAndOrganizeEmails`:

function writeToSheet(data, sheetName) {
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