# SMTP worker

Consumes the mail queue and sends through SendGrid. Standalone: it shares no code
and no process with `apps/core`.

Core's job ends when the broker acknowledges a message; this worker's begins there.
Nothing in `apps/core` sends member mail — if this is not running, mail queues up and
nobody receives anything.

## Running it

```bash
cp workers/smtp/.env.example workers/smtp/.env   # then fill it in
pnpm install
pnpm --filter @karma/smtp-worker dev
```

It prints the queue and broker it attached to. In production, `pnpm build` then
`pnpm start`, or use the `smtp-worker` entry in `ecosystem.config.js`.

It does **not** have to run on the core server. It needs TCP to the broker and
outbound HTTPS to SendGrid, and nothing else.

## Checking whether it is working

The queue's consumer count answers it. Zero consumers with a rising `ready` count
means mail is being published and nothing is sending it — which is the state this
worker exists to fix.

## What it does with failures

| Outcome | Action | Why |
|---|---|---|
| Sent | ack | — |
| Unreadable message | ack, logged | The bytes will not improve; requeuing loops forever. |
| SendGrid rejected it (4xx) | ack, logged loudly | Bad template id or address — the same bytes get the same answer tomorrow. |
| Rate limit / outage / network | retried, then requeued and paused | The message may well succeed later, so it keeps its place. The pause stops the worker burning a whole backlog against a dead endpoint. |

`SMTP_WORKER_DRY_RUN=1` acks without sending — use it to clear a queue of test
messages without mailing anyone.
