feat: add join confirmation and mail templating
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Simon 2026-03-09 18:15:12 +01:00
parent 3672ef0d03
commit 6385fbc831
Signed by: simon
GPG key ID: 40E7A58C4AA1EDB2
24 changed files with 585 additions and 53 deletions

View file

@ -0,0 +1,12 @@
defmodule MvWeb.EmailLayoutView do
@moduledoc """
Layout view for transactional emails (join confirmation, user confirmation, password reset).
Renders a single layout template that wraps all email body content.
See docs/email-layout-mockup.md for the layout structure.
"""
use Phoenix.View,
root: "lib/mv_web",
path: "templates/emails/layouts",
namespace: MvWeb
end

View file

@ -0,0 +1,13 @@
defmodule MvWeb.EmailsView do
@moduledoc """
View for transactional email body templates.
Templates are rendered inside EmailLayoutView layout when sent via Phoenix.Swoosh.
"""
use Phoenix.View,
root: "lib/mv_web",
path: "templates/emails",
namespace: MvWeb
use Gettext, backend: MvWeb.Gettext, otp_app: :mv
end

View file

@ -0,0 +1,33 @@
defmodule MvWeb.Emails.JoinConfirmationEmail do
@moduledoc """
Sends the join request confirmation email (double opt-in) using the unified email layout.
"""
use Phoenix.Swoosh,
view: MvWeb.EmailsView,
layout: {MvWeb.EmailLayoutView, :layout}
use MvWeb, :verified_routes
import Swoosh.Email
use Gettext, backend: MvWeb.Gettext, otp_app: :mv
alias Mv.Mailer
@doc """
Sends the join confirmation email to the given address with the confirmation link.
Called from the domain after a JoinRequest is created (submit flow).
"""
def send(email_address, token) when is_binary(email_address) and is_binary(token) do
confirm_url = url(~p"/confirm_join/#{token}")
subject = gettext("Confirm your membership request")
new()
|> from(Mailer.mail_from())
|> to(email_address)
|> subject(subject)
|> put_view(MvWeb.EmailsView)
|> put_layout({MvWeb.EmailLayoutView, "layout.html"})
|> render_body("join_confirmation.html", %{confirm_url: confirm_url, subject: subject})
|> Mailer.deliver!()
end
end