feat: admin email hub — sent log, inbox, compose, audiences, delivery tracking

Add full email management at /admin/emails with:
- email_log table tracking all outgoing emails with resend_id + delivery events
- inbound_emails table for Resend webhook-received messages
- Resend webhook handler (/webhooks/resend) updating delivery status in real-time
- send_email() returns resend_id (str|None) instead of bool; all 9 worker
  handlers pass email_type= for per-type filtering
- Admin UI: sent log with HTMX filters, email detail with API-enriched HTML
  preview, inbox with unread badges + reply, compose with branded wrapping,
  audience management with contact list/remove
- Sidebar Email section with unread badge via blueprint context processor

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Deeman
2026-02-23 12:15:34 +01:00
parent cb1f00baf0
commit 454b362c88
20 changed files with 1049 additions and 21 deletions

View File

@@ -188,6 +188,10 @@ Same as Flow 2 but arrives at `/<lang>/leads/quote` directly (no planner state).
| Leads | `GET /admin/leads`, `/admin/leads/<id>` | List, filter, view detail, change status, forward to supplier, create |
| Suppliers | `GET /admin/suppliers`, `/admin/suppliers/<id>` | List, view, adjust credits, change tier, create |
| Feedback | `GET /admin/feedback` | View all submitted feedback |
| Email Sent Log | `GET /admin/emails`, `/admin/emails/<id>` | List all outgoing emails (filter by type/event/search), detail with API-enriched HTML preview |
| Email Inbox | `GET /admin/emails/inbox`, `/admin/emails/inbox/<id>` | Inbound emails (unread badge), detail with sandboxed HTML, inline reply |
| Email Compose | `GET /admin/emails/compose` | Send ad-hoc emails with from-address selection + optional branded wrapping |
| Audiences | `GET /admin/emails/audiences`, `/admin/emails/audiences/<id>/contacts` | Resend audiences, contact list, remove contacts |
| Article Templates | `GET /admin/templates` | CRUD + bulk generate articles from template+data |
| Published Scenarios | `GET /admin/scenarios` | CRUD public scenario cards (shown on landing) |
| Articles | `GET /admin/articles` | CRUD, publish/unpublish, rebuild HTML |
@@ -211,6 +215,7 @@ Same as Flow 2 but arrives at `/<lang>/leads/quote` directly (no planner state).
| `dashboard` | `/dashboard` | No |
| `billing` | `/billing` | No |
| `admin` | `/admin` | No |
| `webhooks` | `/webhooks` | No |
**Language detection for non-prefixed blueprints:** Cookie (`lang`) → `Accept-Language` header → fallback `"en"`