6.8 KiB
Raw Permalink Blame History

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 RoletaskRoleArn
    • Task Role 至少授權:
    • sqs:ReceiveMessage
    • sqs:DeleteMessage
    • sqs:GetQueueAttributes
    • ses:SendEmailraw_bulk
    • ses:SendBulkEmailbulk_template若有使用
    • ECS Task Definition 可設定環境變數:
    • AWS_REGION=ap-northeast-1(或直接用 .envAWS__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 clientid 自動隨機產生):
    • 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 已存在且屬於同一 tenantInstaller 會重用既有 webhook client不重複建立可直接搭配 --upsert-member-center 做同步
    • client_id 已存在但屬於不同 tenantInstaller 會中止並回報錯誤
    • 若 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 的通用 clientWebhook__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__SigningKeyHS 對稱驗簽)
  • 本機測試輔助(臨時):
    • TestFriendly__Enabled=true 時:
    • webhook 收到未知 tenant 會自動建立 tenant
    • /webhooks/ses 不做任何 DB 存取,但會保留 Member Center callback 流程(僅用於測試流程打通)
    • Dev SenderMock 發信):
    • DevSender__Enabled=true:背景 worker 會處理 pending send jobs並將每位收件人的預計發送內容寫入 events_inboxsource=dev_sender, event_type=send.preview
    • DevSender__PollIntervalSeconds:輪詢間隔秒數(預設 5
    • ESP__Provider=ses 時,即使 DevSender__Enabled=false,背景 sender 仍會啟動並改用 SES 發送(模式由 Ses__SendMode 決定)
    • SES 相關參數:Ses__RegionSes__FromEmailSes__ConfigurationSet(可選)、Ses__SendModeSes__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_nameSes__TemplateName
    • SES 發送時會附帶 message tagstenant_idlist_idcampaign_idsend_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-UnsubscribeList-Unsubscribe-Post headers
    • 正式環境建議維持 false