Packages
phoenix_kit
1.4.2
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
Current section
Files
lib/phoenix_kit/install/mailer_config.ex
defmodule PhoenixKit.Install.MailerConfig do
use PhoenixKit.Install.IgniterCompat
@moduledoc """
Handles mailer configuration for PhoenixKit installation.
This module provides functionality to:
- Configure development mailer with Swoosh.Adapters.Local
- Add production mailer templates for various providers
- Generate appropriate notices for mailer setup
"""
alias Igniter.Project.Config
alias PhoenixKit.Install.FinchSetup
alias PhoenixKit.Install.RuntimeDetector
@doc """
Adds PhoenixKit mailer configuration for development and production.
Now supports both delegation mode and built-in mode:
- **Delegation mode**: Configure PhoenixKit to use parent app's mailer
- **Built-in mode**: Configure PhoenixKit's own mailer (legacy)
## Parameters
- `igniter` - The igniter context
## Returns
Updated igniter with mailer configuration and notices.
"""
def add_mailer_configuration(igniter) do
igniter
|> add_mailer_delegation_config()
|> add_prod_mailer_config()
|> FinchSetup.add_finch_configuration()
|> add_mailer_production_notice()
end
# Add mailer delegation configuration - detects and uses parent app's mailer
defp add_mailer_delegation_config(igniter) do
parent_app = get_parent_app_name()
case detect_parent_mailer(parent_app) do
{:ok, parent_mailer} ->
# Configure PhoenixKit to use parent app's mailer
Config.configure_new(
igniter,
"config.exs",
:phoenix_kit,
[:mailer],
parent_mailer
)
:not_found ->
# Fall back to built-in PhoenixKit mailer
add_dev_mailer_config(igniter)
end
end
# Add Local mailer adapter for development - supports both dev.exs and runtime.exs
defp add_dev_mailer_config(igniter) do
case RuntimeDetector.detect_config_pattern() do
:runtime ->
add_runtime_mailer_config(igniter)
:dev_exs ->
add_simple_dev_mailer_config(igniter)
:config_exs ->
add_config_exs_mailer_config(igniter)
end
end
# Add mailer config to runtime.exs file
defp add_runtime_mailer_config(igniter) do
case RuntimeDetector.find_insertion_point() do
{:runtime, line_number} ->
insert_into_runtime_file(igniter, line_number)
{:dev_exs, line_number} ->
add_simple_dev_mailer_config_at_line(igniter, line_number)
{:config_exs, line_number} ->
add_config_exs_mailer_config_at_line(igniter, line_number)
end
end
# Simple dev.exs configuration (legacy behavior)
defp add_simple_dev_mailer_config(igniter) do
Config.configure_new(
igniter,
"dev.exs",
:phoenix_kit,
[PhoenixKit.Mailer],
adapter: Swoosh.Adapters.Local
)
end
# Add mailer config to config.exs with environment check
defp add_config_exs_mailer_config(igniter) do
config_content = """
# PhoenixKit mailer configuration
if config_env() == :dev do
config :phoenix_kit, PhoenixKit.Mailer,
adapter: Swoosh.Adapters.Local
end
"""
# Try to append to config.exs, fall back to notice if it fails
try do
Igniter.update_file(igniter, "config/config.exs", fn source ->
current_content = Rewrite.Source.get(source, :content)
updated_content = current_content <> "\n" <> config_content
Rewrite.Source.update(source, :content, updated_content)
end)
rescue
_ ->
add_runtime_config_notice(igniter)
end
end
# Insert mailer config into runtime.exs file
defp insert_into_runtime_file(igniter, line_number) do
mailer_config = """
# PhoenixKit mailer configuration
config :phoenix_kit, PhoenixKit.Mailer,
adapter: Swoosh.Adapters.Local
"""
try do
Igniter.update_file(igniter, "config/runtime.exs", fn source ->
current_content = Rewrite.Source.get(source, :content)
lines = String.split(current_content, "\n")
# Insert at the specified line
{before_lines, after_lines} = Enum.split(lines, line_number - 1)
updated_content =
before_lines ++
[mailer_config] ++
after_lines
|> Enum.join("\n")
Rewrite.Source.update(source, :content, updated_content)
end)
rescue
_ ->
# Fallback to simple notice if insertion fails
add_runtime_config_notice(igniter)
end
end
# Add dev mailer config at specific line number
defp add_simple_dev_mailer_config_at_line(igniter, line_number) do
mailer_config = """
# PhoenixKit mailer configuration
config :phoenix_kit, PhoenixKit.Mailer,
adapter: Swoosh.Adapters.Local
"""
try do
Igniter.update_file(igniter, "config/dev.exs", fn source ->
current_content = Rewrite.Source.get(source, :content)
lines = String.split(current_content, "\n")
# Insert at the specified line
{before_lines, after_lines} = Enum.split(lines, line_number - 1)
updated_content =
before_lines ++
[mailer_config] ++
after_lines
|> Enum.join("\n")
Rewrite.Source.update(source, :content, updated_content)
end)
rescue
_ ->
# Fallback to default behavior
add_simple_dev_mailer_config(igniter)
end
end
# Add config_exs mailer config at specific line number
defp add_config_exs_mailer_config_at_line(igniter, line_number) do
mailer_config = """
# PhoenixKit mailer configuration
if config_env() == :dev do
config :phoenix_kit, PhoenixKit.Mailer,
adapter: Swoosh.Adapters.Local
end
"""
try do
Igniter.update_file(igniter, "config/config.exs", fn source ->
current_content = Rewrite.Source.get(source, :content)
lines = String.split(current_content, "\n")
# Insert at the specified line
{before_lines, after_lines} = Enum.split(lines, line_number - 1)
updated_content =
before_lines ++
[mailer_config] ++
after_lines
|> Enum.join("\n")
Rewrite.Source.update(source, :content, updated_content)
end)
rescue
_ ->
# Fallback to notice
add_runtime_config_notice(igniter)
end
end
# Get the parent application name
defp get_parent_app_name do
Mix.Project.config()[:app]
end
# Detect parent application's mailer module
defp detect_parent_mailer(app_name) do
app_module = app_name |> to_string() |> Macro.camelize()
# Common mailer module patterns
mailer_candidates = [
Module.concat([app_module, "Mailer"]),
Module.concat([app_module <> "Web", "Mailer"])
]
# Find the first existing mailer module
mailer_candidates
|> Enum.find(&mailer_module_exists?/1)
|> case do
nil -> :not_found
mailer -> {:ok, mailer}
end
end
# Check if a mailer module exists in the project
defp mailer_module_exists?(module) do
case Code.ensure_compiled(module) do
{:module, _} -> function_exported?(module, :deliver, 1)
_ -> false
end
rescue
_ -> false
end
# Add production mailer configuration template as comments
defp add_prod_mailer_config(igniter) do
prod_config_template = get_prod_mailer_template()
if File.exists?("config/prod.exs") do
# Check if PhoenixKit mailer config already exists before appending
Igniter.update_file(igniter, "config/prod.exs", fn source ->
try do
current_content = Rewrite.Source.get(source, :content)
# Only add template if PhoenixKit mailer config doesn't already exist
if String.contains?(current_content, "# Configure PhoenixKit mailer for production") do
# Config already exists, no changes needed
source
else
# Add the template
updated_content = current_content <> "\n" <> prod_config_template
Rewrite.Source.update(source, :content, updated_content)
end
rescue
_ ->
# Fallback: just return original source if there's an error
source
end
end)
else
# Create prod.exs with import Config and template
initial_content = "import Config\n" <> prod_config_template
Igniter.create_new_file(igniter, "config/prod.exs", initial_content)
end
end
# Get production mailer configuration template
defp get_prod_mailer_template do
"""
# Configure PhoenixKit mailer for production
#
# IMPORTANT: Configure sender email address
# config :phoenix_kit,
# from_email: "noreply@yourcompany.com",
# from_name: "Your Company Name"
# OPTION 1 (RECOMMENDED): Use your app's existing mailer
# PhoenixKit will automatically use your app's mailer if configured with:
# config :phoenix_kit, mailer: MyApp.Mailer
#
# Then configure your app's mailer as usual:
# config :my_app, MyApp.Mailer,
# adapter: Swoosh.Adapters.SMTP,
# relay: "smtp.sendgrid.net",
# username: System.get_env("SENDGRID_USERNAME"),
# password: System.get_env("SENDGRID_PASSWORD"),
# port: 587,
# auth: :always,
# tls: :always
# OPTION 2 (LEGACY): Configure PhoenixKit's built-in mailer
# Uncomment and configure the adapter you want to use:
# SMTP configuration (recommended for most providers)
# config :phoenix_kit, PhoenixKit.Mailer,
# adapter: Swoosh.Adapters.SMTP,
# relay: "smtp.sendgrid.net",
# username: System.get_env("SENDGRID_USERNAME"),
# password: System.get_env("SENDGRID_PASSWORD"),
# port: 587,
# auth: :always,
# tls: :always
# SendGrid API configuration
# config :phoenix_kit, PhoenixKit.Mailer,
# adapter: Swoosh.Adapters.Sendgrid,
# api_key: System.get_env("SENDGRID_API_KEY")
# Mailgun configuration
# config :phoenix_kit, PhoenixKit.Mailer,
# adapter: Swoosh.Adapters.Mailgun,
# api_key: System.get_env("MAILGUN_API_KEY"),
# domain: System.get_env("MAILGUN_DOMAIN")
# ==========================================
# Amazon SES configuration (COMPLETE SETUP GUIDE)
# ==========================================
# STEP 1: Add required dependencies to mix.exs
# {:gen_smtp, "~> 1.2"} # Required for AWS SES
# {:finch, "~> 0.18"} # Required for HTTP client
#
# Also add :finch to extra_applications in mix.exs:
# extra_applications: [:logger, :runtime_tools, :finch]
# STEP 2: Add Finch to your application supervisor (lib/your_app/application.ex)
# Add this to your children list:
# {Finch, name: Swoosh.Finch}
# STEP 3: Configure Swoosh API client (config/config.exs)
# config :swoosh, :api_client, Swoosh.ApiClient.Finch
#
# ⚠️ IMPORTANT: Check that config/dev.exs does NOT have:
# config :swoosh, :api_client, false
# This setting will override Finch configuration and break AWS SES!
# STEP 4: Configure AWS SES
# For your app's mailer (recommended approach):
# config :your_app, YourApp.Mailer,
# adapter: Swoosh.Adapters.AmazonSES,
# region: "eu-north-1", # or "us-east-1", "us-west-2", etc.
# access_key: System.get_env("AWS_ACCESS_KEY_ID"),
# secret: System.get_env("AWS_SECRET_ACCESS_KEY")
#
# Then configure PhoenixKit to use your mailer:
# config :phoenix_kit,
# mailer: YourApp.Mailer,
# from_email: "noreply@yourcompany.com",
# from_name: "Your Company"
#
# Legacy approach (using PhoenixKit's built-in mailer):
# config :phoenix_kit, PhoenixKit.Mailer,
# adapter: Swoosh.Adapters.AmazonSES,
# region: "eu-north-1",
# access_key: System.get_env("AWS_ACCESS_KEY_ID"),
# secret: System.get_env("AWS_SECRET_ACCESS_KEY")
# STEP 5: AWS SES Setup Checklist
# □ Create AWS IAM user with SES permissions (ses:*)
# □ Verify sender email address in AWS SES Console
# □ Verify recipient email addresses (if in sandbox mode)
# □ Ensure correct AWS region matches your verification
# □ Request production access to send to any email
# □ Set environment variables:
# - AWS_ACCESS_KEY_ID
# - AWS_SECRET_ACCESS_KEY
# - AWS_REGION (optional, defaults to eu-north-1)
# Common AWS SES regions:
# - eu-west-1 (Ireland)
# - us-east-1 (N. Virginia)
# - us-west-2 (Oregon)
# - eu-north-1 (Stockholm)
# TROUBLESHOOTING:
# If you see "function false.post/4 is undefined":
# 1. Check that Finch is in your mix.exs deps: {:finch, "~> 0.18"}
# 2. Check that :finch is in extra_applications
# 3. Check that Swoosh.Finch is in application.ex children
# 4. Make sure there's no "api_client: false" in dev.exs
# 5. Restart your Phoenix server after changes
#
# See full setup guide: docs/AWS_SES_SETUP.md
"""
end
# Add brief notice about mailer configuration
defp add_mailer_production_notice(igniter) do
parent_app = get_parent_app_name()
notice =
case detect_parent_mailer(parent_app) do
{:ok, parent_mailer} ->
"📧 Email configured to use #{inspect(parent_mailer)} (see config/prod.exs for production setup)"
:not_found ->
"📧 Email configured (built-in PhoenixKit.Mailer, see config/prod.exs)"
end
Igniter.add_notice(igniter, notice)
end
# Add notice when runtime configuration cannot be automatically applied
defp add_runtime_config_notice(igniter) do
notice = """
⚠️ Runtime configuration detected
PhoenixKit couldn't automatically configure the mailer due to complex runtime.exs patterns.
Please add this configuration manually to your runtime.exs dev block:
config :phoenix_kit, PhoenixKit.Mailer,
adapter: Swoosh.Adapters.Local
"""
Igniter.add_notice(igniter, notice)
end
end