Packages
phoenix_kit
1.7.112
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/users/auth/user_notifier.ex
defmodule PhoenixKit.Users.Auth.UserNotifier do
@moduledoc """
User notification system for PhoenixKit authentication workflows.
This module handles email delivery for user authentication and account management workflows,
including account confirmation, password reset, and email change notifications.
## Email Types
- **Confirmation instructions**: Sent during user registration
- **Password reset instructions**: Sent when user requests password reset
- **Email update instructions**: Sent when user changes their email address
## Configuration
Configure your mailer in your application config:
config :phoenix_kit, PhoenixKit.Mailer,
adapter: Swoosh.Adapters.SMTP,
# ... other adapter configuration
## Customization
Override this module in your application to customize email templates
and delivery behavior while maintaining the same function signatures.
"""
import Swoosh.Email
alias PhoenixKit.Email.Provider
alias PhoenixKit.Mailer
# Delivers the email using the appropriate mailer.
# Uses the configured parent application mailer if available,
# otherwise falls back to PhoenixKit's built-in mailer.
defp deliver(recipient, subject, text_body, html_body) do
from_email = get_from_email()
from_name = get_from_name()
email =
new()
|> to(recipient)
|> from({from_name, from_email})
|> subject(subject)
|> text_body(text_body)
|> html_body(html_body)
with {:ok, _metadata} <-
Mailer.deliver_email(email,
user_uuid: nil,
template_name: "user_notification",
campaign_id: "authentication"
) do
{:ok, email}
end
end
# Get the from email address from configuration or use a default
# Priority: Settings Database > Config file > Default
defp get_from_email do
# Priority 1: Settings Database (runtime)
case PhoenixKit.Settings.get_setting("from_email") do
nil ->
# Priority 2: Config file (compile-time, fallback)
case PhoenixKit.Config.get(:from_email) do
{:ok, email} -> email
# Priority 3: Default
_ -> "noreply@localhost"
end
email ->
email
end
end
# Get the from name from configuration or use a default
# Priority: Settings Database > Config file > Default
defp get_from_name do
# Priority 1: Settings Database (runtime)
case PhoenixKit.Settings.get_setting("from_name") do
nil ->
# Priority 2: Config file (compile-time, fallback)
case PhoenixKit.Config.get(:from_name) do
{:ok, name} -> name
# Priority 3: Default
_ -> "PhoenixKit"
end
name ->
name
end
end
@doc """
Deliver instructions to confirm account.
Uses the 'register' template from the database if available,
falls back to hardcoded template if not found.
"""
def deliver_confirmation_instructions(user, url) do
# Variables for template substitution
template_variables = %{
"user_email" => user.email,
"confirmation_url" => url
}
# Try to get template from database, fallback to text-only
{subject, html_body, text_body, db_template} =
case Provider.current().get_active_template_by_name("register") do
nil ->
fallback_text = """
Hi #{user.email},
You can confirm your account by visiting the URL below:
#{url}
If you didn't create an account with us, please ignore this.
"""
{"Confirm your account", nil, fallback_text, nil}
template ->
rendered = Provider.current().render_template(template, template_variables)
{rendered.subject, rendered.html_body, rendered.text_body, template}
end
if db_template, do: Provider.current().track_usage(db_template)
deliver(user.email, subject, text_body, html_body)
end
@doc """
Deliver instructions to reset a user password.
Uses the 'reset_password' template from the database if available,
falls back to hardcoded template if not found.
"""
def deliver_reset_password_instructions(user, url) do
# Variables for template substitution
template_variables = %{
"user_email" => user.email,
"reset_url" => url
}
# Try to get template from database, fallback to text-only
{subject, html_body, text_body, db_template} =
case Provider.current().get_active_template_by_name("reset_password") do
nil ->
fallback_text = """
Hi #{user.email},
You can reset your password by visiting the URL below:
#{url}
If you didn't request this change, please ignore this.
"""
{"Reset your password", nil, fallback_text, nil}
template ->
rendered = Provider.current().render_template(template, template_variables)
{rendered.subject, rendered.html_body, rendered.text_body, template}
end
if db_template, do: Provider.current().track_usage(db_template)
deliver(user.email, subject, text_body, html_body)
end
@doc """
Deliver instructions to update a user email.
Uses the 'update_email' template from the database if available,
falls back to hardcoded template if not found.
"""
def deliver_update_email_instructions(user, url) do
# Variables for template substitution
template_variables = %{
"user_email" => user.email,
"update_url" => url
}
# Try to get template from database, fallback to text-only
{subject, html_body, text_body, db_template} =
case Provider.current().get_active_template_by_name("update_email") do
nil ->
fallback_text = """
Hi #{user.email},
You can change your email by visiting the URL below:
#{url}
If you didn't request this change, please ignore this.
"""
{"Confirm your email change", nil, fallback_text, nil}
template ->
rendered = Provider.current().render_template(template, template_variables)
{rendered.subject, rendered.html_body, rendered.text_body, template}
end
if db_template, do: Provider.current().track_usage(db_template)
deliver(user.email, subject, text_body, html_body)
end
@doc """
Deliver organization invitation email to a new (unregistered) user.
Sends a registration link containing the invitation token so the invitee
can register and automatically join the organization on email confirmation.
"""
def deliver_organization_invitation(email, organization_name, registration_url) do
fallback_text = """
Hi #{email},
#{organization_name} has invited you to join their organization.
To accept the invitation, register an account by visiting the link below:
#{registration_url}
This invitation link will expire in 7 days.
If you did not expect this invitation, you can safely ignore this email.
"""
deliver(email, "You've been invited to join #{organization_name}", fallback_text, nil)
end
@doc """
Deliver magic link registration instructions.
Uses the 'magic_link_registration' template from the database if available,
falls back to hardcoded template if not found.
"""
def deliver_magic_link_registration(user_or_email, url) do
# Handle both user struct and plain email string
email =
case user_or_email do
%{email: email} -> email
email when is_binary(email) -> email
end
# Variables for template substitution
template_variables = %{
"user_email" => email,
"registration_url" => url
}
# Try to get template from database, fallback to text-only
{subject, html_body, text_body, db_template} =
case Provider.current().get_active_template_by_name("magic_link_registration") do
nil ->
fallback_text = """
Hi #{email},
Welcome! To complete your registration, please click the link below:
#{url}
This link will expire in 30 minutes for your security.
If you didn't request this registration, please ignore this email.
"""
{"Complete Your Registration", nil, fallback_text, nil}
template ->
rendered = Provider.current().render_template(template, template_variables)
{rendered.subject, rendered.html_body, rendered.text_body, template}
end
if db_template, do: Provider.current().track_usage(db_template)
deliver(email, subject, text_body, html_body)
end
end