For senders whose mail body is the receipt (e.g. GoCardless payouts) there is no attachment to file. The new action "Als PDF anhängen + nach <Ordner>" renders the mail like a print from a mail client (header block From/To/Date/Subject, then the content) and replaces it in the target folder with: original content + PDF + the original mail byte-for-byte as Original.eml, so the unaltered original is retained (GoBD). - Rendering with WeasyPrint. Images are fetched by us and inlined as data: URIs; WeasyPrint itself may only read data:. Fetching is restricted to http(s), public addresses (private, loopback, link-local and PDF_BLOCKED_NETWORKS, default 172.0.0.0/12, are refused; redirects are checked hop by hop), with time and size limits. cid: images come from the MIME parts. - The replacement is APPENDed with the original flags and INTERNALDATE, verified in the target via its new Message-ID, and only then is the original deleted. Already converted mails are only moved. - "PDF-Vorschau" in the rule dialog renders the newest matching mail read-only and opens it in the browser. - List/log show 📄 targets; warnings for PDF + move/delete and for PDF + "Hat Anhang = Ja"; log folder search covers PDF targets. - Docker image gets Pango and fonts (~316 MB total). Tested with the real GoCardless mail (3 remote images, rendered both locally and inside the built image) and a simulated IMAP server for success, rejected APPEND, missing copy and already converted mails. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
29 lines
1.1 KiB
Python
29 lines
1.1 KiB
Python
from pathlib import Path
|
|
|
|
from pydantic_settings import BaseSettings
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
database_url: str = "sqlite:///data/mailfilter.db"
|
|
yaml_config_path: str = "config/filters.yaml"
|
|
encryption_key: str = ""
|
|
yaml_sync_on_startup: bool = True
|
|
log_level: str = "INFO"
|
|
# Ausführliches Verarbeitungslog (jede Nicht-Übereinstimmung, jede Regel pro
|
|
# Poll). Erzeugt Millionen Einträge — nur zur Fehlersuche einschalten.
|
|
log_verbose: bool = False
|
|
# Log-Rotation: Einträge älter als N Tage löschen und höchstens so viele
|
|
# behalten (die neuesten). Läuft täglich zur angegebenen Stunde (UTC) und
|
|
# einige Minuten nach jedem Start.
|
|
log_retention_days: int = 30
|
|
log_max_entries: int = 200_000
|
|
maintenance_hour_utc: int = 2
|
|
# Mail→PDF: Bilder werden nie aus privaten Netzen geladen. Zusätzlich
|
|
# gesperrte Netze (kommagetrennt), z.B. intern genutzte öffentliche Bereiche.
|
|
pdf_blocked_networks: str = "172.0.0.0/12"
|
|
|
|
model_config = {"env_file": ".env", "env_file_encoding": "utf-8"}
|
|
|
|
|
|
settings = Settings()
|