# PhoenixKitEmails
[](https://elixir-lang.org)
[](LICENSE.md)
Email tracking, analytics, and AWS SES integration for [PhoenixKit](https://github.com/BeamLabEU/phoenix_kit). Drop-in email logging, delivery event tracking, engagement metrics, templating, rate limiting, and an admin dashboard.
## Features
- **Email logging** — comprehensive logging of all outgoing emails with optional body/header storage
- **AWS SES integration** — SQS-based event polling for delivery, bounce, complaint, open, and click events
- **Analytics & metrics** — system stats, engagement rates, campaign performance, and provider comparison
- **Email templates** — create and manage reusable email templates with a LiveView editor
- **Rate limiting** — configurable protection against abuse and spam via [Hammer](https://github.com/ExHammer/hammer)
- **Blocklist** — manage blocked email addresses
- **Queue management** — view and manage outgoing email queue
- **Archival** — automatic cleanup, body compression, and S3 archival of old email data
- **Webhook processing** — process incoming delivery/bounce/complaint webhooks
- **CSV export** — export email logs via controller endpoint
- **Email open/click tracking** — pixel tracking and link rewriting for engagement metrics
- **Admin dashboard** — LiveView pages for logs, metrics, templates, queue, blocklist, and settings
- **Auto-discovery** — implements `PhoenixKit.Module` behaviour; PhoenixKit finds it at startup with zero config
## Installation
Add `phoenix_kit_emails` to your dependencies in `mix.exs`:
```elixir
def deps do
[
{:phoenix_kit_emails, "~> 0.1"}
]
end
```
Then fetch dependencies:
```bash
mix deps.get
```
> **Note:** For development or if not yet published to Hex, you can use:
> ```elixir
> {: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
```elixir
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
```elixir
# 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
```elixir
# 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
```elixir
# 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
```elixir
# 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/emails`.
| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `email_enabled` | boolean | `false` | Enable/disable the email system |
| `email_save_body` | boolean | `false` | Save full email body (vs preview only) |
| `email_save_headers` | boolean | `false` | Save email headers |
| `email_ses_events` | boolean | `false` | Manage AWS SES delivery events |
| `email_retention_days` | integer | `90` | Days to keep email logs |
| `aws_ses_configuration_set` | string | — | AWS SES configuration set name |
| `email_compress_body` | integer | — | Compress body after N days |
| `email_archive_to_s3` | boolean | `false` | Enable S3 archival |
| `email_sampling_rate` | integer | — | Percentage of emails to fully log |
| `email_create_placeholder_logs` | boolean | `false` | Create placeholder logs for orphaned events |
## Permissions
The module declares permissions via `permission_metadata/0`:
- `"emails"` — access to email admin dashboard and all sub-pages
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
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
sqs_worker.ex # SQS worker process
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
| Table | Description |
|-------|-------------|
| `phoenix_kit_email_logs` | Email log records (UUIDv7 PK) |
| `phoenix_kit_email_events` | Delivery/bounce/complaint/open/click events |
| `phoenix_kit_email_templates` | Reusable email templates |
## Development
```bash
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
- Verify `email_enabled` is `true` in settings
- Ensure the module is listed as a dependency in the parent app's `mix.exs`
### SES events not processing
- Verify `email_ses_events` is enabled in settings
- Check that `aws_ses_configuration_set` is configured
- Ensure SQS queue permissions allow the application to poll
- Review Oban dashboard for failed SQS polling jobs
### Metrics showing zero data
- Confirm emails are being logged (check `/admin/emails`)
- Verify the date range filter matches when emails were sent
## License
MIT — see [LICENSE](LICENSE.md) for details.
## Links
- [GitHub](https://github.com/BeamLabEU/phoenix_kit_emails)
- [PhoenixKit](https://github.com/BeamLabEU/phoenix_kit)