6.8 KiB
6.8 KiB
Install
- 需求:.NET SDK 8.x, PostgreSQL
- 設定:複製
.env.example→.env - AWS Credential(SQS/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:ReceiveMessagesqs:DeleteMessagesqs:GetQueueAttributesses: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
- 預設由 API 啟動時自動執行(
- 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 - 若
client_id已存在且屬於同一 tenant,Installer 會重用既有 webhook client(不重複建立),可直接搭配--upsert-member-center做同步 - 若
client_id已存在但屬於不同 tenant,Installer 會中止並回報錯誤 - 若 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必須等於 payloadtenant_id - 不支援
X-Client-Idfallback - 預設拒絕
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__ClientIdMemberCenter__ClientSecretMemberCenter__Scope=newsletter:events.writeMemberCenter__ApiToken僅作暫時 fallback(非首選)
- Send Job API 驗證(JWT):
Jwt__IssuerJwt__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 Sender(Mock 發信):
DevSender__Enabled=true:背景 worker 會處理pendingsend 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(預設):使用 SESSendEmail,依內容分組後每次最多 50 位收件者(不依賴 SES Template)Ses__SendMode=bulk_template:使用 SESSendBulkEmail+ Template(需提供template.ses_template_name或Ses__TemplateName)- SES 發送時會附帶 message tags:
tenant_id、list_id、campaign_id、send_job_id - SQS Poller(SES 事件回流):
Sqs__Enabled=trueSqs__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 endpoint,sender 會在發送前批次呼叫
/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_templatelist_unsubscribe_mailto- sender 會自動加上
List-Unsubscribe與List-Unsubscribe-Postheaders - 正式環境建議維持
false