mass_mail_engine/docs/INSTALL.md

97 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Install
- 需求:.NET SDK 8.x, PostgreSQL
- 設定:複製 `.env.example``.env`
- AWS CredentialSQS/SES
- Local / Docker 開發:
- 設定 `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`(若為臨時憑證再加 `AWS_SESSION_TOKEN`
- 設定 `AWS__Region`(或 `Sqs__Region` / `Ses__Region`
- 建議設 `AWS_EC2_METADATA_DISABLED=true`,避免本機誤打 EC2 metadata
- ECS 正式環境(建議):
- 不要放 Access Key改用 ECS Task Role`taskRoleArn`
- Task Role 至少授權:
- `sqs:ReceiveMessage`
- `sqs:DeleteMessage`
- `sqs:GetQueueAttributes`
- `ses:SendEmail`raw_bulk
- `ses:SendBulkEmail`bulk_template若有使用
- ECS Task Definition 可設定環境變數:
- `AWS_REGION=ap-northeast-1`(或直接用 `.env``AWS__Region`
- Migration
- 預設由 API 啟動時自動執行(`Db__AutoMigrate=true`
- 需要關閉時請設定 `Db__AutoMigrate=false`
- 手動執行可用 `dotnet run --project src/SendEngine.Installer -- migrate`
- Webhook Auth 初始化(不使用 SQL 檔,改用 Installer
- 若僅需先建立 tenant 基本資料:
- `dotnet run --project src/SendEngine.Installer -- ensure-tenant --tenant-id <tenant_uuid> [--tenant-name <name>]`
- 使用 Installer 建立 webhook client`id` 自動隨機產生):
- `dotnet run --project src/SendEngine.Installer -- add-webhook-client --tenant-id <tenant_uuid> [--tenant-name <name>] --client-id <client_id> --name <display_name> --scopes <scope1,scope2>`
- 例如:`dotnet run --project src/SendEngine.Installer -- add-webhook-client --tenant-id 11111111-1111-1111-1111-111111111111 --tenant-name "Tenant A" --client-id member-center-webhook --name "Member Center Webhook" --scopes newsletter:events.write`
- 若 tenant 不存在Installer 會先自動建立 `tenants` 基本資料,避免 webhook 出現 `tenant_not_found`
- 建立成功後Member Center webhook header `X-Client-Id` 請帶回傳的 `id`
- 若要自動同步到 Member Center `POST /integrations/send-engine/webhook-clients/upsert`(保留原手動流程):
- `dotnet run --project src/SendEngine.Installer -- add-webhook-client --tenant-id <tenant_uuid> --client-id <client_id> --name <display_name> --scopes <scope1,scope2> --upsert-member-center --mc-base-url <member_center_base_url> --mc-client-id <oauth_client_id> --mc-client-secret <oauth_client_secret> --mc-scope newsletter:events.write.global`
- 可選參數:
- `--mc-token-path`(預設 `/oauth/token`
- `--mc-upsert-path`(預設 `/integrations/send-engine/webhook-clients/upsert`
- `--mc-token-url` / `--mc-upsert-url`(使用完整 URL 時可覆蓋 path 組合)
- Webhook 驗證規則為 tenant 綁定:`auth_clients.tenant_id` 必須等於 payload `tenant_id`
- 不支援 `X-Client-Id` fallback
- 預設拒絕 `tenant_id = NULL` 的通用 client`Webhook__AllowNullTenantClient=false`
- Member Center 回寫授權(建議):
- `MemberCenter__BaseUrl`(建議)
- `MemberCenter__DisableSubscriptionPath`(預設 `/subscriptions/disable`
- `MemberCenter__TokenPath`(預設 `/oauth/token`
- `MemberCenter__OneClickUnsubscribeTokensPath`(預設 `/newsletter/one-click-unsubscribe-tokens`
- `MemberCenter__ClientId`
- `MemberCenter__ClientSecret`
- `MemberCenter__Scope=newsletter:events.write`
- `MemberCenter__ApiToken` 僅作暫時 fallback非首選
- Send Job API 驗證JWT
- `Jwt__Issuer`
- `Jwt__Audience`
- 建議Member Center OIDC/JWKS
- `Jwt__Authority`(例如 `http://member-center`
-`Jwt__MetadataAddress`(例如 `http://member-center/.well-known/openid-configuration`
- 若兩者都未設定,會自動回退使用 `MemberCenter__BaseUrl + /.well-known/openid-configuration`
- `Jwt__RequireHttpsMetadata`(本機可設 `false`
- 相容舊模式(不建議):`Jwt__SigningKey`HS 對稱驗簽)
- 本機測試輔助(臨時):
- `TestFriendly__Enabled=true` 時:
- webhook 收到未知 tenant 會自動建立 tenant
- `/webhooks/ses` 不做任何 DB 存取,但會保留 Member Center callback 流程(僅用於測試流程打通)
- Dev SenderMock 發信):
- `DevSender__Enabled=true`:背景 worker 會處理 `pending` send jobs並將每位收件人的預計發送內容寫入 `events_inbox``source=dev_sender`, `event_type=send.preview`
- `DevSender__PollIntervalSeconds`:輪詢間隔秒數(預設 5
- `ESP__Provider=ses` 時,即使 `DevSender__Enabled=false`,背景 sender 仍會啟動並改用 SES 發送(模式由 `Ses__SendMode` 決定)
- SES 相關參數:`Ses__Region``Ses__FromEmail``Ses__ConfigurationSet`(可選)、`Ses__SendMode``Ses__TemplateName`
- SNS 簽章驗證參數:
- `Ses__SkipSignatureValidation`(建議正式環境 `false`
- `Ses__AllowedTopicArns`(逗號分隔 allowlist建議正式環境必填
- `Ses__AllowedCertHosts`(逗號分隔;留空時只接受 `sns.*.amazonaws.com`
- `Ses__SignatureMaxSkewSeconds`(預設 300
- `Ses__SendMode=raw_bulk`(預設):使用 SES `SendEmail`,依內容分組後每次最多 50 位收件者(不依賴 SES Template
- `Ses__SendMode=bulk_template`:使用 SES `SendBulkEmail` + Template需提供 `template.ses_template_name``Ses__TemplateName`
- SES 發送時會附帶 message tags`tenant_id``list_id``campaign_id``send_job_id`
- SQS PollerSES 事件回流):
- `Sqs__Enabled=true`
- `Sqs__QueueUrl=<aws_sqs_queue_url>`
- `Sqs__Region`(未設定時回退 `AWS__Region` 再回退 `Ses__Region`
- `Sqs__PollWaitSeconds`(預設 20
- `Sqs__MaxMessages`(預設 10
- `Sqs__VisibilityTimeoutSeconds`(預設 30
- SQS poller 目前未提供獨立 DLQ worker可先用 AWS SQS redrive policy 管理失敗訊息
- `SendBulkEmail` 會使用 SES 模板名稱:
- 先讀 `campaign.template.ses_template_name`
- 若未提供則回退 `Ses__TemplateName`
- 若設定了 Member Center one-click token endpointsender 會在發送前批次呼叫 `/newsletter/one-click-unsubscribe-tokens`,僅發送 `status=issued` 的收件者
- 內容替換合約Mock 與 SES 共用):
- `{{email}}`
- `{{unsubscribe_token}}`
- `{{tenant_id}}` / `{{list_id}}` / `{{campaign_id}}` / `{{send_job_id}}`
- 若在 `campaign.template` 提供:
- `list_unsubscribe_url_template`
- `list_unsubscribe_mailto`
- sender 會自動加上 `List-Unsubscribe``List-Unsubscribe-Post` headers
- 正式環境建議維持 `false`