Skip to content

メール取込

関連: データ取込 / Gemini / アーキテクチャ

方針

  • 受信・保存はプログラム(IMAP)
  • 種別判定・金額抽出は Gemini(Skills 相当は Gemini の仕組みで代替)
  • 金額検証・重複排除はプログラム側のガードレール
  • 「全部 Gemini 丸投げ」にはしない

想定されるメール種別(楽天など)

厳密な件名ルールは最初から全部書かない。Gemini に分類させる。

kind イメージ 扱い
flash 利用速報(使った直後) リアルタイム支出候補。Discord 即時向き
statement 明細・請求・確定系 補正・取りこぼし検知。即時通知は抑制可
ignore キャンペーン、案内、セキュリティ通知など 支出にしない。raw だけ残す

同じ支払いが flash と後続メールで二重に見えることがあるので、重複排除が必要。

処理フロー

IMAP 定期取得(1〜5分間隔)
  → 未処理メールを取得
  → raw(件名 / From / 受信日時 / 本文テキスト)を PostgreSQL に保存
  → Gemini 分類+抽出(structured JSON)
  → プログラムで検証
      - amount が本文に存在するか
      - kind / is_expense の整合
      - dedupe_key で既存支出と突合
  → OK なら支出イベント化
  → flash かつ is_expense なら Discord へ厳し目通知

Gemini にやらせること

  • kind: flash / statement / ignore
  • amount, merchant, paid_at
  • is_expense: 家計の「支出」として数えるか
  • dedupe_hint: 同一取引っぽさを示す短い鍵(店名+金額+日付など)
  • confidence / notes(任意)

やらせないこと:

  • メール受信そのもの
  • 生データの永続化
  • 最終的な会計確定(検証失敗時は保留)

プロンプトの渡し方は Gemini

プログラム側ガードレール

  1. 生データ必須保存 … 再処理・監査用
  2. 金額検証 … 抽出 amount が本文中に現れるか(表記ゆれは正規化して比較)
  3. ignore はイベント化しない
  4. 重複排除
  5. 同一 Message-ID は再処理しない
  6. dedupe_hint + 金額 + 日付近傍で flash ↔ statement を結びつける
  7. 既に flash で計上済みなら statement は「確認」扱い(二重計上しない)
  8. 失敗時needs_review にして Discord に「読めなかった」と短く報告(任意)

IMAP 準備

  1. 利用通知が届くメールアドレスを決める(専用でも可)
  2. IMAP が使えること(Gmail ならアプリパスワード等)
  3. 可能なら楽天の送信元 / 件名でざっくり事前フィルタ(最終判定は Gemini)

環境変数(メール関連)

IMAP_HOST=
IMAP_USER=
IMAP_PASSWORD=
IMAP_FOLDER=INBOX
# 任意: 送信元ざっくりフィルタ
# IMAP_FROM_FILTER=rakuten.co.jp

出力 JSON イメージ(Gemini → アプリ)

{
  "kind": "flash",
  "is_expense": true,
  "amount": 1280,
  "currency": "JPY",
  "merchant": "コンビニXYZ",
  "paid_at": "2026-08-08T12:34:00+09:00",
  "dedupe_hint": "コンビニXYZ|1280|2026-08-08",
  "confidence": 0.86,
  "notes": "利用速報と判定"
}