warrenchen d49c30b447 feat: Add SQS integration for SES event processing
- Introduced SqsSesPollerWorker to poll messages from SQS and process SES events.
- Implemented SesEventProcessingService to handle SES event payloads and store them in the database.
- Updated DevMockSenderWorker to support new SES sending methods and improved logging for unsubscribe headers.
- Added AWS SDK for SQS to project dependencies.
2026-02-26 17:10:25 +09:00

3.4 KiB
Raw Permalink Blame History

Design

本文件描述 Send Engine 的核心模組、資料流、模組邊界與 Auth/Scope 設計。 本引擎只負責事件控制與執行,不提供 UI。 ESP 介接暫定為 Amazon SES。

核心模組

  • Event Ingest
  • List Store多租戶
  • Campaign / Send Job
  • Sender Adapter
  • Delivery & Bounce Handling

Sending Proxy 規格整合

目標與邊界

  • 接收內容網站或會員平台送來的發送工作
  • 呼叫 Amazon SES API優先 SES v2
  • 必帶 Configuration Set + Message Tags
  • 消費 SES 回流事件Bounce / Complaint / Delivery
  • 必要時回寫 Member Center

不負責:

  • List-Unsubscribe one-click endpoint 本身的服務實作
  • 會員最終名單權威資料庫

狀態機

Job 狀態(目前實作):

  • pending
  • running
  • completed
  • failed
  • cancelled

Job 狀態(規劃擴充):

  • queued
  • sending
  • sent
  • partially_failed

Recipient 狀態:

  • pending
  • sent
  • delivered
  • soft_bounced
  • hard_bounced
  • complained
  • suppressed

SES 事件回流架構(建議)

  • SES Configuration Set -> SNS Topic -> SQS Queue -> ECS Worker
  • Worker 職責:
  • Poll SQS
  • 解析 SNS envelope 與 SES payload
  • 更新 DB 狀態
  • 必要時呼叫 Member Center 停用/註記 API

目前實作:

  • 已提供 SqsSesPollerWorkerSQS 輪詢)
  • worker 直接呼叫內部 SES processing service不走 HTTP self-call
  • 仍保留 POST /webhooks/ses 直接接收模式(相容/測試)

信任邊界與 Auth 模型

外部角色

  • Member Center事件來源與名單權威來源authority
  • 各租戶網站內容來源campaign/content producer
  • Send Engine執行與狀態記錄executor

信任邊界

  • Send Engine 不自行發放 tenant 身分;一律以 Member Center 代表的 tenant scope 為準
  • 所有 API 必須攜帶 tenant_id且在驗證後固定於 request context

驗證方式(建議)

  1. Member Center → Send Engine
    • 使用簽名 WebhookHMAC已實作
    • header 內含 X-Client-Id,對應 auth_clients.id 並受 tenant 綁定與 scope 驗證
  2. 租戶網站 → Send Engine
    • 使用 OAuth2 Client Credentials 或 JWT由 Member Center 簽發)
    • token 內含 tenant_id 與 scopes例如 newsletter:send.write
  3. Send Engine → Member Center
    • 使用 OAuth2 Client CredentialsSend Engine 作為 client
    • scopes 只允許 newsletter:list.read / newsletter:events.read / newsletter:events.write

Tenant Scope 取得與約束

  • 事件 ingest:以 token 中的 tenant_id 為唯一來源,不接受 body 覆寫
  • Send Job 建立tenant_id 從 token 取得list_id 必須屬於該 tenant
  • 名單同步:由 Member Center 主動推送(全量/增量Send Engine 不主動拉取名單
  • 回寫事件:回寫時攜帶同一 tenant_idMember Center 做二次驗證

防護與審計

  • 所有跨服務呼叫需記錄 tenant_idclient_idscoperequest_id
  • API 層進行 scope 檢查與 tenant 一致性檢查
  • Event Ingest 與 Webhook 需具備重放防護timestamp + nonce

名單外流風險控制

  • Send Engine 不提供「名單查詢 API」
  • 全量同步由 Member Center 發動並推送
  • 如需測試/診斷,僅回傳計數與版本資訊,不回傳名單內容

資料模型原則

  • 事件為 append-only快照表僅反映最新狀態
  • 任何狀態變更必須可追溯(含來源與租戶)