Files
imap-mail-filter-service/app/schemas/schemas.py
T
duffyduckandClaude Opus 5.5 1b4f6ed34e redesign filter page: rule test, match stats, warnings, toggle
- Rule tester (POST /api/filters/test): evaluates an unsaved rule
  read-only against the newest matching mails in the source folder,
  using an IMAP SEARCH on the first text condition to narrow candidates.
  Shows matches, near misses with the failing condition, and whether
  any candidate had an attachment at all (would have caught the
  Klarmobil and it-moench misconfigurations immediately).
- Per-rule match_count / last_match_at (new migration), incremented by
  the scheduler on every match and shown in the list.
- PATCH /api/filters/{id}/enabled toggles a rule without resetting its
  processed state (a full PUT re-evaluates every mail for that rule).
- New filter list: cards with enable switch, priority, condition and
  action chips, match stats, and warnings (display name in from/to,
  "am (exakt)" date, duplicates, empty values, invalid regex, move
  without folder). Quick filters for active/inactive/warnings/never
  matched; copy-as-template; remembered account selection.
- Edit dialog: wider layout, live warnings, integrated test panel,
  sensible defaults for new rules (from + date after Jan 1 + move).
- Light global refresh: nav with active item, page background, cards.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 09:48:12 +02:00

155 lines
3.4 KiB
Python

from datetime import datetime
from pydantic import BaseModel
from app.models.db_models import ActionType, ConditionField, MatchType
# --- Filter Condition ---
class FilterConditionCreate(BaseModel):
field: ConditionField
match_type: MatchType
value: str
negate: bool = False
class FilterConditionResponse(FilterConditionCreate):
id: int
model_config = {"from_attributes": True}
# --- Filter Action ---
class FilterActionCreate(BaseModel):
action_type: ActionType
parameter: str | None = None
class FilterActionResponse(FilterActionCreate):
id: int
model_config = {"from_attributes": True}
# --- Filter Rule ---
class FilterRuleCreate(BaseModel):
name: str
account_id: int
priority: int | None = None # None → automatisch ans Ende einsortieren (max+10)
enabled: bool = True
stop_processing: bool = False
source_folder: str = "INBOX"
conditions: list[FilterConditionCreate] = []
actions: list[FilterActionCreate] = []
class FilterRuleUpdate(BaseModel):
name: str | None = None
priority: int | None = None
enabled: bool | None = None
stop_processing: bool | None = None
source_folder: str | None = None
conditions: list[FilterConditionCreate] | None = None
actions: list[FilterActionCreate] | None = None
class FilterRuleResponse(BaseModel):
id: int
account_id: int
name: str
priority: int
enabled: bool
stop_processing: bool
source_folder: str
match_count: int = 0
last_match_at: datetime | None = None
conditions: list[FilterConditionResponse]
actions: list[FilterActionResponse]
created_at: datetime
updated_at: datetime
model_config = {"from_attributes": True}
class FilterRuleEnabled(BaseModel):
enabled: bool
class FilterRuleTest(BaseModel):
account_id: int
source_folder: str = "INBOX"
conditions: list[FilterConditionCreate]
limit: int = 40
# --- Account ---
class AccountCreate(BaseModel):
name: str
imap_host: str
imap_port: int = 993
use_ssl: bool = True
username: str
password: str
smtp_host: str | None = None
smtp_port: int | None = None
smtp_username: str | None = None
smtp_password: str | None = None
poll_interval_seconds: int = 120
enabled: bool = True
class AccountUpdate(BaseModel):
name: str | None = None
imap_host: str | None = None
imap_port: int | None = None
use_ssl: bool | None = None
username: str | None = None
password: str | None = None
smtp_host: str | None = None
smtp_port: int | None = None
smtp_username: str | None = None
smtp_password: str | None = None
poll_interval_seconds: int | None = None
enabled: bool | None = None
class AccountResponse(BaseModel):
id: int
name: str
imap_host: str
imap_port: int
use_ssl: bool
username: str
smtp_host: str | None
smtp_port: int | None
smtp_username: str | None
poll_interval_seconds: int
enabled: bool
last_poll_at: datetime | None
filter_rules: list[FilterRuleResponse] = []
created_at: datetime
updated_at: datetime
model_config = {"from_attributes": True}
class AccountListResponse(BaseModel):
id: int
name: str
imap_host: str
username: str
enabled: bool
last_poll_at: datetime | None
poll_interval_seconds: int
filter_rule_count: int = 0
model_config = {"from_attributes": True}