Remove faker, floki, igniter, ecto_psql_extras (zero usages), exvcr (zero usages), and resend. Replace resend with Aprsme.Swoosh.ResendAdapter using the already-present req dependency. Frees 23 packages total from the lockfile including hackney, certifi, and the tesla dependency chain. Fix two pre-existing test isolation bugs: - signal_handler_test called the real ShutdownHandler.shutdown() via SIGTERM simulation without restoring state, causing page_controller_test to see shutting_down: true and return 503 - page_controller_test setup now resets ShutdownHandler state defensively
78 lines
2.2 KiB
Elixir
78 lines
2.2 KiB
Elixir
defmodule Aprsme.Swoosh.ResendAdapter do
|
|
@moduledoc false
|
|
@behaviour Swoosh.Adapter
|
|
|
|
@api_url "https://api.resend.com/emails"
|
|
|
|
@impl true
|
|
def deliver(%Swoosh.Email{} = email, config) do
|
|
api_key = Keyword.fetch!(config, :api_key)
|
|
|
|
body =
|
|
%{
|
|
subject: email.subject,
|
|
from: format_sender(email.from),
|
|
to: format_recipients(email.to),
|
|
bcc: format_recipients(email.bcc),
|
|
cc: format_recipients(email.cc),
|
|
reply_to: format_recipients(email.reply_to),
|
|
headers: email.headers,
|
|
html: email.html_body,
|
|
text: email.text_body
|
|
}
|
|
|> Enum.reject(fn {_k, v} -> is_nil(v) or v == [] or v == %{} end)
|
|
|> Map.new()
|
|
|
|
req_opts = maybe_put_plug([json: body, headers: [{"authorization", "Bearer #{api_key}"}]], config)
|
|
|
|
case Req.post(@api_url, req_opts) do
|
|
{:ok, %{status: status, body: %{"id" => id}}} when status in 200..299 ->
|
|
{:ok, %{id: id}}
|
|
|
|
{:ok, %{body: %{"name" => name, "message" => message}}} ->
|
|
{:error, {name, message}}
|
|
|
|
{:ok, %{body: body}} ->
|
|
{:error, body}
|
|
|
|
{:error, reason} ->
|
|
{:error, reason}
|
|
end
|
|
end
|
|
|
|
@impl true
|
|
def deliver_many(emails, config) do
|
|
Enum.reduce_while(emails, {:ok, []}, fn email, {:ok, acc} ->
|
|
case deliver(email, config) do
|
|
{:ok, result} -> {:cont, {:ok, acc ++ [result]}}
|
|
{:error, _} = error -> {:halt, error}
|
|
end
|
|
end)
|
|
end
|
|
|
|
@impl true
|
|
def validate_config(config) do
|
|
if Keyword.has_key?(config, :api_key) do
|
|
:ok
|
|
else
|
|
{:error, "Missing required :api_key configuration for Aprsme.Swoosh.ResendAdapter"}
|
|
end
|
|
end
|
|
|
|
defp maybe_put_plug(opts, config) do
|
|
case Keyword.get(config, :plug) do
|
|
nil -> opts
|
|
plug -> Keyword.put(opts, :plug, plug)
|
|
end
|
|
end
|
|
|
|
defp format_sender(nil), do: nil
|
|
defp format_sender(from) when is_binary(from), do: from
|
|
defp format_sender({"", from}), do: from
|
|
defp format_sender({name, from}), do: "#{name} <#{from}>"
|
|
|
|
defp format_recipients(nil), do: nil
|
|
defp format_recipients(r) when is_binary(r), do: r
|
|
defp format_recipients({_name, addr}), do: addr
|
|
defp format_recipients(list) when is_list(list), do: Enum.map(list, &format_recipients/1)
|
|
end
|