網路安全策進會 NYCU Cyber Security Club 的社費電子收據寄送程式。讀取繳費名單 CSV,透過 SMTP2GO API 逐一寄出收據給每位學員。
- Node.js 22 以上與 pnpm
- SMTP2GO 帳號
- 驗證寄件網域(建議)或單一寄件信箱,
SENDER_EMAIL必須是已驗證的地址 - 建立 API Key,權限至少開啟
/email/send
- 驗證寄件網域(建議)或單一寄件信箱,
pnpm install
cp .env.example .env # 已經有 .env 就跳過社團名稱、寄件人名稱、信件主旨都直接寫在程式與模板裡,.env 只放每次寄送會變動的設定。
| 變數 | 必填 | 說明 |
|---|---|---|
SMTP2GO_API_KEY |
✓ | SMTP2GO API Key |
SMTP2GO_API_URL |
預設 https://api.smtp2go.com/v3,也可用 us-api、eu-api、au-api |
|
SENDER_EMAIL |
✓ | 寄件信箱,寄件人名稱固定為「網路安全策進會 NYCU Cyber Security Club」 |
REPLY_TO |
學員按「回覆」時寄到的信箱;收據寫著「有問題直接回覆這封信」,請填有人在看的信箱 | |
FEE_ITEM |
✓ | 繳費項目,例如 115 學年度社費 |
FEE_ITEM_EN |
✓ | 繳費項目的英文名稱,會和中文並列在信裡,例如 2026-27 Membership Fee |
FEE_AMOUNT |
✓ | 金額(新台幣,正整數) |
PAYMENT_DATE |
收款日期 YYYY-MM-DD,預設為執行當天(台北時間) |
|
RECEIPT_PREFIX |
收據編號前綴;編號為 前綴-學號,例如 CSC115-110550001 |
|
ISSUER |
經手人,例如 總務 王小明 |
|
MEMBERS_CSV |
名單路徑,預設 data/members.csv |
|
SEND_INTERVAL_MS |
每封信之間等待的毫秒數,預設 1000 |
放在 data/members.csv,格式參考 data/members.example.csv:
姓名,學號,Email
王小明,115550001,xiaoming.wang@example.com- 表頭也接受
Name、Student ID、E-mail等英文寫法,欄位順序不限,多餘的欄位會忽略 - 從 Excel 匯出時請選「CSV UTF-8」
- 寄送前會先檢查整份名單:空白欄位、Email 格式、重複的學號或 Email,有任何一行有問題就不會寄出任何信
pnpm check # 1. 檢查 .env 與名單,列出每個人是否已寄出
pnpm preview # 2. 產生 preview/receipt.html,用瀏覽器打開看收據
pnpm send --test you@example.com # 3. 用名單第一個人的資料寄測試信給自己(主旨會加上 [測試])
pnpm send # 4. 正式寄出,輸入 yes 確認其他選項:
--id 學號:只處理指定的學員,可重複使用,例如pnpm send --id 115550001 --id 115550002--force:連已寄出的人也重寄--yes:不詢問直接寄出
每寄出一封,就在 logs/sent.jsonl 寫入一行紀錄(收據編號、Email、SMTP2GO email_id、寄出時間)。再次執行 pnpm send 會略過紀錄裡已寄出的人,所以中途中斷或部分失敗時,修正問題後直接重跑即可。
- 遇到 HTTP 429(太頻繁)或 5xx,會以 2、4、8、16 秒的間隔自動重試
- API Key 無效(401/403)會立刻停止;連續 3 封失敗也會停下來,通常是寄件人尚未驗證
- 連線逾時後重試的極少數情況下,學員可能收到兩封,可以到 SMTP2GO 後台的寄送紀錄確認
- 模板在
templates/receipt.html(HTML)與templates/receipt.txt(純文字),使用 Mustache 語法 - 圖片(主視覺、PAID 印章、結尾狐狸)是用
pnpm assets從assets/background.png與assets/logo.svg轉成的 ASCII art,輸出到assets/email/。社團主視覺原圖assets/background.png不在 repo 裡,要重新產生圖片時請另外放進去;產生時需要 macOS 內建的 Menlo 與 PingFang TC 字型 - 寄出的信直接引用 GitHub 上的圖片:
https://raw.githubusercontent.com/bamboofox/receipt/main/assets/email/。改圖之後要 push 到 main 才會生效,而且已經寄出的信也會跟著顯示新圖 pnpm preview產生的預覽檔會改用本機的assets/email/,還沒 push 的圖也看得到
Gmail App 在深色模式下會自動把信件的淺色背景反轉成深色、深色文字反轉成淺色,而且無法關閉。所以模板刻意這樣設計:
- 版面是淺色的,並宣告
color-scheme: light,Apple Mail 等尊重這個設定的信箱會維持淺色 - 圖片都是透明背景,只用霓虹橘
#FF5A1F與電光藍#2F5BEA這種中間調的顏色。Gmail 不會改圖片的顏色,所以不管底色被反轉成白或黑都看得清楚,反轉後剛好是社團原本的黑底霓虹風格 - 不要在圖片裡使用黑色或白色的文字或線條,底色反轉後會看不見
- SMTP2GO 免費方案每月 1,000 封、每天 200 封;尚未驗證寄件網域時每小時只能寄 25 封,人數多時請先驗證網域,或把
SEND_INTERVAL_MS調到150000(2.5 分鐘)以上 data/*.csv、preview/、logs/含學員個資,已列入.gitignore
assets/background.png 社團主視覺原圖(不進版控)
assets/logo.svg 社團 logo
assets/email/ 信件用的圖片(pnpm assets 產生)
templates/receipt.html HTML 收據模板
templates/receipt.txt 純文字收據模板
data/ 繳費名單 CSV
scripts/build-email-assets.js 產生信件圖片
src/cli.js 指令入口(check / preview / send)
src/config.js 讀取並檢查 .env
src/members.js 讀取並檢查名單
src/template.js 套用模板
src/smtp2go.js SMTP2GO API 與重試
src/sent-log.js 寄送紀錄