作成: 2026-02-21
ステータス: 仕様確定 → 実装フェーズへ
複数のメールアカウントに届くメールをLLMで重要度判定し、重要なメールだけをLINEで通知する。
フィードバックを積み重ねることで判定が賢くなっていく仕組みを持つ。
[Xserver/Gmail/Hotmail IMAP]
↓ Windmill スケジュール実行(ポーリング)
[メール取得・正規化]
↓
[重要度判定エンジン](Django API経由でDBを参照)
├─ アドレスルールあり → ルールに従う(never_notify → スキップ)
├─ ドメインルールあり → ルールに従う(never_notify → スキップ)
└─ ルールなし → LLM(Claude API)に判定させる
↓ 文脈として「過去フィードバック集計」を渡す
↓ 重要と判断されたメール
[LINE Messaging API で通知]
「件名: ○○ / 送信者: △△
👉 https://keinafarm.net/mail/feedback/{token}」
↓ タップ
[KeinaシステムのDjangoビュー /mail/feedback/{token}]
↓ フィードバック選択
[KeinaシステムのPostgreSQL更新]
↓ 次回ポーリング時にWindmillが参照
| 役割 | 技術 |
|---|---|
| ワークフロー実行 | Windmill(既にサーバーで稼働中) |
| メール取得 | IMAP統一(Xserver/Gmail/Hotmail) |
| LLM判定 | Claude API |
| LINE通知 | LINE Messaging API(既に連携済み) |
| フィードバック画面・API | Keinaシステム(Django)に機能追加 |
| DB | KeinaシステムのPostgreSQL |
| Windmill ↔ Keinasystem連携 | Django REST API(APIキー認証) |
ルールは複数アカウントをまたいで共通(アカウントを区別しない)。
新着メール受信
↓
0. 宛先補正(To ヘッダー)
- @keinafarm.com 宛先は xserver1〜xserver6 に正規化(Gmail先行取り込み時の誤ラベル防止)
↓
1. mail_senders に一致するアドレスルールがあるか?
→ never_notify: スキップ(LLM呼ばない、記録もしない)
↓
2. mail_senders に一致するドメインルールがあるか?
→ never_notify: スキップ(LLM呼ばない、記録もしない)
↓
3. LLM判定(Claude API)
入力:
- 送信者メールアドレス・ドメイン
- 件名
- 本文冒頭(200字程度)
- 過去フィードバック集計(後述)
出力:
- important / not_important
↓
4. important → mail_emails に記録 → トークン発行 → LINE通知
not_important → mail_emails に記録(通知なし)
アドレスルール > ドメインルール > LLM判断(具体的なほど優先)
トークン肥大化を防ぐため、生の履歴ではなく集計値を渡す:
送信者: promo@example.com (example.com)
過去に通知したメール: 8通
- 重要だった: 2回
- 普通のメール: 5回
- 今後通知しない: 0回
- フィードバック未提供: 1回
件名: ××のご案内
本文冒頭: ...(200字)
mail_senders(送信者ルール)| フィールド | 型 | 説明 |
|---|---|---|
| id | AutoField | |
| EmailField (nullable) | アドレス指定 例: info@amazon.co.jp | |
| domain | CharField (nullable) | ドメイン指定 例: amazon.co.jp |
| rule | CharField | 'never_notify' のみ(MVP) |
| note | TextField | メモ(「○○の営業メール」など) |
| created_at | DateTimeField | |
| updated_at | DateTimeField |
email か domain のどちらか一方のみ設定するmail_emails(通知メール記録)| フィールド | 型 | 説明 |
|---|---|---|
| id | AutoField | |
| account | CharField | 'gmail' / 'gmail_service' / 'hotmail' / 'xserver1'〜'xserver6'(旧データは 'xserver') |
| message_id | CharField (unique) | メールのMessage-ID(重複防止) |
| sender_email | EmailField | |
| sender_domain | CharField | |
| subject | CharField | |
| body_preview | TextField | 本文冒頭200字程度 |
| received_at | DateTimeField | |
| llm_verdict | CharField | 'important' / 'not_important' |
| notified_at | DateTimeField (nullable) | LINE通知日時 |
| feedback | CharField (nullable) | 'important' / 'not_important' / 'never_notify' |
| feedback_at | DateTimeField (nullable) | フィードバック日時 |
mail_notification_tokens(フィードバック用トークン)| フィールド | 型 | 説明 |
|---|---|---|
| id | AutoField | |
| OneToOneField(MailEmail) | 1メール1トークン | |
| token | UUIDField (unique) | 推測不可能なランダムUUID |
| created_at | DateTimeField |
認証: リクエストヘッダー X-API-Key: <secret> で行う。
| メソッド | URL | 用途 |
|---|---|---|
| GET | /api/mail/sender-rule/ |
送信者ルール確認 |
| GET | /api/mail/sender-context/ |
LLM用フィードバック集計取得 |
| POST | /api/mail/emails/ |
メール記録+トークン発行 |
/api/mail/sender-rule/クエリパラメータ: ?email=promo@example.com&domain=example.com
レスポンス例:
{
"matched": true,
"rule": "never_notify",
"match_type": "domain"
}
/api/mail/sender-context/クエリパラメータ: ?email=promo@example.com&domain=example.com
レスポンス例:
{
"total_notified": 8,
"important": 2,
"not_important": 5,
"never_notify": 0,
"no_feedback": 1
}
/api/mail/emails/リクエストボディ:
{
"account": "gmail",
"message_id": "<xxx@gmail.com>",
"sender_email": "promo@example.com",
"sender_domain": "example.com",
"subject": "○○のご案内",
"body_preview": "...",
"received_at": "2026-02-21T10:30:00Z",
"llm_verdict": "important",
"notification_reason": "llm_important",
"applied_rule_type": null
}
notification_reason: llm_important / rule_always_notifyapplied_rule_type: address / domain(notification_reason=rule_always_notify の時のみ)notification_reason 未指定で llm_verdict=important の場合、Keina 側で llm_important を補完レスポンス(important の場合のみトークンを返す):
{
"id": 42,
"feedback_url": "https://keinafarm.net/mail/feedback/550e8400-e29b-41d4-a716-446655440000"
}
/mail/feedback/{token})「今後通知しない」を選ぶと展開:
○ このアドレスだけ(promo@example.com)
○ このドメインごと(example.com)
[確定する]
「今後通知しない」でフィードバック確定時、mail_senders にルールを自動追加する。
/mail/rules/)ナビゲーションにメニュー追加。
表示内容: