PhoenixKitEmails

ElixirLicense: MIT

Email tracking, analytics, and AWS SES integration for PhoenixKit. Drop-in email logging, delivery event tracking, engagement metrics, templating, rate limiting, and an admin dashboard.

Features

⚠️ Email templates are moving to files

Message templates are moving out of phoenix_kit_email_templates and into files a host owns in its own repository — version-controlled and reviewable, rather than edited through an admin UI and invisible to code review. Core reads them through phoenix_kit_templates.

Nothing has changed yet. The database layer still wins at send time and every customized template works exactly as it does today. But a later release drops the table, and edits that have not been exported will be lost then.

If you have customized any email template:

mix phoenix_kit_emails.templates.export # --dry-run to preview first

Review the diff and commit the files. Nothing is deleted and no row is touched, so an export that turns out wrong costs nothing but the files.

The task exports only what you actually edited. A template still identical to what this package ships is skipped, because core supplies those itself now, translated into every shipped locale. On an install that never opened the template editor it writes nothing at all, and you can stop reading here.

Newsletter layouts (is_system: false, picked per broadcast) are not affected — those are authored at runtime by people who cannot open a pull request, so they keep a table and an editor.

What the files look like

The template name becomes a directory; each part is a file, and any locale that is not the fallback carries its code:

priv/phoenix_kit_templates/
└── register/
├── subject.txt # the fallback locale — what everyone falls through to
├── subject.uk.txt
├── text.txt
└── html.html

Installation

Add phoenix_kit_emails to your dependencies in mix.exs:

def deps do
[
{:phoenix_kit_emails, "~> 0.2"}
]
end

Then fetch dependencies:

mix deps.get

Note: For development or if not yet published to Hex, you can use:

{:phoenix_kit_emails, github: "BeamLabEU/phoenix_kit_emails"}

PhoenixKit auto-discovers the module at startup — no additional configuration needed.

Quick Start

  1. Add the dependency to mix.exs
  2. Run mix deps.get
  3. Enable the module in admin settings (email_enabled: true)
  4. Configure your AWS SES configuration set name in settings
  5. Email logs and analytics are available at /admin/emails

Usage

System management

alias PhoenixKit.Modules.Emails
# Check if system is enabled
Emails.enabled?()
# Enable/disable the system
Emails.enable_system()
Emails.disable_system()
# Get current configuration
config = Emails.get_config()

Email logging

# Create a log entry
{:ok, log} = Emails.create_log(%{
to: "user@example.com",
from: "noreply@example.com",
subject: "Welcome!",
status: "sent"
})
# List logs with filters
logs = Emails.list_logs(%{status: "sent", page: 1})
# Get a specific log
log = Emails.get_log!(log_uuid)

Analytics

# Get system statistics
stats = Emails.get_system_stats(:last_30_days)
# => %{total_sent: 5000, delivered: 4850, bounce_rate: 2.5, open_rate: 23.4}
# Get campaign performance
campaign_stats = Emails.get_campaign_stats("newsletter_2024")
# => %{total_sent: 1000, delivery_rate: 98.5, open_rate: 25.2, click_rate: 4.8}
# Get engagement metrics
metrics = Emails.get_engagement_metrics(:last_7_days)
# Get provider performance comparison
performance = Emails.get_provider_performance(:last_30_days)

Webhook processing

# Process an incoming webhook from AWS SES
{:ok, event} = Emails.process_webhook_event(webhook_data)
# List events for a specific log
events = Emails.list_events_for_log(log_uuid)

Maintenance

# Clean up old logs (by retention days)
{deleted_count, _} = Emails.cleanup_old_logs(90)
# Compress old email bodies to save storage
Emails.compress_old_bodies(30)
# Archive old data to S3
Emails.archive_to_s3(180)

Settings

Settings are managed through the PhoenixKit Settings API and can be configured via the admin UI at /admin/settings/email-sending.

KeyTypeDefaultDescription
email_enabledbooleanfalseEnable/disable the email system
email_save_bodybooleanfalseSave full email body (vs preview only)
email_save_headersbooleanfalseSave email headers
email_ses_eventsbooleanfalseManage AWS SES delivery events
email_retention_daysinteger90Days to keep email logs
aws_ses_configuration_setstringAWS SES configuration set name
email_compress_bodyintegerCompress body after N days
email_archive_to_s3booleanfalseEnable S3 archival
email_s3_bucketstringS3 bucket archives are written to
email_s3_integrationstringIntegrations UUID that signs uploads (unset = ExAws chain)
email_sampling_rateintegerPercentage of emails to fully log
email_create_placeholder_logsbooleanfalseCreate placeholder logs for orphaned events

Permissions

The module declares permissions via permission_metadata/0:

Use Scope.has_module_access?/2 to check permissions in your application.

Architecture

lib/
mix/tasks/
phoenix_kit_emails.install.ex # Install mix task
phoenix_kit/modules/emails/
emails.ex # Context + PhoenixKit.Module behaviour
application_integration.ex # Application-level integration
archiver.ex # S3 archival logic
archive_worker.ex # Hourly Oban cron that calls the archiver
email_log_data.ex # Email log data struct
event.ex # Delivery/bounce/complaint event schema
interceptor.ex # Email interceptor for logging
log.ex # Email log schema
metrics.ex # Analytics and metrics queries
paths.ex # Centralized URL path helpers
provider.ex # Provider behaviour
rate_limiter.ex # Rate limiting via Hammer
sqs_polling_job.ex # Oban job for SQS polling
sqs_polling_manager.ex # SQS polling lifecycle management
sqs_processor.ex # SQS message processing
supervisor.ex # OTP Supervisor
table_columns.ex # Admin table column definitions
template.ex # Email template schema
templates.ex # Template management context
utils.ex # Shared utilities
web/
blocklist.ex # Blocklist admin LiveView
details.ex # Email log detail LiveView
emails.ex # Email logs admin LiveView
email_tracking.ex # Open/click tracking
export_controller.ex # CSV export controller
metrics.ex # Metrics dashboard LiveView
queue.ex # Queue management LiveView
routes.ex # Route definitions
settings.ex # Settings admin LiveView
template_editor.ex # Template editor LiveView
templates.ex # Templates admin LiveView
webhook_controller.ex # Webhook endpoint controller

Database Tables

TableDescription
phoenix_kit_email_logsEmail log records (UUIDv7 PK)
phoenix_kit_email_eventsDelivery/bounce/complaint/open/click events
phoenix_kit_email_templatesReusable email templates

Development

mix deps.get # Install dependencies
mix test # Run tests
mix format # Format code
mix credo --strict # Static analysis (strict mode)
mix dialyzer # Type checking
mix docs # Generate documentation
mix precommit # Compile + format + credo + dialyzer
mix quality # Format + credo + dialyzer

Troubleshooting

Emails not appearing in admin

SES events not processing

Metrics showing zero data

License

MIT — see LICENSE for details.