Mailglass.Adapters.Swoosh (Mailglass v2.5.0)

Copy Markdown View Source

Adapter bridging to any Swoosh.Adapter.

Adopters configure their Swoosh adapter once and mailglass wraps it — they keep existing Postmark/SendGrid/Mailgun/SES/Resend/SMTP config. mailglass adds error normalization into %Mailglass.SendError{}. The authoritative dispatch span belongs to the outbound facade's call_adapter/2, so a provider call emits one span rather than a nested duplicate.

Pure: no DB, no PubSub, no Process.put. Caller's process owns the HTTP request via Swoosh's :api_client (adopter-supplied, typically Finch).

Configuration

config :mailglass,
  adapter: {Mailglass.Adapters.Swoosh,
            swoosh_adapter: {Swoosh.Adapters.Postmark,
                             api_key: System.fetch_env!("POSTMARK_API_KEY")}}

The :swoosh_adapter opt carries either a module (for Swoosh adapters with no config) or a {module, opts} tuple.

Error mapping (v0.1)

Swoosh shapeMapped SendError :typeContext fields
{:api_error, 429, _} or 500..599:adapter_failure / transientprovider_status, reason_class, provider_module
{:api_error, 400..499, _}:adapter_failure / permanentprovider_status, reason_class, provider_module
Known transport/timeouts:adapter_failure / transientreason_class: :transport, provider_module
Unknown or malformed outcomes:adapter_failure / permanentreason_class: :unknown, provider_module

PII policy: Provider response bodies and reason text never enter error context, exception messages, JSON, or persisted delivery errors. The 8 forbidden keys (:to, :from, :body, :html_body, :subject, :headers, :recipient, :email) NEVER appear in error context. NoPiiInTelemetryMeta enforces.

What this module does NOT do

  • Does not call Swoosh.Mailer.deliver/1 — forbidden in library code. Calls Swoosh.Adapter.deliver/2 (the behaviour callback) directly.
  • Is not a GenServer — pure function, stateless.
  • Does not touch mailglass_events, mailglass_deliveries, or Phoenix.PubSub. Side-effect-free by design.