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/plain 與 text/html:
- 成功、等待重試、失敗與總執行數。
- 失敗/重試/執行中項目優先摘要。
- 每個 job 的狀態、台北時間起訖、耗時與 message。
- 每個 task/API 的狀態、台北時間起訖、耗時與錯誤摘要。
動態文字會 HTML escape,過長 message/error 會截斷。郵件與 log 都不會輸出
SMTP_PASSWORD 或 CLOUDFLARE_EMAIL_API_TOKEN。
Runtime 設定
| 環境變數 | 必填條件 | 預設 | 說明 |
|---|---|---|---|
SCHEDULE_SUMMARY_MAIL_ENABLED |
永遠 | false |
true/false;必須明確啟用 |
SCHEDULE_SUMMARY_MAIL_TRANSPORT |
enabled | smtp |
smtp 或 cloudflare |
SCHEDULE_SUMMARY_MAIL_TO |
enabled | 空 | 逗號分隔收件人;不同環境使用不同名單 |
SMTP_HOST |
transport=smtp |
空 | SMTP server hostname |
SMTP_PORT |
transport=smtp |
587 |
1..65535 |
SMTP_SECURITY |
transport=smtp |
starttls |
starttls、ssl 或 none |
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
587、SMTP_SECURITY=starttls。 - Implicit TLS:通常使用 port
465、SMTP_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_USERNAMESMTP_PASSWORDCLOUDFLARE_EMAIL_API_TOKEN
Variables:
SCHEDULE_SUMMARY_MAIL_ENABLEDSCHEDULE_SUMMARY_MAIL_TRANSPORTSCHEDULE_SUMMARY_MAIL_TOSMTP_HOSTSMTP_PORTSMTP_SECURITYSMTP_FROMSMTP_TIMEOUT_SECONDSCLOUDFLARE_EMAIL_ACCOUNT_IDCLOUDFLARE_EMAIL_FROMCLOUDFLARE_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 欄位,也不會建立網路連線。