0.1.8 - 2026-06-24
Added
- Admin UI overhaul for the Emails module: page title/subtitle moved into the admin shell top bar; a daisyUI table toolbar across Emails/Templates/Queue/Blocklist (dropdown filters, a persistent inline search with inline clear, action buttons); clickable column-header sorting (server-side, URL-backed, field-whitelisted) on the contexts that support ordering; body-row click-to-open (Emails/Queue → Details, Templates → edit); a drag-and-drop column customizer on Emails; and a "Get update on this email" per-row status sync. (#13)
Send Testnow renders and sends the seededtest_emailsystem template (falling back to a built-in body) and recordstemplate_name, the sending admin'suser_uuid, andsource_module: "emails", so the email Details page shows the template, user, and module. (#13)
Fixed
- Webhook security (SNS): the signing-certificate URL is locked to
sns.<region>.amazonaws.comwith a/SimpleNotificationService-*.pempath before any fetch (blocks forged-cert signature bypass and SSRF);SignatureVersionis honored (SHA-1 vs SHA-256);X-Forwarded-Foris trusted only from configured proxies (newwebhook_trusted_proxiessetting, default empty); andconfirm_subscription/1actually issues the SubscribeURL GET. (#12) - Event ingestion: open/click events no longer overwrite terminal statuses (bounced/complaint/rejected/failed); event creation is idempotent via DB unique constraints with graceful
{:ok, :duplicate_event}mapping; open/click dedup onoccurred_atpreserves multiple distinct engagements while collapsing exact SQS redeliveries;opened_at/clicked_atare now recorded. (#12) - SQS pipeline: placeholder logs are inserted directly, bypassing the sampling roll that previously returned
{:ok, :skipped}, crashed callers, and re-cycled messages forever; the Oban poller is collapsed to exactly one self-healing chain (always self-schedules while enabled, backs off on misconfiguration instead of dying);Task.yield_manyprevents a slow task from aborting a whole batch; sub-second polling intervals are rejected. (#12) - The dedup insert in
Event.create_event/1runs withmode: :savepoint, so a unique-constraint violation insideLog.mark_as_opened/2/mark_as_clicked/3's transaction no longer aborts the transaction and silently rolls back the status update. - Analytics:
get_stats_for_period/2now counts thecomplaintstatus (it previously matched acomplainedstring that is never written, so the metric was always 0) and runs as one grouped query instead of seven aggregate round-trips. (#12) - The Emails table column customizer validates column ids against the available-column set before persisting, so a crafted client event can no longer store an unknown column. (#13)
- List sorting applies a deterministic UUID (primary-key) tiebreaker, so rows with equal primary-sort values page consistently across the Emails, Templates, and Blocklist lists. (#13)
Changed
- Archiver body compression truly streams via
Repo.streamin a transaction (was loading the full result set and only compressing the first batch); CSV exports route every cell through formula-injection + RFC 4180 escaping;list_logsno longer preloads[:user, :events]on the admin hot path; PubSub status updates refresh a single row instead of reloading the list. (#12) - Adopt
phoenix_kit1.7.165 (provides the core migration backing the email-event dedup unique indexes).
0.1.7 - 2026-06-23
Added
- Live-update the Emails admin list on delivery-status changes via PubSub.
Log.update_log/2broadcasts a lightweight{:email_log_updated, …}event only when a log's status actually changes; the emails LiveView refreshes just the affected on-screen row (no 30-day stats recompute). Best-effort — a PubSub failure can never break the DB write. (#11)
Fixed
- Consolidate SQS polling onto a single Oban-based poller: remove the legacy 842-line
SQSWorkerGenServer.SQSPollingJob+SQSPollingManagerare now the sole poller and runtime control surface (enable/disable without an app restart). (#11) - Self-scheduling no longer stalls: the polling job's
uniqueconstraint excludes running jobs, so an executing job can enqueue its successor and a crash-orphaned job can't permanently block new inserts. (#11) - SQS messages no longer re-cycle forever:
delete_message/3returns failures instead of swallowing them as:ok, reads both string and atom receipt-handle keys, and won't count an undeleted message as processed. (#11) - The admin SQS-polling toggle now starts/stops the poller at runtime (routed through
SQSPollingManager) instead of only persisting the flag and waiting for the next boot. (#11) - Provider detection classifies a message as
aws_seswhen an SES configuration set is configured, even when the host app sends through its own Swoosh mailer. (#11) - Post-merge review fixes: compile clean under
--warnings-as-errorswith Oban 2.23 (narrow the polling job'suniquestates to[:scheduled]), satisfycredo --strictfor the new broadcast helper, and drop a stale retiredearmarkentry from the lockfile.
Changed
- Refresh dependency lockfile (notable bumps:
oban→ 2.23,phoenix_kit→ 1.7.164,phoenix_live_view→ 1.2,swoosh→ 1.26,tesla→ 1.20,bandit→ 1.12,req).
0.1.6 - 2026-05-25
Added
- Route all 9 Emails admin LiveViews through the per-module
PhoenixKit.Modules.Emails.Gettextbackend, so this package'sru/etcatalogues resolve at render time instead of falling back to English. Extends gettext coverage across the full template surface (IAM/SES setup walkthrough, template editor, blocklist, metrics, queue);default.potgrows to 447 msgids. (#9) - Localise ~100
put_flashmessages across the Emails LiveViews (settings toggles, errors, confirmations) with%{var}interpolation bindings anden/ru/ettranslations. (#10)
Fixed
- Correct gettext catalogue mis-fills from the bulk regeneration: 12
enentries wheremsgstr≠msgid, and 7ru/etcross-locale mistranslations (e.g. the "Setup AWS Infrastructure" button rendering a stray "3." step prefix; Archive/Clone template tooltips reading "New Template";Queuedstatus showing "Queue").
Changed
- Require
phoenix_kit ~> 1.7.106(per-module Gettext backend API). - Refresh dependency lockfile (notable bumps:
phoenix_kit1.7.108→1.7.120,ecto/ecto_sql3.13→3.14,fresco0.1→0.6 plus newetcher,tesla1.17→1.18,hammer7.3→7.4,bandit,plug,req).
0.1.5 - 2026-05-12
Added
- Wrap Emails settings and email tracking UI strings in
gettext(47 new msgids indefault.pot,en,ru,etcatalogues). Covers tracking-options toggle labels, data retention block, privacy notice, current configuration table, tracking-benefits headers, IAM/SES setup walkthrough, and remaining placeholders.
Changed
- Widen Emails settings page to use the full container width on wide screens (drop the
max-w-4xl mx-autowrapper). Short numeric inputs keep theirmax-w-xscaps. - Refresh dependency lockfile to latest compatible versions (notable bumps:
finch0.21→0.22,postgrex0.22.1→0.22.2,swoosh1.25.1→1.25.2,phoenix_kit1.7.106→1.7.108,telemetry1.4.1→1.4.2).
0.1.4 - 2026-05-08
Added
- Per-module Gettext backend (
PhoenixKit.Modules.Emails.Gettext) withen/ru/etcatalogues for all admin sidebar tab labels. Requiresphoenix_kitrelease that ships thegettext_backendTab API (BeamLabEU/phoenix_kit#522); on older releases tabs render raw English (graceful degradation).
Fixed
- Suppress
EmailInterceptorLogger warnings when the configured Swoosh adapter is not AWS SES.
Changed
- Refresh dependency lockfile to latest compatible versions (notable bumps:
bandit,db_connection,decimal,ecto,ex_doc).
0.1.3 - 2026-04-12
Fixed
- Add routing anti-pattern warning to AGENTS.md
All notable changes to this project will be documented in this file.
This project adheres to Semantic Versioning.
0.1.2 - 2026-04-02
Fixed
- Changed
css_sources/0return type from atom to binary to matchPhoenixKit.Modulebehaviour callback spec.
Changed
- Rewrote README to match sibling project structure with full documentation.
0.1.1 - 2026-03-27
Fixed
- Removed
@behaviourand@implannotations fromProviderto fix compilation warnings (behaviour defined in host app). - Suppressed
Hammerundefined module warning inWebhookController.
Changed
- Rewrote install task to automatically add Tailwind CSS
@sourcedirective toapp.css(idempotent). - Updated
.gitignorewith standard Elixir project entries.
0.1.0 - 2026-03-24
Added
- Initial extraction from PhoenixKit core into a standalone package.
PhoenixKit.Email.Providerbehaviour with 14 callbacks.- AWS SES integration for email sending via SMTP and API.
- AWS SNS webhook processing for bounce, complaint, and delivery notifications.
- AWS SQS polling for asynchronous event ingestion.
- Email tracking and analytics (opens, clicks, deliveries, bounces, complaints).
- 9 admin LiveViews: dashboard, logs, templates, campaigns, recipients, settings, domains, blocklist, tracking.
- Email template management with variable interpolation.
- CSV and JSON export for email logs and analytics.
- Swoosh interceptor for automatic email tracking.
- Rate limiting on webhook endpoints via Hammer.
- SNS signature verification for webhook security.
- CSV formula injection protection in exports.
- Install mix task (
mix phoenix_kit_emails.install).