"""outgoing system mail (password reset) configured in the admin panel The server sends its own mail — today only password-reset links — through an SMTP account the administrator sets up in the admin panel. The password is envelope-encrypted with MASTER_KEY like every mail-account secret. ``public_url`` is where users reach the app; reset links are built from it, never from the request's Host header, which an attacker controls. Revision ID: 0020 Revises: 0019 Create Date: 2026-09-30 """ from __future__ import annotations from collections.abc import Sequence from alembic import op revision: str = "0020" down_revision: str | None = "0019" branch_labels: str | Sequence[str] | None = None depends_on: str | Sequence[str] | None = None _COLUMNS = ( ("smtp_host", "text NOT NULL DEFAULT ''"), ("smtp_port", "integer NOT NULL DEFAULT 587"), ("smtp_security", "text NOT NULL DEFAULT 'starttls'"), ("smtp_username", "text NOT NULL DEFAULT ''"), ("smtp_secret_ct", "bytea"), ("smtp_from", "text NOT NULL DEFAULT ''"), ("public_url", "text NOT NULL DEFAULT ''"), ) def upgrade() -> None: for name, ddl in _COLUMNS: op.execute(f"ALTER TABLE app_settings ADD COLUMN {name} {ddl}") op.execute( "ALTER TABLE app_settings ADD CONSTRAINT ck_app_settings_smtp_security " "CHECK (smtp_security IN ('starttls', 'ssl', 'none'))" ) def downgrade() -> None: op.execute("ALTER TABLE app_settings DROP CONSTRAINT IF EXISTS ck_app_settings_smtp_security") for name, _ in reversed(_COLUMNS): op.execute(f"ALTER TABLE app_settings DROP COLUMN IF EXISTS {name}")