innovedus_cms/docs/newsletter_integration_memo.md
Warren Chen 69ef3ccf72 feat(newsletter): Implement newsletter subscription and unsubscription features
- Added models for NewsletterSystemSettings and NewsletterTemplateSettings to manage configuration.
- Created forms for subscribing and unsubscribing from the newsletter.
- Developed views for handling subscription, confirmation, and unsubscription processes.
- Integrated Member Center API for managing newsletter subscriptions.
- Implemented email sending functionality with SMTP settings.
- Added templates for displaying subscription status and unsubscription confirmation.
- Enhanced CSS for newsletter forms and status messages.
- Included tests for newsletter functionality and security measures for sensitive data.
2026-02-17 17:57:16 +09:00

207 lines
6.8 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.

# 電子報介接備忘錄(租戶端 / Wagtail
最後更新2026-02-11
## 1. 目標與前提
本備忘錄用於整理租戶端Wagtail接下來的實作方向重點是先完成可運行流程再逐步補完細節。
## 2. 已確認決策(本次會議結論)
1. Member Center 雖為共用平台,但目前只有一個租戶。
2. 現階段「發確認信」與「訂閱/退訂頁面」先做在 Wagtail。
3. Wagtail 與 Member Center 的溝通以 API 為主。
4. SMTP relay 僅負責寄出一次重送、token 安全、簽章等由其他系統或工具負責,不屬 Wagtail 責任。
5. 工作大項與順序固定為:
1. 準備工作(電子報系統設定)
2. 訂閱流程
3. 退訂流程
4. 電子報 app
5. 發信流程(排程)
## 3. 工作大項與執行順序(含範圍)
## 3.1 準備工作(電子報系統設定,第一優先)
範圍:
- 建立 Member Center 連線設定base URL、tenant_id、list_id、API timeout 等)。
- 建立 Send Engine 連線設定base URL、OAuth scope、API timeout 等)。
- 建立一般發信設定SMTP relay、寄件者名稱/信箱、reply-to、預設編碼等
- 建立模板設定:
- 訂閱確認信 template
- 訂閱確認(成功)頁面 template
- 取消訂閱頁面 template
重點:
- 設定集中管理,避免散落在程式碼或多處後台欄位。
- 區分「系統連線設定」與「內容模板設定」,便於權限與維運。
完成標準DoD
- 可在單一設定入口完成上述設定並通過基本驗證。
- 模板可被後續訂閱/退訂流程直接引用。
## 3.2 訂閱流程(第二優先)
範圍:
- 在站台頁面區塊(暫定 Footer提供 email 訂閱入口。
- 後端接收 email呼叫 Member Center 訂閱 API。
- 由 Wagtail 送出訂閱確認信(透過 SMTP relay
- 使用者點信內連結回到 Wagtail 確認頁。
- 確認頁自動呼叫 Member Center 確認 API。
重點:
- 流程中 token 需一路帶入與驗證。
- 確認信內容採 HTML可附純文字 fallback
完成標準DoD
- 可從站台成功發起訂閱。
- 可收到確認信並完成確認。
- 確認成功/失敗頁有明確訊息與追蹤記錄。
## 3.3 退訂流程(第三優先)
範圍:
- 電子報底部提供退訂連結,導向 Wagtail 退訂頁。
- 進入退訂頁時,先向 Member Center 申請退訂 token。
- 使用者按確認退訂後,呼叫 Member Center 退訂 API 完成流程。
重點:
- token 不做長期保存。
- 頁面需可處理 token 失效/不存在等錯誤狀態。
完成標準DoD
- 使用者能從信件連結完成退訂。
- 退訂結果頁可正確呈現成功/失敗狀態。
## 3.4 電子報 app第四優先
範圍:
- 在 Wagtail 後台提供電子報內容管理能力。
- 提供 HTML 編輯器建立/編修內容。
- 支援可替換參數(例如 token、email
重點:
- 編輯器中的連結參數以佔位符表示,發送前由 backend 替換。
- 若有 Member Center API 相關連結需在內容中可配置,也採相同參數機制。
完成標準DoD
- 編輯器可存草稿與更新內容。
- 內容中參數可在送出前正確替換。
## 3.5 發信流程(排程,第五優先)
範圍:
- 可建立發送任務與排程時間。
- 排程前可持續編輯內容與調整時間。
- 到時觸發時:先取 Member Center auth再將內容包固定 header/footer送到 Send Engine。
重點:
- 「內容定稿」與「實際送出」拆開。
- 發送前的模板組裝由 Wagtail backend 負責。
完成標準DoD
- 排程到點可成功建立 Send Engine send job。
- 失敗可記錄原因並可人工重試。
## 4. 參數替換規則(先行約定)
建議佔位符格式(待實作時可再定版):
- `{{token}}`
- `{{email}}`
- `{{list_id}}`
- `{{tenant_id}}`
- `{{confirm_url}}`
- `{{unsubscribe_url}}`
替換時機:
- 發信前 backend 最後一步統一替換。
注意事項:
- URL 參數需做 URL encode。
- 缺少必要參數時,中止發送並記錄可追蹤錯誤。
## 5. URL 與系統歸屬標註規範(文件撰寫規則)
後續文件凡提到網址,必須明確標註「是哪個系統」:
1. Wagtail租戶站台網址
- 例:`https://{tenant-site}/newsletter/confirm?token=...`
- 用途:使用者互動頁、站台前台/後台頁面。
2. Member Center API 網址
- 例:`https://{member-center}/newsletter/subscribe`
- 用途:訂閱、確認、退訂 token、退訂等 API。
3. Send Engine API 網址
- 例:`https://{send-engine}/api/send-jobs`
- 用途:建立/查詢/取消發信任務。
4. SMTP Relay 連線端點
- 用途Wagtail 寄送確認信。
- 備註:僅作為寄送通道,不承擔重送與安全機制。
## 6. 非 Wagtail 責任邊界(本階段)
以下不納入目前 Wagtail 工作範圍:
- SMTP 後續重送策略。
- token 簽章與高階安全策略。
- 跨系統風控與防濫用機制。
## 7. 下一步(實作啟動清單)
1. 先完成電子報系統設定Member Center / Send Engine / SMTP / 模板)。
2. 再完成訂閱流程 API 串接與確認頁。
3. 再完成退訂頁與退訂 API 串接。
4. 建立電子報 app 與 HTML 編輯器資料模型。
5. 最後接排程任務與 Send Engine 發信。
## 8. Member Center API 實際規格(以 member_center 程式碼 / OpenAPI 為準)
資料來源2026-02-17 比對):
- `../member_center/src/MemberCenter.Api/Controllers/NewsletterController.cs`
- `../member_center/docs/openapi.yaml`
### 8.1 Base URL 與路徑
- OpenAPI `servers.url``/api`,部署時實際呼叫通常為:
- `https://{member-center}/api/newsletter/...`
- 若部署已在 gateway 做 path rewrite也可為
- `https://{member-center}/newsletter/...`
- 租戶端必須以實際部署路徑設定 `member_center_base_url`
### 8.2 Endpoint / Method / Request
1. 訂閱
- `POST /newsletter/subscribe`
- JSON body必要
- `list_id`Guid
- `email`string
- JSON body可選
- `preferences`object
- `source`string
- 回傳包含 `confirm_token`
2. 訂閱確認(雙重驗證)
- `GET /newsletter/confirm?token=...`
- 注意:**confirm 是 GET不是 POST**
3. 單一名單退訂
- `POST /newsletter/unsubscribe`
- JSON body必要
- `token`string
4. 申請退訂 token
- `POST /newsletter/unsubscribe-token`
- JSON body必要
- `list_id`Guid
- `email`string
- 回傳:
- `unsubscribe_token`string
### 8.3 與租戶端目前實作對齊結果
- `subscribe`:已使用 `POST`
- `confirm`:已改為 `GET + query token`(修正 HTTP 405 問題)。
- `unsubscribe`:已使用 `POST`,且 body 僅送 `token`
- `unsubscribe-token`:已使用 `POST`,且 body 送 `list_id + email`