Add proper batch mailing functionality

This commit is contained in:
Nathan Chapman 2024-11-18 14:59:58 -07:00
parent 709282091c
commit 584dc08292
6 changed files with 78 additions and 31 deletions

View File

@ -6,8 +6,7 @@ defmodule SendIt.Marketing do
import Ecto.Query, warn: false
alias SendIt.Repo
alias SendIt.Marketing.Contact
alias SendIt.Marketing.Message
alias SendIt.Marketing.{Contact, Message, MessageNotifier}
@doc """
Returns the list of contacts.
@ -146,10 +145,25 @@ defmodule SendIt.Marketing do
"""
def create_message(attrs \\ %{}) do
%Message{}
|> Message.changeset(attrs)
|> change_message(attrs)
|> Repo.insert()
end
@doc """
Delivers the given message to the message's contacts list
## Examples
iex> deliver_message(message)
{:ok, %{to: ..., body: ...}}
"""
def deliver_message(%Message{} = message) do
message
|> Repo.preload(:contacts)
|> MessageNotifier.deliver_message()
end
@doc """
Updates a message.
@ -164,7 +178,7 @@ defmodule SendIt.Marketing do
"""
def update_message(%Message{} = message, attrs) do
message
|> Message.changeset(attrs)
|> change_message(attrs)
|> Repo.update()
end
@ -194,6 +208,10 @@ defmodule SendIt.Marketing do
"""
def change_message(%Message{} = message, attrs \\ %{}) do
Message.changeset(message, attrs)
contacts = list_contacts()
message
|> Message.changeset(attrs)
|> Ecto.Changeset.put_assoc(:contacts, contacts)
end
end

View File

@ -0,0 +1,51 @@
defmodule SendIt.Marketing.MessageNotifier do
use SendItWeb, :html
require Logger
import Swoosh.Email
alias SendIt.Mailer
@from_name "Port Townsend Roasting Co."
@from_email "newsletter@ptcoffee.com"
def deliver_message(message) do
message.contacts
|> format_recipients()
|> dbg()
|> deliver(message.subject, message.content)
end
defp deliver(recipients, subject, body) do
email =
new(
to: recipients,
from: {@from_name, @from_email},
subject: subject,
html_body:
body
|> Phoenix.HTML.html_escape()
|> Phoenix.HTML.safe_to_string()
)
|> put_provider_option(:recipient_vars, format_recipient_vars(recipients))
case Mailer.deliver(email) do
{:ok, _} ->
{:ok, email}
{:error, reason} ->
Logger.warning("Sending email failed: #{inspect(reason)}")
{:error, reason}
end
end
defp format_recipients(recipients) do
Enum.map(recipients, &{&1.name, &1.email})
end
defp format_recipient_vars(recipients) do
Enum.reduce(recipients, %{}, fn {name, email}, acc ->
Map.put_new(acc, email, %{name: name})
end)
end
end

View File

@ -20,7 +20,7 @@ defmodule SendItWeb.MessageLive.FormComponent do
phx-submit="save"
>
<.input field={@form[:subject]} type="text" label="Subject" />
<.input field={@form[:content]} type="text" label="Content" />
<.input field={@form[:content]} type="textarea" label="Content" />
<:actions>
<.button phx-disable-with="Saving...">Save Message</.button>
</:actions>
@ -49,24 +49,11 @@ defmodule SendItWeb.MessageLive.FormComponent do
save_message(socket, socket.assigns.action, message_params)
end
defp save_message(socket, :edit, message_params) do
case Marketing.update_message(socket.assigns.message, message_params) do
{:ok, message} ->
notify_parent({:saved, message})
{:noreply,
socket
|> put_flash(:info, "Message updated successfully")
|> push_patch(to: socket.assigns.patch)}
{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, assign(socket, form: to_form(changeset))}
end
end
defp save_message(socket, :new, message_params) do
case Marketing.create_message(message_params) do
{:ok, message} ->
{:ok, _email} = Marketing.deliver_message(message)
notify_parent({:saved, message})
{:noreply,

View File

@ -22,7 +22,6 @@
<div class="sr-only">
<.link navigate={~p"/messages/#{message}"}>Show</.link>
</div>
<.link patch={~p"/messages/#{message}/edit"}>Edit</.link>
</:action>
<:action :let={{id, message}}>
<.link
@ -35,7 +34,7 @@
</.table>
<.modal
:if={@live_action in [:new, :edit]}
:if={@live_action in [:new]}
id="message-modal"
show
on_cancel={JS.patch(~p"/messages")}

View File

@ -1,11 +1,6 @@
<.header>
Message <%= @message.id %>
<:subtitle>This is a message record from your database.</:subtitle>
<:actions>
<.link patch={~p"/messages/#{@message}/show/edit"} phx-click={JS.push_focus()}>
<.button>Edit message</.button>
</.link>
</:actions>
</.header>
<.list>

View File

@ -68,10 +68,7 @@ defmodule SendItWeb.Router do
on_mount: [{SendItWeb.UserAuth, :ensure_authenticated}] do
live "/messages", MessageLive.Index, :index
live "/messages/new", MessageLive.Index, :new
live "/messages/:id/edit", MessageLive.Index, :edit
live "/messages/:id", MessageLive.Show, :show
live "/messages/:id/show/edit", MessageLive.Show, :edit
live "/users/settings", UserSettingsLive, :edit
live "/users/settings/confirm_email/:token", UserSettingsLive, :confirm_email