変更内容まとめ

バックエンド
models.py — MailSender.rule に always_notify 追加、MailEmail.feedback にも追加、マイグレーション適用済み
views.py — FeedbackView.post が always_notify を受け取ったら MailSender ルールを作成(never_notify と同じ仕組み)
フロントエンド
feedback/[token]/page.tsx — 4択目「🔔 常に通知してほしい」を追加。スコープ選択(アドレス/ドメイン)もあり。色はteal系で区別
mail/rules/page.tsx — 追加フォームにルール種別セレクタを追加、一覧に「常に通知」バッジ(teal)を表示
Windmill側の使い方(メモ)
GET /api/mail/sender-rule/ のレスポンスに "rule": "always_notify" が返ってきたら、LLMをスキップして llm_verdict: "important" で直接 POST /api/mail/emails/ を呼べばOKです。
This commit is contained in:
Akira
2026-02-22 09:49:28 +09:00
parent 7a1aa81f9f
commit df16ab1ee0
6 changed files with 129 additions and 45 deletions

View File

@@ -0,0 +1,23 @@
# Generated by Django 5.0 on 2026-02-22 00:34
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('mail', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='mailemail',
name='feedback',
field=models.CharField(blank=True, choices=[('important', '重要だった'), ('not_important', '普通のメール'), ('never_notify', '今後通知しない'), ('always_notify', '常に通知してほしい')], max_length=20, null=True, verbose_name='フィードバック'),
),
migrations.AlterField(
model_name='mailsender',
name='rule',
field=models.CharField(choices=[('always_notify', '常に通知'), ('never_notify', '通知しない')], default='never_notify', max_length=20, verbose_name='ルール'),
),
]

View File

@@ -2,13 +2,19 @@ import uuid
from django.db import models
SENDER_RULE_CHOICES = [
('always_notify', '常に通知'),
('never_notify', '通知しない'),
]
class MailSender(models.Model):
"""送信者ルールnever_notify: 通知しない)"""
"""送信者ルール"""
email = models.EmailField(null=True, blank=True, verbose_name="メールアドレス")
domain = models.CharField(max_length=255, null=True, blank=True, verbose_name="ドメイン")
rule = models.CharField(
max_length=20,
choices=[('never_notify', '通知しない')],
choices=SENDER_RULE_CHOICES,
default='never_notify',
verbose_name="ルール"
)
@@ -45,6 +51,7 @@ FEEDBACK_CHOICES = [
('important', '重要だった'),
('not_important', '普通のメール'),
('never_notify', '今後通知しない'),
('always_notify', '常に通知してほしい'),
]

View File

@@ -159,7 +159,7 @@ class FeedbackView(APIView):
mail_email = self._get_mail_email(token)
feedback = request.data.get('feedback')
valid_feedbacks = ['important', 'not_important', 'never_notify']
valid_feedbacks = ['important', 'not_important', 'never_notify', 'always_notify']
if feedback not in valid_feedbacks:
return Response(
{'error': f'feedback は {valid_feedbacks} のいずれかを指定してください'},
@@ -171,18 +171,18 @@ class FeedbackView(APIView):
mail_email.feedback_at = timezone.now()
mail_email.save(update_fields=['feedback', 'feedback_at'])
# 「今後通知しない」の場合、送信者ルールを作成/更新
if feedback == 'never_notify':
# 送信者ルールを伴うフィードバックの処理
if feedback in ('never_notify', 'always_notify'):
scope = request.data.get('scope') # 'address' or 'domain'
if scope == 'address':
MailSender.objects.update_or_create(
email=mail_email.sender_email,
defaults={'domain': None, 'rule': 'never_notify'}
defaults={'domain': None, 'rule': feedback}
)
elif scope == 'domain':
MailSender.objects.update_or_create(
domain=mail_email.sender_domain,
defaults={'email': None, 'rule': 'never_notify'}
defaults={'email': None, 'rule': feedback}
)
return Response({'status': 'ok'})