# `Mailglass.Adapters.Swoosh`
[🔗](https://github.com/szTheory/mailglass/blob/v2.6.0/lib/mailglass/adapters/swoosh.ex#L1)

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 shape | Mapped SendError `:type` | Context fields |
|--------------|--------------------------|----------------|
| `{:api_error, 429, _}` or `500..599` | `:adapter_failure` / transient | `provider_status`, `reason_class`, `provider_module` |
| `{:api_error, 400..499, _}` | `:adapter_failure` / permanent | `provider_status`, `reason_class`, `provider_module` |
| Known transport/timeouts | `:adapter_failure` / transient | `reason_class: :transport`, `provider_module` |
| Unknown or malformed outcomes | `:adapter_failure` / permanent | `reason_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.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
