# `SquatchMail.Web.WebhookController`
[🔗](https://github.com/Axio-Intelligence/Squatch-Mail/blob/v0.1.0/lib/squatch_mail/web/controllers/webhook_controller.ex#L1)

Receives inbound Amazon SNS/SES event notifications at
`POST <dashboard_path>/webhooks/sns/:token`.

This route intentionally lives outside the dashboard's `live_session` pipe
(see `SquatchMail.Web.Router`): it is a machine-to-machine API endpoint
authenticated by the per-source `:token` path segment, not a browser
session, so it skips CSRF protection and session fetching entirely.

## Raw body requirement

SNS signature verification needs the exact bytes SNS sent. The pipeline
that mounts this route must configure `Plug.Parsers` with `body_reader:
{SquatchMail.SNS.RawBodyReader, :read_body, []}` (scoped to this path is
enough) so `conn.assigns[:raw_body]` is populated - see
`SquatchMail.SNS.RawBodyReader`'s moduledoc for the exact plug pipeline
snippet. If `:raw_body` isn't set (misconfigured pipeline), this falls back
to re-encoding `conn.params` as JSON, which is **not** byte-identical to
what SNS sent and will fail signature verification - that fallback exists
only so the endpoint still responds predictably instead of crashing on a
`nil` body.

This is a plain `Plug`, not a `Phoenix.Controller` (same pattern as
`SquatchMail.Web.AssetController`) - Phoenix's router dispatches `get`/
`post` to either kind of module identically (`post "/path", Module,
:create`), and a webhook endpoint doing a single JSON-in/status-code-out
exchange doesn't need view/format negotiation.

# `call`

Handles the inbound webhook POST. Always responds within the request
cycle - SNS treats non-2xx as "retry", so the status code doubles as
retry/no-retry signaling:

  * `200` - processed or intentionally ignored (no retry wanted).
  * `404` - unknown `:token` (retrying won't help; the token is wrong).
  * `403` - signature verification failed (retrying won't help either;
    it'll fail again unless the payload changes, which SNS won't do).
  * `500` - a transient failure (SubscribeURL confirmation GET failed,
    DB hiccup, etc) - retryable, so SNS retrying is the desired behavior.

---

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