跳轉到

Daily Schedule Summary Mail

Cortex scheduler 每天 23:30(Asia/Taipei)寄送當日排程摘要。23:30 刻意晚於 23:00 的 lagging_dataset_catchup,讓最後一輪延遲資料補抓也能出現在信中。

功能預設關閉。只有 SCHEDULE_SUMMARY_MAIL_ENABLED=true 且所選 transport 設定通過驗證時才會連線寄信。支援通用 SMTP,以及 Cloudflare Email Service REST API。

郵件內容

主旨格式:

[Cortex][SUCCESS|PARTIAL|FAILED|EMPTY] YYYY-MM-DD 每日排程摘要

內容同時包含 text/plaintext/html

  1. 成功、等待重試、失敗與總執行數。
  2. 失敗/重試/執行中項目優先摘要。
  3. 每個 job 的狀態、台北時間起訖、耗時與 message。
  4. 每個 task/API 的狀態、台北時間起訖、耗時與錯誤摘要。

動態文字會 HTML escape,過長 message/error 會截斷。郵件與 log 都不會輸出 SMTP_PASSWORDCLOUDFLARE_EMAIL_API_TOKEN

Runtime 設定

環境變數 必填條件 預設 說明
SCHEDULE_SUMMARY_MAIL_ENABLED 永遠 false true/false;必須明確啟用
SCHEDULE_SUMMARY_MAIL_TRANSPORT enabled smtp smtpcloudflare
SCHEDULE_SUMMARY_MAIL_TO enabled 逗號分隔收件人;不同環境使用不同名單
SMTP_HOST transport=smtp SMTP server hostname
SMTP_PORT transport=smtp 587 1..65535
SMTP_SECURITY transport=smtp starttls starttlssslnone
SMTP_USERNAME 視 SMTP provider 若設定,SMTP_PASSWORD 也必須設定
SMTP_PASSWORD 視 SMTP provider Secret;不得提交或印入 log
SMTP_FROM transport=smtp 寄件者,例如 Cortex Ops <cortex@example.com>
SMTP_TIMEOUT_SECONDS transport=smtp 15 正數;SMTP timeout
CLOUDFLARE_EMAIL_ACCOUNT_ID transport=cloudflare Cloudflare account ID
CLOUDFLARE_EMAIL_API_TOKEN transport=cloudflare 獨立 Email Sending: Edit token;Secret
CLOUDFLARE_EMAIL_FROM transport=cloudflare routing domain 寄件者
CLOUDFLARE_EMAIL_TIMEOUT_SECONDS transport=cloudflare 15 正數;REST request timeout

常見 transport 組合:

  • STARTTLS:通常使用 port 587SMTP_SECURITY=starttls
  • Implicit TLS:通常使用 port 465SMTP_SECURITY=ssl
  • 無 TLS:只應用於受控的本機 SMTP capture/內網 relay, SMTP_SECURITY=none;不可把帳密送到不受信任網路。

實際 hostname、port、帳號格式與寄件者驗證規則以所選 provider 文件為準。

Cloudflare Free

Cloudflare Free 僅能寄送至帳戶中的 Verified Destination Address,寄件者必須屬於 已啟用 Email Routing 的 domain。詳見 Cloudflare 官方的 REST API 寄信說明平台限制計價說明。Dev 範例:

SCHEDULE_SUMMARY_MAIL_ENABLED=false
SCHEDULE_SUMMARY_MAIL_TRANSPORT=cloudflare
SCHEDULE_SUMMARY_MAIL_TO=rdaoshiken@gmail.com
CLOUDFLARE_EMAIL_ACCOUNT_ID=<account-id>
CLOUDFLARE_EMAIL_API_TOKEN=<Email Sending: Edit token>
CLOUDFLARE_EMAIL_FROM=Cortex Dev <noreply@aoshiken.com>
CLOUDFLARE_EMAIL_TIMEOUT_SECONDS=15

先保持 disabled;確認 token 與收件地址後才切成 true。Cloudflare SMTP submission 需要 Workers Paid,Free plan 不應把 API token 填入 SMTP_PASSWORD

Dev 啟用

把設定放在 gitignored 的 investment-agent/.env,再解析 compose 確認值已傳入:

docker compose -f investment-agent/docker-compose.yml config scheduler

設定完成後,operator 可在核准的維護時段 recreate scheduler 讓新環境變數生效:

docker compose -f investment-agent/docker-compose.yml up -d --force-recreate scheduler

不要把 .env、provider app password、SMTP credential 或 Cloudflare token commit 到 Git。

SIT 設定

SIT CD 不讀主機 .env.sit。在 GitHub Settings → Secrets and variables → Actions 設定:

Secrets:

  • SMTP_USERNAME
  • SMTP_PASSWORD
  • CLOUDFLARE_EMAIL_API_TOKEN

Variables:

  • SCHEDULE_SUMMARY_MAIL_ENABLED
  • SCHEDULE_SUMMARY_MAIL_TRANSPORT
  • SCHEDULE_SUMMARY_MAIL_TO
  • SMTP_HOST
  • SMTP_PORT
  • SMTP_SECURITY
  • SMTP_FROM
  • SMTP_TIMEOUT_SECONDS
  • CLOUDFLARE_EMAIL_ACCOUNT_ID
  • CLOUDFLARE_EMAIL_FROM
  • CLOUDFLARE_EMAIL_TIMEOUT_SECONDS

第一次建議保持 SCHEDULE_SUMMARY_MAIL_ENABLED=false 部署,確認 scheduler 正常後再填完整 provider 設定並切成 true。SIT 收件人不可沿用 production 群組,避免測試訊息混入正式告警。

驗證與診斷

確認 registrar 已載入:

docker logs cortex-scheduler 2>&1 | rg "Daily Schedule Summary Mail"

查看最近寄送 audit:

docker exec cortex-postgres psql -U cortex -d cortex_investment -P pager=off -c "
SELECT id, status, reason, message, started_at, ended_at
FROM update_runs
WHERE job_name = 'schedule_summary_mail'
ORDER BY started_at DESC
LIMIT 20;"

查看 delivery task:

docker exec cortex-postgres psql -U cortex -d cortex_investment -P pager=off -c "
SELECT run_id, status, error_message, started_at, ended_at
FROM task_runs
WHERE job_name = 'schedule_summary_mail'
ORDER BY started_at DESC
LIMIT 20;"

狀態語意:

  • success:provider 已接受,當日後續 replay 會跳過。
  • failed:設定、DB builder 或 provider 失敗;人工重跑仍可再次嘗試。
  • skipped:功能未啟用,或當日已有 success。

Provider 已接受信件與 DB audit finalize 是兩個外部系統,無法原子 commit。極端情況下, provider 已接受但 success audit 寫入失敗,人工重跑可能寄出第二封;遇到此狀況應先查 收件匣/provider delivery log,再決定是否重跑。

安全停用

SCHEDULE_SUMMARY_MAIL_ENABLED=false 後 recreate scheduler。排程仍會存在,但每天只寫 一筆 skipped audit,不會解析其餘 provider 欄位,也不會建立網路連線。