feat: mail service
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
# Main Flows
|
||||
|
||||
## Auth / Session -> Mail
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Auth as Auth / Session Service
|
||||
participant Mail as Mail Service
|
||||
participant Redis
|
||||
participant Scheduler
|
||||
participant SMTP as Provider
|
||||
|
||||
Auth->>Mail: POST /api/v1/internal/login-code-deliveries + Idempotency-Key
|
||||
Mail->>Mail: validate request and idempotency scope
|
||||
alt MAIL_SMTP_MODE = stub
|
||||
Mail->>Redis: persist delivery as suppressed
|
||||
Mail-->>Auth: 200 {outcome=suppressed}
|
||||
else MAIL_SMTP_MODE = smtp
|
||||
Mail->>Redis: persist delivery as queued + attempt #1 scheduled
|
||||
Mail-->>Auth: 200 {outcome=sent}
|
||||
Scheduler->>Redis: claim due attempt
|
||||
Scheduler->>SMTP: send rendered auth mail
|
||||
SMTP-->>Scheduler: accepted or classified failure
|
||||
Scheduler->>Redis: commit sent / retry / failed / dead_letter
|
||||
end
|
||||
```
|
||||
|
||||
`sent` on this boundary means durable intake into the mail-delivery pipeline.
|
||||
It does not mean SMTP completion.
|
||||
|
||||
## Notification -> Mail
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Notify as Notification Service
|
||||
participant Stream as Redis Stream mail:delivery_commands
|
||||
participant Consumer as Command consumer
|
||||
participant Mail as Mail Service
|
||||
participant Redis
|
||||
|
||||
Notify->>Stream: XADD generic command
|
||||
Consumer->>Stream: XREAD from last stored offset
|
||||
Consumer->>Mail: decode and validate command
|
||||
alt malformed or conflicting command
|
||||
Mail->>Redis: record malformed command entry
|
||||
Consumer->>Redis: save stream offset
|
||||
else valid command
|
||||
Mail->>Redis: persist delivery + first attempt + optional payload bundle
|
||||
Consumer->>Redis: save stream offset
|
||||
end
|
||||
```
|
||||
|
||||
## Retry and Dead Letter
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Scheduler
|
||||
participant Redis
|
||||
participant Worker as Attempt worker
|
||||
participant SMTP as Provider
|
||||
|
||||
Scheduler->>Redis: find next due delivery
|
||||
Scheduler->>Redis: load work item
|
||||
alt template delivery not yet rendered
|
||||
Scheduler->>Redis: render and store materialized content
|
||||
end
|
||||
Scheduler->>Redis: claim scheduled attempt
|
||||
Scheduler->>Worker: enqueue claimed work
|
||||
Worker->>SMTP: send materialized message
|
||||
SMTP-->>Worker: accepted / suppressed / transient_failure / permanent_failure
|
||||
alt accepted
|
||||
Worker->>Redis: commit sent + provider_accepted
|
||||
else suppressed
|
||||
Worker->>Redis: commit suppressed + provider_rejected
|
||||
else transient failure before retry budget ends
|
||||
Worker->>Redis: commit transport_failed|timed_out + next scheduled attempt
|
||||
else retry budget exhausted
|
||||
Worker->>Redis: commit dead_letter + dead-letter entry
|
||||
else permanent failure
|
||||
Worker->>Redis: commit failed + provider_rejected
|
||||
end
|
||||
```
|
||||
|
||||
## Operator Resend
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Ops as Trusted operator
|
||||
participant Mail as Mail Service
|
||||
participant Redis
|
||||
|
||||
Ops->>Mail: POST /api/v1/internal/deliveries/{delivery_id}/resend
|
||||
Mail->>Redis: load original delivery and optional payload bundle
|
||||
Mail->>Mail: verify original status is terminal
|
||||
Mail->>Redis: create clone delivery with source=operator_resend
|
||||
Mail-->>Ops: 200 {delivery_id=<clone>}
|
||||
```
|
||||
|
||||
Resend always creates a new delivery and never mutates the original delivery or
|
||||
its attempt history.
|
||||
Reference in New Issue
Block a user