Phoenix
A Swoosh adapter, so every Phoenix mailer and email in the app goes through emails.sh.
Phoenix generates a Swoosh mailer for every new application. Point it at an adapter of yours and the emails your context modules already build go out through the API, with no other change.
Configure
# config/runtime.exs
# Read at boot, not compiled in. The key comes from
# https://emails.sh/dashboard/api-keys.
config :acme, Acme.Mailer,
adapter: Acme.EmailsshAdapter,
api_key: System.fetch_env!("EMAILSSH_API_KEY")The adapter
# lib/acme/emailssh_adapter.ex
defmodule Acme.EmailsshAdapter do
@moduledoc "Swoosh adapter for emails.sh."
use Swoosh.Adapter, required_config: [:api_key]
@endpoint "https://emails.sh/v1/emails"
@impl true
def deliver(%Swoosh.Email{} = email, config) do
body =
%{
from: address(email.from),
to: Enum.map(email.to, &elem(&1, 1)),
subject: email.subject,
html: email.html_body,
text: email.text_body
}
|> maybe_put(:cc, Enum.map(email.cc || [], &elem(&1, 1)))
|> maybe_put(:bcc, Enum.map(email.bcc || [], &elem(&1, 1)))
|> Map.reject(fn {_k, v} -> is_nil(v) end)
case Req.post(@endpoint, json: body, auth: {:bearer, config[:api_key]}, receive_timeout: 10_000) do
{:ok, %{status: status, body: %{"id" => id}}} when status < 400 ->
{:ok, %{id: id}}
{:ok, %{body: %{"error" => %{"code" => code, "message" => message}}}} ->
{:error, {code, message}}
{:error, reason} ->
{:error, reason}
end
end
defp address({nil, addr}), do: addr
defp address({name, addr}), do: "#{name} <#{addr}>"
defp maybe_put(map, _key, []), do: map
defp maybe_put(map, key, value), do: Map.put(map, key, value)
endUse it
# lib/acme/accounts/user_notifier.ex, as generated by phx.gen.auth
defmodule Acme.Accounts.UserNotifier do
import Swoosh.Email
alias Acme.Mailer
def deliver_confirmation_instructions(user, url) do
new()
|> to({user.name, user.email})
|> from({"Acme", "hello@acme.com"})
|> subject("Confirm your Acme account")
|> html_body("<p>Confirm your account: <a href=\"#{url}\">#{url}</a></p>")
|> text_body("Confirm your account: #{url}")
|> Mailer.deliver()
end
end