73 lines
2.0 KiB
Elixir
73 lines
2.0 KiB
Elixir
defmodule WhoNeedHelp.EmailDelivery do
|
|
@moduledoc """
|
|
Delivers email while emitting low-cardinality, purpose-specific telemetry.
|
|
|
|
Telemetry metadata contains only fixed type and outcome labels. Recipients,
|
|
subjects, bodies, references, and other personal data are never attached.
|
|
"""
|
|
|
|
alias WhoNeedHelp.EmailAddress
|
|
alias WhoNeedHelp.Mailer
|
|
|
|
@kinds [
|
|
:auth_email_change,
|
|
:auth_google_link,
|
|
:auth_login,
|
|
:auth_registration,
|
|
:content_removal_confirmation,
|
|
:content_removal_operator,
|
|
:content_removal_received,
|
|
:content_removal_update,
|
|
:support_confirmation,
|
|
:support_operator,
|
|
:support_update
|
|
]
|
|
|
|
@spec deliver(Swoosh.Email.t(), atom()) :: {:ok, term()} | {:error, term()}
|
|
def deliver(%Swoosh.Email{} = email, kind) when kind in @kinds do
|
|
started_at = System.monotonic_time()
|
|
|
|
if valid_envelope?(email) do
|
|
try do
|
|
result = Mailer.deliver(email)
|
|
emit(started_at, kind, result_status(result))
|
|
result
|
|
rescue
|
|
exception ->
|
|
emit(started_at, kind, :exception)
|
|
reraise exception, __STACKTRACE__
|
|
catch
|
|
class, reason ->
|
|
emit(started_at, kind, :exception)
|
|
:erlang.raise(class, reason, __STACKTRACE__)
|
|
end
|
|
else
|
|
emit(started_at, kind, :error)
|
|
{:error, :invalid_email_address}
|
|
end
|
|
end
|
|
|
|
def kinds, do: @kinds
|
|
|
|
defp result_status({:ok, _metadata}), do: :ok
|
|
defp result_status({:error, _reason}), do: :error
|
|
|
|
defp valid_envelope?(email) do
|
|
[email.from, email.reply_to | email.to ++ email.cc ++ email.bcc]
|
|
|> List.flatten()
|
|
|> Enum.reject(&is_nil/1)
|
|
|> Enum.all?(fn
|
|
{_name, address} -> EmailAddress.valid?(address)
|
|
_invalid_recipient -> false
|
|
end)
|
|
end
|
|
|
|
defp emit(started_at, kind, status) do
|
|
:telemetry.execute(
|
|
[:who_need_help, :email, :delivery],
|
|
%{duration: System.monotonic_time() - started_at},
|
|
%{kind: to_string(kind), status: to_string(status)}
|
|
)
|
|
end
|
|
end
|