GEMINI LABEN
NANOLITE — Nano Banana 2 Liteが登場しました。Googleで最も速く、最もコスト効率の高いGemini Imageモデルで、軽量な画像生成を安く回したい用途に向いていますOMNIFLASH — Gemini Omni Flashがpublic previewになりました。ネイティブにマルチモーダルなモデルで、企業や開発者が独自の動的な動画ワークフローを構築できますAGENTS — Managed Agentsが拡張されました。background: trueでサーバー側の非同期実行とポーリング、リモートMCPサーバー連携、対話をまたぐ認証情報のリフレッシュに対応しますMEMORY — Memory BankのIngestEvents APIが一般提供になりました。イベントの取り込みとメモリ生成を分離し、コンテンツを継続的にストリームできますTHROUGHPUT — Provisioned Throughputで、同一モデル・同一リージョンに対して最大7件の保留オーダーを提出できるようになりましたDEPRECATE — 画像生成モデルは8月17日に、Gemini Enterprise Agent PlatformのGrok 4.1系は8月20日に停止される予定ですNANOLITE — Nano Banana 2 Liteが登場しました。Googleで最も速く、最もコスト効率の高いGemini Imageモデルで、軽量な画像生成を安く回したい用途に向いていますOMNIFLASH — Gemini Omni Flashがpublic previewになりました。ネイティブにマルチモーダルなモデルで、企業や開発者が独自の動的な動画ワークフローを構築できますAGENTS — Managed Agentsが拡張されました。background: trueでサーバー側の非同期実行とポーリング、リモートMCPサーバー連携、対話をまたぐ認証情報のリフレッシュに対応しますMEMORY — Memory BankのIngestEvents APIが一般提供になりました。イベントの取り込みとメモリ生成を分離し、コンテンツを継続的にストリームできますTHROUGHPUT — Provisioned Throughputで、同一モデル・同一リージョンに対して最大7件の保留オーダーを提出できるようになりましたDEPRECATE — 画像生成モデルは8月17日に、Gemini Enterprise Agent PlatformのGrok 4.1系は8月20日に停止される予定です
記事一覧/API / SDK
API / SDK/2026-03-29中級

Gemini API でインテリジェントなメール自動分類システムを構築する — Function Calling × 構造化出力の実践

Gemini API の Function Calling と構造化出力を活用し、受信メールを自動で分類・要約・優先度付けするシステムの構築方法を、実際に動作するコード例とともに解説します。

gemini-api279function-calling20structured-output20email-automationtypescript15

なぜメールの自動分類が必要なのか

毎日大量に届くメールの中から、緊急の案件・対応が必要な依頼・情報共有だけのメールを瞬時に見分けるのは、想像以上に認知負荷のかかる作業です。Gemini API の Function Calling と構造化出力を組み合わせれば、受信メールを自動的に分類し、優先度付けと要約を行うインテリジェントなシステムを構築できます。

これは Gemini Lab のプレミアム記事で扱うような実践的なシステム構築の一部を、無料で体験いただける見本記事です。より深い内容にご興味をお持ちの方は、ぜひメンバーシップもご検討ください。

システムアーキテクチャの設計

メール分類システムは、以下の3つのステージで構成します。

ステージ1: 分類(Classification) — メールのカテゴリと優先度を判定

ステージ2: 要約(Summarization) — 本文の要点を3文以内に抽出

ステージ3: アクション抽出(Action Extraction) — 返信や対応が必要な場合にアクションアイテムを生成

// types/email.ts
export interface EmailInput {
  id: string;
  from: string;
  to: string;
  subject: string;
  body: string;
  receivedAt: string;
}
 
export type EmailCategory =
  | "urgent"       // 緊急対応が必要
  | "action"       // 対応が必要(緊急ではない)
  | "info"         // 情報共有・FYI
  | "newsletter"   // ニュースレター・マーケティング
  | "spam";        // スパム・不要
 
export type Priority = "high" | "medium" | "low";
 
export interface ClassifiedEmail extends EmailInput {
  category: EmailCategory;
  priority: Priority;
  summary: string;
  actionItems: string[];
  confidence: number;   // 分類の確信度(0-1)
}

Function Calling でメールを分類する

Gemini の Function Calling を使うことで、メール分類の出力スキーマを厳密に定義できます。これにより、後続の処理で型安全にデータを扱えます。

import { GoogleGenerativeAI } from "@google/generative-ai";
 
const genAI = new GoogleGenerativeAI("YOUR_GEMINI_API_KEY");
 
// メール分類ツールの定義
const classifyEmailTool = {
  functionDeclarations: [{
    name: "classify_email",
    description: "受信メールを分析し、カテゴリ・優先度・要約・アクションアイテムを返す",
    parameters: {
      type: "object",
      properties: {
        category: {
          type: "string",
          enum: ["urgent", "action", "info", "newsletter", "spam"],
          description: "メールのカテゴリ",
        },
        priority: {
          type: "string",
          enum: ["high", "medium", "low"],
          description: "優先度",
        },
        summary: {
          type: "string",
          description: "メール本文の要約(3文以内、日本語)",
        },
        action_items: {
          type: "array",
          items: { type: "string" },
          description: "必要なアクションのリスト(対応不要なら空配列)",
        },
        confidence: {
          type: "number",
          description: "分類の確信度(0.0〜1.0)",
        },
      },
      required: ["category", "priority", "summary", "action_items", "confidence"],
    },
  }],
};
 
async function classifyEmail(email: EmailInput): Promise<ClassifiedEmail> {
  const model = genAI.getGenerativeModel({
    model: "gemini-2.5-flash",
    tools: [classifyEmailTool],
  });
 
  const prompt = `以下のメールを分析してください。
 
差出人: ${email.from}
件名: ${email.subject}
本文:
${email.body}
 
このメールのカテゴリ、優先度、要約、必要なアクションを classify_email 関数で返してください。`;
 
  const result = await model.generateContent(prompt);
  const response = result.response;
 
  // Function Call の結果を取得
  const functionCall = response.candidates?.[0]?.content?.parts?.find(
    (part) => part.functionCall
  )?.functionCall;
 
  if (!functionCall || functionCall.name !== "classify_email") {
    throw new Error("Expected classify_email function call");
  }
 
  const args = functionCall.args as {
    category: EmailCategory;
    priority: Priority;
    summary: string;
    action_items: string[];
    confidence: number;
  };
 
  return {
    ...email,
    category: args.category,
    priority: args.priority,
    summary: args.summary,
    actionItems: args.action_items,
    confidence: args.confidence,
  };
}

functionDeclarations でスキーマを定義しておくことで、Gemini はこの構造に準拠したデータを返します。enum でカテゴリの選択肢を制限しているため、想定外の値が返ることはありません。

バッチ処理による大量メールの効率的分類

メールボックスに数百通のメールがある場合、1通ずつ処理すると時間がかかります。並行処理とレート制限を組み合わせたバッチ処理を実装します。

// utils/batch-classifier.ts
 
// 同時実行数を制限するセマフォ
class Semaphore {
  private queue: (() => void)[] = [];
  private running = 0;
 
  constructor(private max: number) {}
 
  async acquire(): Promise<void> {
    if (this.running < this.max) {
      this.running++;
      return;
    }
    return new Promise<void>((resolve) => {
      this.queue.push(resolve);
    });
  }
 
  release(): void {
    this.running--;
    const next = this.queue.shift();
    if (next) {
      this.running++;
      next();
    }
  }
}
 
async function batchClassify(
  emails: EmailInput[],
  concurrency = 5
): Promise<ClassifiedEmail[]> {
  const semaphore = new Semaphore(concurrency);
  const results: ClassifiedEmail[] = [];
  const errors: Array<{ email: EmailInput; error: string }> = [];
 
  const tasks = emails.map(async (email) => {
    await semaphore.acquire();
    try {
      const classified = await classifyEmail(email);
      results.push(classified);
    } catch (error) {
      errors.push({
        email,
        error: error instanceof Error ? error.message : "Unknown error",
      });
    } finally {
      semaphore.release();
    }
  });
 
  await Promise.all(tasks);
 
  if (errors.length > 0) {
    console.warn(`${errors.length}/${emails.length} emails failed classification`);
  }
 
  // 優先度でソート(high → medium → low)
  const priorityOrder = { high: 0, medium: 1, low: 2 };
  results.sort((a, b) => priorityOrder[a.priority] - priorityOrder[b.priority]);
 
  return results;
}

分類ルールのカスタマイズ

ビジネスの種類や個人の作業スタイルに合わせて、分類ルールをカスタマイズするための設定レイヤーを追加します。

// config/classification-rules.ts
interface ClassificationRules {
  urgentSenders: string[];      // 常に urgent として扱う送信者
  infoOnlyDomains: string[];    // 常に info として扱うドメイン
  spamKeywords: string[];       // スパムと判定するキーワード
  customPromptRules: string;    // 追加の分類ルール(自然言語)
}
 
const defaultRules: ClassificationRules = {
  urgentSenders: [
    "boss@company.com",
    "ceo@company.com",
  ],
  infoOnlyDomains: [
    "noreply@github.com",
    "notifications@slack.com",
  ],
  spamKeywords: [
    "unsubscribe",
    "limited time offer",
  ],
  customPromptRules: `
    - クライアントからの請求関連メールは常に "urgent" + "high" にする
    - 社内の週報は "info" + "low" にする
    - 採用関連のメールは "action" + "medium" にする
  `,
};
 
function buildClassificationPrompt(
  email: EmailInput,
  rules: ClassificationRules
): string {
  // 事前ルールチェック
  if (rules.urgentSenders.includes(email.from)) {
    return `このメールは重要な送信者(${email.from})からです。カテゴリを "urgent" として分類してください。\n\n${email.body}`;
  }
 
  const domain = email.from.split("@")[1];
  if (domain && rules.infoOnlyDomains.includes(domain)) {
    return `このメールは通知ドメイン(${domain})からです。カテゴリを "info" として分類してください。\n\n${email.body}`;
  }
 
  return `以下の追加ルールに従ってメールを分類してください:
${rules.customPromptRules}
 
差出人: ${email.from}
件名: ${email.subject}
本文: ${email.body}`;
}

分類結果のダッシュボード出力

分類結果をわかりやすく表示するダッシュボード用のレポートを生成します。

function generateReport(emails: ClassifiedEmail[]): string {
  const byCategory = emails.reduce((acc, email) => {
    acc[email.category] = (acc[email.category] || 0) + 1;
    return acc;
  }, {} as Record<string, number>);
 
  const urgent = emails.filter(e => e.category === "urgent");
  const actions = emails.filter(e => e.category === "action");
 
  let report = `📊 メール分類レポート\n`;
  report += `━━━━━━━━━━━━━━━━━━━━\n`;
  report += `総数: ${emails.length}通\n\n`;
 
  // カテゴリ別集計
  Object.entries(byCategory).forEach(([cat, count]) => {
    const icon = { urgent: "🔴", action: "🟡", info: "🔵", newsletter: "📰", spam: "⛔" }[cat] || "⚪";
    report += `${icon} ${cat}: ${count}通\n`;
  });
 
  // 緊急メール一覧
  if (urgent.length > 0) {
    report += `\n🔴 緊急対応が必要:\n`;
    urgent.forEach(e => {
      report += `  - [${e.from}] ${e.subject}\n    ${e.summary}\n`;
    });
  }
 
  // アクション一覧
  if (actions.length > 0) {
    report += `\n🟡 対応が必要:\n`;
    actions.forEach(e => {
      report += `  - [${e.from}] ${e.subject}\n`;
      e.actionItems.forEach(item => {
        report += `    → ${item}\n`;
      });
    });
  }
 
  return report;
}
 
// 使用例
const classified = await batchClassify(inboxEmails);
console.log(generateReport(classified));
// 期待出力:
// 📊 メール分類レポート
// ━━━━━━━━━━━━━━━━━━━━
// 総数: 50通
//
// 🔴 urgent: 3通
// 🟡 action: 12通
// 🔵 info: 20通
// 📰 newsletter: 10通
// ⛔ spam: 5通
//
// 🔴 緊急対応が必要:
//   - [client@example.com] 納品日の変更について
//     クライアントから納品日を3日前倒しする依頼。今週金曜までに回答が必要。

全体を振り返って

Gemini API の Function Calling を使えば、受信メールを自動的に分類・要約・アクション抽出するシステムを効率よく構築できます。スキーマを厳密に定義することで型安全なデータフローが実現でき、カスタムルールの追加でビジネスニーズに柔軟に対応できる設計です。

AI を使った業務自動化の全体像

Gemini API の基本は「Gemini API クイックスタート」を、Function Calling の詳細は「Function Calling完全ガイド」もあわせてご覧ください。ストリーミング応答の実装に興味がある方は「ストリーミング応答とマルチターン会話の実装」も参考になります。

個人開発12年の視点で見る Gemini 運用

運用時に毎月見ているメトリクス

  • API 呼び出し成功率と平均レイテンシ
  • 1リクエストあたりの平均トークン消費
  • AdMob 売上との比較で見た ROI
シェア

お読みいただきありがとうございます

Gemini Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

API / SDK2026-06-25
Gemini API × TypeScript 型安全AIアプリケーション設計ガイド — Zodスキーマ・Structured Output・ストリーミングの統合アーキテクチャ
Gemini APIとTypeScriptで型安全なAIアプリケーションを構築する方法を解説。Zodバリデーション、Structured Output、ストリーミング、エラーハンドリングを統合した本番アーキテクチャを実装します。
API / SDK2026-05-09
Gemini APIで tools と responseSchema を同時指定すると400になる — Function Callingと構造化出力を両立する3つの設計
Function Callingで外部APIを呼びつつ、最終回答は決まった形のJSONで受け取りたい。tools と responseSchema を両方指定すると400エラーになる仕様の理由と、本番で安定して動く3つの回避設計を実装例つきで解説します。
API / SDK2026-05-09
Gemini Live API で画面共有しながら音声で対話する『AI ペアプログラマー』を TypeScript で構築する
Gemini Live API と getDisplayMedia で『画面を見せながら音声で相談できる AI ペア』を TypeScript で構築する手順を、コスト最適化と落とし穴まで含めて実装プレイブックにまとめました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →