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