# `Sigra.Delivery`
[🔗](https://github.com/sztheory/sigra/blob/v1.20.0/lib/sigra/delivery.ex#L1)

Email delivery orchestration.

Provides three delivery modes:

- `:async` - Delivers via Oban worker (requires Oban)
- `:sync` - Delivers synchronously in calling process
- `:auto` - Auto-detects Oban presence, falls back to sync

## Threat Mitigation

When using async delivery, only `email_type`, `user_id`, and minimal
metadata (token, code, URL) are stored in the Oban jobs table. The full
email body is reconstructed at delivery time to avoid storing sensitive
content in the database (T-3-INFRA-01).

# `build_job`

```elixir
@spec build_job(atom(), map(), keyword()) :: Ecto.Changeset.t()
```

Builds an Oban job changeset for async email delivery without inserting it.

Useful for testing and for inspecting the job that would be created.

## Returns

An `Ecto.Changeset` for an `Oban.Job`.

# `deliver`

```elixir
@spec deliver(atom(), map(), keyword()) :: {:ok, term()} | {:error, term()}
```

Delivers email using the configured delivery mode.

## Options

- `:delivery_mode` - `:auto` (default), `:async`, or `:sync`
- `:mailer` - Module implementing `Sigra.Mailer` (required for `:sync`)
- `:oban_queue` - Oban queue name (default: `"sigra_mailer"`)

# `deliver_async`

```elixir
@spec deliver_async(atom(), map(), keyword()) :: {:ok, term()} | {:error, term()}
```

Delivers email asynchronously via Oban.

Inserts an Oban job with minimal args (email_type, user_id, token/code/url).
The full email is reconstructed at delivery time.

# `deliver_sync`

```elixir
@spec deliver_sync(atom(), map(), keyword()) :: {:ok, term()} | {:error, term()}
```

Delivers email synchronously in the calling process.

Calls the configured mailer's `deliver/3` callback directly.

## Options

- `:mailer` - Module implementing `Sigra.Mailer` (required)

---

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