-- Daily mail-reputation snapshots parsed from the postfix logs.
--
-- WHY: Sender reputation lives at the RECEIVING operator (Microsoft 365, Google,
-- Yahoo, ...), not at the recipient domain. The provider portals (SNDS, Postmaster,
-- Yahoo CFL) show this but each needs a login and lags 24-48h. Our own postfix logs
-- already contain the ground truth in real time: every send to a Microsoft tenant
-- returns 250 (accepted) / 451 4.7.500 (throttled, "server busy") / 5xx (rejected),
-- and the reject text tells us WHY (reputation 5.7.1, recipient unknown 5.1.1, etc.).
-- A 2026-06-19 audit found 80% of Microsoft sends were getting 451 4.7.500 throttles
-- on the warming IPs -- exactly the signal we need to watch ease as reputation builds.
--
-- This table stores ONE row per (log_date, sending_ip, receiver_operator, outcome
-- class) so we can chart accepted% / deferred% / reject-reason mix per operator over
-- time without re-parsing logs (which rotate fast). Populated by
-- scripts/mail_reputation_monitor.py (idempotent upsert per day).

CREATE TABLE IF NOT EXISTS mail_reputation_daily (
    id              BIGSERIAL PRIMARY KEY,
    log_date        DATE         NOT NULL,          -- the calendar day of the log lines (server TZ)
    sending_ip      TEXT         NOT NULL,          -- our egress IP (207.174.124.94 / .107 / ...)
    receiver        TEXT         NOT NULL,          -- normalized receiving operator: microsoft|google|yahoo|proofpoint|other
    outcome         TEXT         NOT NULL,          -- accepted|throttled|reject_reputation|reject_recipient|reject_content|reject_other|deferred_other
    reason_code     TEXT,                           -- representative enhanced status / code (e.g. 4.7.500, 5.7.1, 5.1.1)
    msg_count       INTEGER      NOT NULL DEFAULT 0,
    sample_text     TEXT,                           -- one representative raw response, for debugging
    created_at      TIMESTAMPTZ  NOT NULL DEFAULT now(),
    updated_at      TIMESTAMPTZ  NOT NULL DEFAULT now(),
    UNIQUE (log_date, sending_ip, receiver, outcome, reason_code)
);

CREATE INDEX IF NOT EXISTS idx_mail_rep_daily_date     ON mail_reputation_daily (log_date);
CREATE INDEX IF NOT EXISTS idx_mail_rep_daily_receiver ON mail_reputation_daily (receiver, log_date);

COMMENT ON TABLE  mail_reputation_daily IS
  'Daily per-IP per-receiving-operator mail delivery outcome counts parsed from postfix logs (SNDS-equivalent reputation trend, no provider login needed). Populated by scripts/mail_reputation_monitor.py.';
COMMENT ON COLUMN mail_reputation_daily.receiver IS
  'Normalized receiving operator: microsoft|google|yahoo|proofpoint|mimecast|other';
COMMENT ON COLUMN mail_reputation_daily.outcome IS
  'accepted|throttled|reject_reputation|reject_recipient|reject_content|reject_other|deferred_other';
