Packages

phoenix_kit

1.7.153
1.7.208 1.7.207 1.7.206 1.7.205 1.7.204 1.7.203 1.7.202 1.7.201 1.7.200 1.7.199 1.7.198 1.7.197 1.7.196 1.7.194 1.7.193 1.7.192 1.7.191 1.7.190 1.7.189 1.7.187 1.7.186 1.7.185 1.7.184 1.7.183 1.7.182 1.7.181 1.7.180 1.7.179 1.7.178 1.7.177 1.7.176 1.7.175 1.7.174 1.7.173 1.7.172 1.7.171 1.7.170 1.7.169 1.7.168 1.7.167 1.7.166 1.7.165 1.7.164 1.7.162 1.7.161 1.7.160 1.7.159 1.7.157 1.7.156 1.7.155 1.7.154 1.7.153 1.7.152 1.7.151 1.7.150 1.7.149 1.7.146 1.7.145 1.7.144 1.7.143 1.7.138 1.7.133 1.7.132 1.7.131 1.7.130 1.7.128 1.7.126 1.7.125 1.7.121 1.7.120 1.7.119 1.7.118 1.7.117 1.7.116 1.7.115 1.7.114 1.7.113 1.7.112 1.7.111 1.7.110 1.7.109 1.7.108 1.7.107 1.7.106 1.7.105 1.7.104 1.7.103 1.7.102 1.7.101 1.7.100 1.7.99 1.7.98 1.7.97 1.7.96 1.7.95 1.7.94 1.7.93 1.7.92 1.7.91 1.7.90 1.7.89 1.7.88 1.7.87 1.7.86 1.7.85 1.7.84 1.7.83 1.7.82 1.7.81 1.7.80 1.7.79 1.7.78 1.7.77 1.7.76 1.7.75 1.7.74 1.7.71 1.7.70 1.7.69 1.7.66 1.7.65 1.7.64 1.7.63 1.7.62 1.7.61 1.7.59 1.7.58 1.7.57 1.7.56 1.7.55 1.7.54 1.7.53 1.7.52 1.7.51 1.7.49 1.7.44 1.7.43 1.7.42 1.7.41 1.7.39 1.7.38 1.7.37 1.7.36 1.7.34 1.7.33 1.7.31 1.7.30 1.7.29 1.7.28 1.7.27 1.7.26 1.7.25 1.7.24 1.7.23 1.7.22 1.7.21 1.7.20 1.7.19 1.7.18 1.7.17 1.7.16 1.7.15 1.7.14 1.7.13 1.7.12 1.7.11 1.7.10 1.7.9 1.7.8 1.7.7 1.7.6 1.7.5 1.7.4 1.7.3 1.7.2 1.7.1 1.7.0 1.6.20 1.6.19 1.6.18 1.6.17 1.6.16 1.6.15 1.6.14 1.6.13 1.6.12 1.6.11 1.6.10 1.6.9 1.6.8 1.6.7 1.6.6 1.6.5 1.6.4 1.6.3 1.5.2 1.5.1 1.5.0 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.3.2 1.3.1 1.3.0 1.2.10 1.2.9 1.2.8 1.2.7 1.2.5 1.2.4 1.2.2 1.2.1 1.2.0 1.1.0 1.0.0

A foundation for building Elixir Phoenix apps — SaaS, social networks, ERP systems, marketplaces, and more

Current section

Files

Jump to
phoenix_kit lib phoenix_kit migrations postgres v07.ex
Raw

lib/phoenix_kit/migrations/postgres/v07.ex

defmodule PhoenixKit.Migrations.Postgres.V07 do
@moduledoc """
PhoenixKit V07 Migration: Email System
This migration introduces comprehensive email tracking capabilities including
logging of outgoing emails, event tracking (open, click, bounce), and
integration with AWS SES for delivery monitoring.
## Changes
### Email System
- Adds phoenix_kit_email_logs table for comprehensive email logging
- Adds phoenix_kit_email_events table for tracking delivery events
- Supports AWS SES integration with configuration sets
- Provides detailed analytics and monitoring capabilities
- Includes rate limiting and security features
### New Tables
- **phoenix_kit_email_logs**: Main email logging with extended metadata
- **phoenix_kit_email_events**: Event tracking (open, click, bounce, complaint)
## PostgreSQL Support
- Supports PostgreSQL prefix for schema isolation
- Optimized indexes for performance
- JSONB fields for flexible metadata storage
"""
use Ecto.Migration
@doc """
Run the V07 migration to add email tracking system.
"""
def up(%{prefix: prefix} = _opts) do
# Create emails table
create_if_not_exists table(:phoenix_kit_email_logs, prefix: prefix) do
# Unique ID from email provider
add :message_id, :string, null: false
# Recipient email
add :to, :string, null: false
# Sender email
add :from, :string, null: false
# Email subject
add :subject, :string, null: true
# JSONB headers without duplication
add :headers, :map, null: true, default: %{}
# First 500+ characters preview
add :body_preview, :text, null: true
# Full email body (optional)
add :body_full, :text, null: true
# Email template identifier
add :template_name, :string, null: true
# Campaign/group identifier
add :campaign_id, :string, null: true
# Number of attachments
add :attachments_count, :integer, null: false, default: 0
# Email size in bytes
add :size_bytes, :integer, null: true
# Send retry attempts
add :retry_count, :integer, null: false, default: 0
# Error message if failed
add :error_message, :text, null: true
# sent, delivered, bounced, opened, clicked, failed
add :status, :string, null: false, default: "sent"
# Send timestamp
add :sent_at, :utc_datetime_usec, null: false, default: fragment("NOW()")
# Delivery timestamp
add :delivered_at, :utc_datetime_usec, null: true
# AWS SES configuration set
add :configuration_set, :string, null: true
# JSONB tags for grouping
add :message_tags, :map, null: true, default: %{}
# aws_ses, smtp, local, etc.
add :provider, :string, null: false, default: "unknown"
# FK to users for auth integration
add :user_id, :integer, null: true
# Timestamps for tracking record creation/update
timestamps(type: :utc_datetime_usec)
end
# Create email events table
create_if_not_exists table(:phoenix_kit_email_events, prefix: prefix) do
# FK to email_logs
add :email_log_id, :integer, null: false
# open, click, bounce, complaint, delivery, send
add :event_type, :string, null: false
# JSONB event-specific data
add :event_data, :map, null: true, default: %{}
# Event timestamp
add :occurred_at, :utc_datetime_usec, null: false, default: fragment("NOW()")
# IP for open/click events
add :ip_address, :string, null: true
# User agent for open/click
add :user_agent, :string, null: true
# JSONB geo data (country, region, city)
add :geo_location, :map, null: true, default: %{}
# URL for click events
add :link_url, :string, null: true
# hard, soft for bounce events
add :bounce_type, :string, null: true
# abuse, auth-failure, fraud, etc.
add :complaint_type, :string, null: true
# Timestamps for tracking record creation/update
timestamps(type: :utc_datetime_usec)
end
# Create indexes for email_logs table
# Performance indexes for common queries
create_if_not_exists index(:phoenix_kit_email_logs, [:to, :sent_at],
prefix: prefix,
name: :phoenix_kit_email_logs_to_sent_at_idx
)
create_if_not_exists index(:phoenix_kit_email_logs, [:status, :sent_at],
prefix: prefix,
name: :phoenix_kit_email_logs_status_sent_at_idx
)
create_if_not_exists index(:phoenix_kit_email_logs, [:sent_at],
prefix: prefix,
name: :phoenix_kit_email_logs_sent_at_idx
)
# Unique constraint on message_id
create_if_not_exists unique_index(:phoenix_kit_email_logs, [:message_id],
prefix: prefix,
name: :phoenix_kit_email_logs_message_id_uidx
)
# Indexes for filtering and analytics
create_if_not_exists index(:phoenix_kit_email_logs, [:user_id],
prefix: prefix,
name: :phoenix_kit_email_logs_user_id_idx
)
create_if_not_exists index(:phoenix_kit_email_logs, [:campaign_id],
prefix: prefix,
name: :phoenix_kit_email_logs_campaign_id_idx
)
create_if_not_exists index(:phoenix_kit_email_logs, [:template_name],
prefix: prefix,
name: :phoenix_kit_email_logs_template_name_idx
)
create_if_not_exists index(:phoenix_kit_email_logs, [:provider, :sent_at],
prefix: prefix,
name: :phoenix_kit_email_logs_provider_sent_at_idx
)
# Create indexes for email_events table
create_if_not_exists index(:phoenix_kit_email_events, [:email_log_id],
prefix: prefix,
name: :phoenix_kit_email_events_email_log_id_idx
)
create_if_not_exists index(:phoenix_kit_email_events, [:event_type, :occurred_at],
prefix: prefix,
name: :phoenix_kit_email_events_type_occurred_at_idx
)
create_if_not_exists index(:phoenix_kit_email_events, [:occurred_at],
prefix: prefix,
name: :phoenix_kit_email_events_occurred_at_idx
)
# Add foreign key constraint for email_events to email_logs
alter table(:phoenix_kit_email_events, prefix: prefix) do
modify :email_log_id,
references(:phoenix_kit_email_logs, on_delete: :delete_all, prefix: prefix)
end
# Set version comment on phoenix_kit table for version tracking
execute "COMMENT ON TABLE #{prefix_table_name("phoenix_kit", prefix)} IS '7'"
end
# Helper function to build table name with prefix
defp prefix_table_name(table_name, nil), do: table_name
defp prefix_table_name(table_name, prefix), do: "#{prefix}.#{table_name}"
def down(%{prefix: prefix} = _opts) do
# Drop indexes first
drop_if_exists index(:phoenix_kit_email_events, [:occurred_at],
prefix: prefix,
name: :phoenix_kit_email_events_occurred_at_idx
)
drop_if_exists index(:phoenix_kit_email_events, [:event_type, :occurred_at],
prefix: prefix,
name: :phoenix_kit_email_events_type_occurred_at_idx
)
drop_if_exists index(:phoenix_kit_email_events, [:email_log_id],
prefix: prefix,
name: :phoenix_kit_email_events_email_log_id_idx
)
drop_if_exists index(:phoenix_kit_email_logs, [:provider, :sent_at],
prefix: prefix,
name: :phoenix_kit_email_logs_provider_sent_at_idx
)
drop_if_exists index(:phoenix_kit_email_logs, [:template_name],
prefix: prefix,
name: :phoenix_kit_email_logs_template_name_idx
)
drop_if_exists index(:phoenix_kit_email_logs, [:campaign_id],
prefix: prefix,
name: :phoenix_kit_email_logs_campaign_id_idx
)
drop_if_exists index(:phoenix_kit_email_logs, [:user_id],
prefix: prefix,
name: :phoenix_kit_email_logs_user_id_idx
)
drop_if_exists index(:phoenix_kit_email_logs, [:message_id],
prefix: prefix,
name: :phoenix_kit_email_logs_message_id_uidx
)
drop_if_exists index(:phoenix_kit_email_logs, [:sent_at],
prefix: prefix,
name: :phoenix_kit_email_logs_sent_at_idx
)
drop_if_exists index(:phoenix_kit_email_logs, [:status, :sent_at],
prefix: prefix,
name: :phoenix_kit_email_logs_status_sent_at_idx
)
drop_if_exists index(:phoenix_kit_email_logs, [:to, :sent_at],
prefix: prefix,
name: :phoenix_kit_email_logs_to_sent_at_idx
)
# Drop email events table (foreign key will be dropped automatically)
drop_if_exists table(:phoenix_kit_email_events, prefix: prefix)
# Drop emails table
drop_if_exists table(:phoenix_kit_email_logs, prefix: prefix)
# Set version comment back to V06
execute "COMMENT ON TABLE #{prefix_table_name("phoenix_kit", prefix)} IS '6'"
end
end