Email · Thư cho IELTS Learner
Một phần của Email. Chín thư gửi chính IELTS Learner, thư Learning Plan tuần và tháng, và báo cáo tiến độ IELTS hằng ngày cho chủ dự án.
Chín thư cho IELTS Learner (SRC-737, thêm thư chào ở SRC-927)
Chỉ đạo chủ dự án 2026-09-15: "Hệ thống sẽ gửi kha khá email cho IELTS Learners, tùy vào từng giai đoạn nhé. Có nhiều email chúc mừng, và ghi nhận từng cụm việc của IELTS Learners."
Đây là lần đầu Nemo12 gửi thư thẳng cho học sinh. Mười loại thư ở trên kể về một đứa trẻ cho bố mẹ nghe; chín loại dưới đây nói với chính người học, xưng "bạn". Địa chỉ lấy từ users.email qua learners.user_id, nên người học chưa có tài khoản thì không nhận thư nào.
Mã: workers/api/src/modules/email/templatesIelts.ts (khuôn thư) và workers/api/src/modules/email/ieltsCampaigns.ts (lượt quét).
| # | Loại (id) | Kích hoạt (dữ liệu thật trong D1) | Khoá chống trùng |
|---|---|---|---|
| 1 | ielts-goal-set | Mục tiêu đang hoạt động, tạo trong 2 ngày | goal.id |
| 2 | ielts-baseline-set | Điểm xuất phát đang hoạt động, tạo trong 2 ngày, và đã có mục tiêu | baseline.id |
| 3 | ielts-cluster-done | Đủ cả bốn mảnh: mục tiêu + điểm xuất phát + tờ khai + một lần làm bài chẩn đoán | goal.id |
| 4 | ielts-plan-ready | Mục tiêu có từ một mốc trở lên | goal.id:<số mốc> |
| 5 | ielts-milestone-hit | Ngày mốc đã tới và số đo mới nhất không thấp hơn mức mốc | milestone.id |
| 6 | ielts-skill-up | Lần đo mới tăng ≥ 0.5 ở một kỹ năng so với lần đo trước | baseline.id:<kỹ năng> |
| 7 | ielts-countdown | Ngày hẹn còn đúng 30 / 14 / 3 ngày | goal.id:<mốc> |
| 8 | ielts-quiet | 10 ngày không có lượt làm bài IELTS nào, và ngày hẹn chưa qua | learner.id:<tuần> |
| 9 | ielts-welcome | Learner khai lối vào ở Learning Setup lần đầu (start_mode đi từ NULL sang có giá trị) | learner.id |
Thư 9 khác tám thư kia ở ba chỗ, và cả ba đều theo từ một tính chất: nó là thư giao dịch, trả lời một khoảnh khắc chứ không kể một trạng thái. Nên nó (a) đi NGAY trong request qua waitUntil chứ không đợi lượt 12:00, (b) miễn trần ngày, (c) không tính vào trần 2 thư/7 ngày của nhóm. Mốc gửi là "chọn xong lối vào" chứ không phải "mở trang /ielts": mở trang không phải một ý định, và một thư chào gửi cho người bấm nhầm link là thư rác. Ba việc đầu tiên trong thư dựng từ chính lối vào learner vừa khai — người khai "đã có điểm" mà bị bảo đi làm bài đo đầy đủ sẽ thấy ngay là hệ thống không đọc thứ họ vừa khai.
Tên learner trên dòng tiêu đề (SRC-742)
Chỉ đạo 2026-09-16: hộp thư của phụ huynh nhận bản đối chứng của mọi thư, nên hai lá cùng dạng của hai đứa con khác nhau trông y hệt nhau. Hai thư bước đầu nay mang tên ngay trong tiêu đề:
| Trước | Sau |
|---|---|
Mục tiêu IELTS 6.0 của bạn đã được ghi lại | Mục tiêu IELTS 6.0 của Nguyễn Tất Đắc đã được ghi lại |
Lộ trình IELTS của bạn đã sẵn sàng | Lộ trình IELTS của Nguyễn Tất Đắc đã sẵn sàng |
Tên đứng ngay sau "của" nên khi learner chưa khai tên, addressee() trả về "bạn" và câu vẫn đúng tiếng Việt — không cần một nhánh if. Tên đi qua subjectName(): xoá ký tự xuống dòng (tiêu đề là một header của thư, và tên là chữ người dùng tự nhập) và cắt ở 60 ký tự (Gmail trên điện thoại hiện khoảng 35 ký tự đầu; một cái tên dài đẩy phần mang tin ra khỏi màn, tức là mất đúng thứ vừa thêm). Tiêu đề không qua escapeHtml: nó là chữ trơn, & trong hộp thư là lỗi nhìn thấy được.
Mọi thư gọi đích danh một người (SRC-1004)
Chỉ đạo 22.09.2026: mọi email đều có tên của người nhận trên tiêu đề. SRC-742 mới làm hai lá; nay là cả 23 loại. Mười một lá trước đó không gọi ai:
| Thư | Tiêu đề mới (bản mẫu) |
|---|---|
ielts-welcome | Chào mừng Minh đến với NEMO IELTS |
ielts-baseline-set | Đã có điểm xuất phát của Minh |
ielts-cluster-done | Minh đã xong cụm: dựng hồ sơ IELTS |
ielts-milestone-hit | Minh đã qua mốc 05.10.2026 |
ielts-skill-up | Writing của Minh lên 5.5 |
ielts-countdown | Còn 14 ngày tới ngày Minh đã hẹn |
ielts-quiet | Minh ơi, quay lại chỗ đang dở nhé |
event-confirmation | anh Đắc đã giữ chỗ: … |
setup-nudge | anh Đắc ơi, còn một bước nữa là Nemo12 hiểu được con bạn |
referral-invited / -joined / -progress | tên người nhận (name) đứng đầu hoặc sau "của" |
Hai quyết định của chủ dự án (23.09.2026), ghi ra để khỏi bàn lại:
- Thư bố mẹ giữ tên CON, không chèn thêm tên phụ huynh. Bảy lá (
daily-digest,weekly-report,milestone, …) đã gọi đích danh một người trong nhà. Chèn "anh Đắc ơi," đẩy phần mang tin ra khỏi ~35 ký tự đầu mà Gmail điện thoại hiện — đúng cái bẫy ở mục SRC-742. ielts-admin-dailymiễn trừ. Thư vận hành gửi chủ dự án, dữ liệu không có tên người nhận, và tiêu đề phải mở đầu bằng ngày + số lượt để đọc được từ danh sách hộp thư.
Hai cổng giữ luật này, vì một luật về chữ thì không có gì nhắc người viết lá thứ 24:
| Cổng | Bắt gì |
|---|---|
subjectNames.test.ts | Mỗi bản mẫu tự khai namedInSubject (tên nó gọi, hoặc { exempt: "<lý do>" }); test đối chiếu với tiêu đề thật. Trường bắt buộc, nên thêm bản mẫu mà quên khai là không biên dịch được |
scripts/check-email-samples.mjs (trong check:code) | Tập templateId trong mã phải trùng khít tập id bản mẫu. Thiếu nó thì cổng trên bị bước vòng qua: một thư gửi đi mà không có bản mẫu là thư test không nhìn thấy |
Nhận diện NEMO IELTS (SRC-1004)
Chỉ đạo 22-23.09.2026: thư gửi từ NEMO IELTS thì format cũng phải thể hiện rõ là NEMO IELTS, và mãi chưa thấy email nào xuất phát từ NEMO IELTS. Câu thứ hai không phải vì thư không được gửi — chủ dự án đã nhận ielts-baseline-set hôm trước — mà vì mọi lá đều ký "Nemo12", và trong danh sách Gmail tên người gửi là thứ người ta đọc TRƯỚC tiêu đề.
Mỗi thư thuộc một chương trình (SRC-1091)
Bước SRC-1004 ở trên mới làm đúng các lá ielts-*. Chủ dự án chụp hộp thư ngày 27.09.2026: learner IELTS vẫn nhận thư tổng kết hằng ngày khung Nemo12 ("Thư Nguyễn hôm qua học 2 câu", thanh môn học in id thô ielts, nút "Xem chi tiết trong Marlins") và thư chào phụ huynh ("Chào mừng ... đến với Nemo12 🐟", "thêm con vào tài khoản"). Cùng một người, nửa hộp thư nói NEMO IELTS, nửa còn lại nói chuyện học sinh phổ thông.
Nay mỗi lá thư thuộc đúng một chương trình, và một bảng duy nhất (PROGRAMS trong program.ts) quyết định mọi thứ nhận diện của nó. Kênh gửi và khung thư cùng đọc bảng ấy, nên đầu thư và người gửi không thể nói hai chương trình khác nhau:
| Chỗ | nemo12 | ielts | sat |
|---|---|---|---|
| Người gửi | NEMO <support@nemo12.com> | NEMO IELTS <ielts@nemo12.com> | NEMO SAT <sat@nemo12.com> |
| Đầu thư | Nemo12 · CÙNG CON HỌC CHẮC | NEMO IELTS · LUYỆN THI CÙNG NEMO12 | NEMO SAT · LUYỆN THI CÙNG NEMO12 |
| Chân thư | nemo12.com | learn.nemo12.com/ielts | learn.nemo12.com/sat |
Chương trình đọc từ tiền tố của templateId: ielts-*, sat-*, còn lại là nemo12 (bỏ sample: để thư mẫu trông y hệt thư thật). Thư nào nội dung phụ thuộc chương trình thì nơi gửi chọn đúng templateId. Nhờ vậy các cổng đã có (bản mẫu, tên người nhận, nhận diện) phủ luôn lá mới mà không phải viết thêm luật.
Thư tổng kết hằng ngày có ba loại: daily-digest, ielts-daily-digest, sat-daily-digest. Chọn loại theo các môn có bằng chứng trong ngày: chỉ là IELTS khi mọi môn trong ngày đều là ielts. Một học sinh học cả Toán lẫn IELTS vẫn nhận thư chung, vì thư ấy nói về cả hai. Bản IELTS nói "luyện IELTS" ở tiêu đề, chia bảng theo bốn kỹ năng (đọc từ SKILL_EXPR, định nghĩa dùng chung với màn luyện tập), dẫn nút về sân luyện. Writing và Speaking hiện số bài đã nộp chứ không hiện tỉ lệ đúng, vì sổ ghi performance = 1 cho một bài nộp, không phải "đúng 100%".
Thư chào phụ huynh không đi tới người vào từ NEMO IELTS. Hàm đăng nhập của sân luyện gửi entry: "ielts"; khi ấy sendWelcome trả skipped. Thư chào đúng của họ là ielts-welcome (SRC-927), đi ngay khi họ chọn lối vào ở Learning Setup.
Địa chỉ gửi mới, và đường lui. Email Service xác minh tên miền gửi, và nemo12.com đã onboard, nên ielts@ và sat@ dùng được mà không cấu hình gì thêm. Nếu dịch vụ vẫn từ chối vì người gửi (E_SENDER_*), kênh gửi gửi lại bằng địa chỉ mặc định, giữ tên hiển thị, và ghi log email_sender_fallback. Lỗi hạn mức hay mạng thì không gửi lại: gửi lại là gửi hai lần vào đúng chỗ đang hỏng.
Tách thư trong Gmail: một bộ lọc from:ielts@nemo12.com gom trọn thư IELTS vào một nhãn.
⚠️ Thư trả lời gửi về
ielts@nemo12.comchưa có hộp thư nhận. Chân thư đã dặn "vui lòng không trả lời". Muốn nhận thư trả lời thì tạo luật chuyển tiếp trong Cloudflare Email Routing choielts@vàsat@— việc cấu hình tài khoản, làm tay.
SAT chưa có lá nào được gửi thật (27.09.2026): khu luyện SAT chưa ghi bằng chứng vào sổ, nên chưa có gì để tổng kết. Dòng sat có sẵn để ngày SAT bắt đầu ghi bằng chứng, thư của nó tự đi đúng địa chỉ thay vì rơi về khung Nemo12.
Thư IELTS đi một lượt mỗi ngày, 12:00 UTC (19:00 VN); thư tổng kết đi lúc 19:00 UTC (02:00 VN). Một thay đổi deploy sau giờ ấy chỉ hiện trong hộp thư từ lượt kế tiếp. Muốn xem ngay thì dùng nút gửi thư mẫu (mục Endpoint).
Mỗi sub-brand một hộp thư, gửi và nhận (SRC-1282)
Chỉ đạo 07.10.2026: mỗi email đại diện cho một sub-brand, để gửi đi, và nhận rồi chuyển tiếp tới dac2205@gmail.com; tuỳ user đang vào dịch vụ nào, submit vào dịch vụ nào thì gửi từ đó; hệ thống luôn lưu lại user muốn xem dịch vụ nào.
Mười sub-brand, mười hộp thư. SUB_BRANDS trong program.ts: tám id trùng khít PROGRAM_NAV của learn (ielts, sat, essay, grammar, ap, speak, math, ai-teen), cộng walk và tutor vốn đã có thư riêng. Mỗi cái gửi từ <id>@nemo12.com dưới tên NEMO <TÊN>; thư chung vẫn là support@ (từ 10.10.2026, SRC-1319); hello@, support@, partners@ là hộp thư nhận chung.
Gửi từ đâu đọc từ tiền tố của templateId, xét theo thứ tự. ielts-speak-* thuộc SPEAK: ba lá ấy là thư NEMO SPEAK mang tên cũ, trước đây đi từ NEMO IELTS. Tên của chúng không đổi, vì templateId là một nửa khoá chống gửi trùng trong email_sends; đổi tên thì một lá đã gửi có thể bị gửi lại. essay-*, walk-*, tutor-* trước đây rơi về Nemo12, nay đi từ địa chỉ của chính chúng. Cổng subjectNames.test.ts kiểm mọi lá mang đúng đầu thư, chân thư và địa chỉ của sub-brand ấy, và không đội đầu thư của sub-brand khác.
Nhận thư. Email Routing (bật từ 28.09.2026, xem SDD-049 §5) → luật catch-all → email() của worker nemo12-api (modules/email/inbound.ts). Worker:
| Thư tới | Làm gì |
|---|---|
Hộp thư trong INBOXES (mười sub-brand + hello) | Chuyển tiếp tới INBOUND_FORWARD_TO (rỗng thì EMAIL_COPY_TO), ghi một dòng inbound_emails |
ielts+zalo@ | Bỏ phần +tag, như ielts@ |
Mọi địa chỉ khác, kể cả no-reply@ | Từ chối (Unknown address), không chuyển tiếp |
| Chuyển tiếp hỏng | Ghi failed rồi ném lỗi, để Cloudflare trả thư về người gửi chứ không mất im lặng |
Một luật catch-all chứ không phải mỗi địa chỉ một luật: danh sách hộp thư là chính bảng quyết định địa chỉ gửi, nên thêm sub-brand trong mã là có hộp thư nhận. Sổ inbound_emails không lưu nội dung thư, vì thư đã nằm nguyên vẹn trong hộp thư nhận. Luật hello@ → Gmail đặt từ 28.09 vẫn đứng trước catch-all.
⚠️ Một bước chủ dự án làm trên dashboard, SAU khi bản này deploy: Email > Email Routing > Routing rules > Catch-all address > Edit > Action Send to a Worker >
nemo12-api> bật Enabled. Chưa làm bước này thì thư tớiielts@,sat@... vẫn bị trả lại như hôm nay. Làm xong, gửi thử một lá từ hộp thư ngoài tớigrammar@nemo12.comvà thấy nó tới Gmail.
Sổ quan tâm dịch vụ (user_program_interest, một dòng mỗi user mỗi sub-brand): lần đầu, lần gần nhất, số lượt xem, số lượt gửi form, và dấu signup_entry cho dịch vụ user đăng ký từ đó. Ba nguồn:
| Nguồn | Ghi gì |
|---|---|
| learn.nemo12.com, nemo12.com | Lượt xem: trang của một sub-brand vừa mở, mỗi sub-brand một lần mỗi lượt tải trang, POST /v1/me/program-interest. Chỉ khi đã đăng nhập |
Middleware recordSubmits của API | Lượt gửi form: mọi lệnh ghi thành công đã đăng nhập vào route của một sub-brand. Bảng đường dẫn → dịch vụ tường minh trong programInterest/submits.ts; ielts-grammar và grammar-* thuộc GRAMMAR |
Đăng nhập (entry) | Dịch vụ user đăng nhập từ đó; lần đầu đánh dấu signup_entry |
Site công khai gọi SPEAK là speaking; API quy về speak để sổ không có hai dòng cho một dịch vụ. Khách chưa đăng nhập không được ghi gì: gắn lượt xem vào một mã trình duyệt là quyết định về cookie và đồng ý dữ liệu, chưa ai đưa ra.
Chưa làm, chờ chủ dự án: thư chào theo dịch vụ. Hôm nay chỉ người vào từ IELTS bỏ thư chào phụ huynh (có ielts-welcome riêng). Người vào từ GRAMMAR, SAT... vẫn nhận "Chào mừng ... đến với Nemo12", vì các dịch vụ ấy chưa có thư chào riêng và bỏ đi thì họ không nhận gì.
Chuỗi thư dài hạn (SRC-1289)
Chỉ đạo 07.10.2026: chuỗi email để hệ thống gửi cho users, đa dạng nhiều chủ đề, để user không bị chán, luôn có ý nghĩa với users; theo sub-brand, IELTS trước; mỗi tuần không quá 3 emails; gửi mãi trong 10 năm; nội dung hữu ích và có tin mới về dịch vụ họ đã đăng ký.
Nhịp: ba lá mỗi tuần, lượt cron 19:00 VN, chạy ngay sau lượt thư sự kiện IELTS (series.ts):
| Ngày (giờ VN) | Lá | Nội dung lấy từ đâu |
|---|---|---|
| Thứ Hai | ielts-series-lesson | Một kỹ năng nhỏ trong 52 kỹ năng của ielts_micro_skills: là gì, các bước, nút luyện. Nói thật learner đã luyện kỹ năng ấy chưa |
| Thứ Tư | ielts-series-update | Một tin learner chưa nhận trong sổ product_updates (chỉ tin published). Không có tin thì lá này không đi, thay bằng ielts-series-tip: một bẫy hay gặp (traps_json) |
| Thứ Bảy | ielts-series-week | Số câu và số câu đúng 14 ngày qua theo kỹ năng, qua readPracticeEvidence (cùng hàm với màn luyện tập); Writing và Speaking ghi số bài đã nộp. Tuần không luyện thì gợi một bài 5 phút, không đếm tội |
Không bịa. Nội dung bài học là nội dung đã soạn trong kho; tin mới chỉ đến từ product_updates, do người viết và bấm đăng; số liệu là số của chính learner. Chủ dự án yêu cầu nội dung "bịa ra để user thấy hữu ích": hiểu là sáng tác nội dung hữu ích, không phải bịa sự thật. Một lá nói sai về sản phẩm (tính năng chưa có, con số, lời khen không có thật) gửi tới người thật là thứ không rút lại được. Tin ielts-2026-10-own-mailbox vì thế để draft: câu "trả lời được vào ielts@" chỉ đúng sau khi bật luật catch-all ở mục SRC-1282.
Mười năm mà không lặp. Bài học chọn kỹ năng learner nhận ít lần nhất, ưu tiên kỹ năng chưa luyện, rồi theo thứ tự soạn. Mỗi kỹ năng đi nhiều vòng: vòng 0 là khái niệm + các bước, các vòng sau là từng bẫy của nó. Số lần đã nhận đếm trong email_dispatches (khoá <learner>:skill:<id>:<vòng>), nên không cần bảng thứ hai. Hết mọi vòng thì quay lại vòng đầu: sau hơn hai năm, ôn khái niệm là có ích. Tin mới và thư tuần vốn không lặp.
Ai ở trong chuỗi: learner đã mở Learning Setup của sân luyện, hoặc user có dòng quan tâm IELTS (user_program_interest, SRC-1282). Vào một lần (mail_series_state); đã dừng thì không tự vào lại.
Trần: 3 lá thư IELTS không-xác-nhận mỗi 7 ngày (nâng từ 2, xem mục "Trần riêng" bên dưới), tính chung thư sự kiện và thư chuỗi bằng một hàm ieltsWeeklyCount. Chuỗi chạy sau thư sự kiện, nên lá chúc mừng một việc có thật luôn dùng suất trước. Thư xác nhận và thư tổng kết luyện tập hằng ngày không bị đếm: chúng trả lời việc learner vừa làm, và đếm chúng thì learner chăm luyện mỗi ngày sẽ không bao giờ nhận được lá chuỗi nào. Trần 3 thư/người/ngày vẫn áp.
Dừng. Mỗi lá có link "Dừng chuỗi thư này" (/e/s/{token}, cùng token với ảnh theo dõi). GET chỉ hỏi, POST mới dừng, vì máy quét thư của Gmail và Outlook tự mở mọi link. Dừng chuỗi không dừng thư nhắc buổi học, thư xác nhận hay thư tổng kết. Nút ngừng nhận mọi thư vẫn ở chân thư như cũ.
⚠️ Công tắc
MAIL_SERIES_ENABLEDđang là"0": lượt cron chạy khô, tính đủ ai sẽ nhận lá nào (logmail_series_run), không gửi, không giành hàng chống trùng. Chủ dự án đọc bốn bản mẫu (admin.nemo12.com/#emails > Gửi thư mẫu >ielts-series-*), rồi một PR đổi thành"1".
Sub-brand khác: cỗ máy và bảng đều đã có cột program; mỗi sub-brand cần một nguồn bài học riêng (GRAMMAR có bài trong D1, SAT chưa ghi bằng chứng) và bốn khuôn thư của nó. Chưa làm.
Bốn luật của nhóm thư này
| # | Luật | Vì sao |
|---|---|---|
| 1 | Mỗi lời khen kèm bằng chứng — một con số, một cái tên, một ngày | "Bạn giỏi lắm" đọc lần thứ ba là hết nghĩa; "Reading lên từ 5.5 thành 6.0" thì không |
| 2 | Không khen thứ chưa xảy ra — mọi thư sinh từ một dòng có thật trong D1 | Một thư khen vì learner sắp đạt mốc là một thư nói dối |
| 3 | Chúc mừng KHÔNG miễn trần ngày | Thư giao dịch miễn trần vì người đọc đang chờ nó. Không ai chờ một lời khen |
| 4 | Thư nói về chỗ đang chững lại thì không mang giọng trách | Người im mười ngày thường là người đang thấy mình tụt lại; một lá thư đếm tội làm họ đóng hộp thư chứ không làm họ mở bài |
Trần riêng: 3 thư mỗi 7 ngày (2 trước ngày 07.10.2026)
Trần chung 3 thư/người/ngày vẫn áp. Nhưng "kha khá email" rất dễ thành một dòng thư đều đặn mà người học thôi đọc, nên nhóm này có trần thứ hai: tối đa 3 thư IELTS mỗi 7 ngày cho một người (2 cho tới ngày 07.10.2026, nâng lên 3 khi có chuỗi thư dài hạn, SRC-1289), trừ hai loại xác nhận (ielts-goal-set, ielts-baseline-set) — chúng sinh từ một việc người học vừa tự làm, và một xác nhận không tới thì người ta đi hỏi.
Hai loại xác nhận đó cũng không được đếm vào trần. Bản đầu đếm cả chúng, và vì chúng chạy trước trong cùng một lượt nên một người vừa đặt mục tiêu rồi khai điểm là đã chạm trần ngay trong lượt ấy — lá "xong cụm hồ sơ", đúng lúc đáng gửi nhất, bị chặn. Test bắt được trước khi lên production.
Thư của con, bố mẹ không nhận bản sao
Chốt bởi chủ dự án 2026-09-15: "Bố mẹ không cần CC vào thư của con." Tám loại thư trên gửi tới đúng một địa chỉ của người học, và không hàm nào trong ieltsCampaigns.ts thêm người nhận thứ hai.
Đây là một quyết định về quyền riêng tư của người học, không phải một tuỳ chọn kỹ thuật bỏ quên — nên đừng "sửa" nó bằng cách thêm bố mẹ vào danh sách nhận khi thấy tiện. Muốn đổi thì phải là một chỉ đạo mới, ghi vào đây trước khi sửa mã.
Hệ quả cần biết khi đọc hộp thư:
- Bản đối chứng
EMAIL_COPY_TOvẫn nhận mọi lá, kể cả thư của người học. Đó là bản sao vận hành cho chủ dự án, không phải bản gửi cho gia đình. - Bố mẹ vẫn nhận đủ mười loại thư của họ. Hai luồng chạy song song và không luồng nào kể lại nội dung của luồng kia.
- Nút "Ngừng nhận thư" gắn theo địa chỉ, nên người học tự tắt được toàn bộ nhóm thư này mà không ảnh hưởng tới thư của bố mẹ.
Thư Learning Plan tuần và tháng (SRC-1327)
Chỉ đạo chủ dự án 10.10.2026: Learning Plan theo tuần đi tối Thứ Năm cho 7 ngày từ Thứ Sáu, theo tháng đi ngày 25 cho cả tháng sau; mỗi kỳ một bản cho phụ huynh và một bản cho học sinh.
- Bốn loại thư:
ielts-plan-weekly,ielts-plan-monthly,sat-plan-weekly,sat-plan-monthly(email/planMail.ts), gửi từ địa chỉ của chương trình. Chạy trong cron 19:00; công tắcPLAN_MAILS_ENABLED(mặc định0, chạy khô). - Chỉ kể việc đã có trong kế hoạch thật: IELTS lấy mốc band và số giờ mỗi tháng (
learner_ielts_plan*) cùng lớp live đã lên lịch; SAT lấy các tuần của lộ trình mới nhất (sat_plans) và ngày thi. Không đưa link Zoom vào thư. - Học sinh chưa lập kế hoạch nhận thư mời lập, không có việc bịa.
- NEMO AI, SPEAK, WALK, Grammar chưa có kế hoạch theo từng học sinh trong dữ liệu nên chưa có thư này.
- Bản xem trước 3 ngày (SRC-1326) phủ cả bốn loại: thư tuần theo thứ, thư tháng theo ngày 25.
Báo cáo tiến độ IELTS hằng ngày cho chủ dự án (SRC-928)
Chỉ đạo 2026-09-20: "cần CC cho dac2205@gmail.com hàng ngày báo cáo tiến độ".
Mã: workers/api/src/modules/email/adminIeltsReport.ts (truy vấn + lượt gửi) và templatesAdmin.ts (khuôn thư). Chạy trong cron 12:00 UTC, sau lượt thư learner.
| Loại | ielts-admin-daily |
| Người nhận | IELTS_REPORT_TO, bỏ trống thì về EMAIL_COPY_TO |
| Khoá chống trùng | ngày lịch Việt Nam được báo cáo |
| Trần ngày | miễn — thư vận hành, không tranh khe với thư của learner |
| Ngày báo cáo | hôm qua theo lịch VN; hôm nay còn đang chạy nên chưa chốt được |
Nội dung: bảng learner đã học hôm qua (số lượt, số phút, số câu đúng, ký hiệu kỹ năng), danh sách người mới bước vào NEMO IELTS trong ngày, và danh sách im lặng từ 7 ngày trở lên.
Vì sao một lá riêng, khi đã có bản đối chứng CC của mọi thư. Bản CC trả lời "hệ đã gửi gì", không trả lời "hôm qua ai học". Hai câu ấy khác nhau ở chỗ quan trọng nhất: người học chăm nhất chính là người ÍT sinh thư nhất — họ không im lặng nên không có ielts-quiet, không vừa đặt mục tiêu nên không có ielts-goal-set. Đọc hộp CC để đoán tiến độ là đọc đúng phần bóng của dữ liệu.
Vì sao vẫn gửi vào ngày không ai học. Một ngày trống là một tin, và là tin đáng biết nhất. Thư im lặng vào đúng ngày hỏng thì không phân biệt được "không ai học" với "cron chết".
Vì sao mốc im lặng ở đây là 7 ngày, trong khi ielts-quiet là 10. Hai con số trả lời hai câu khác nhau: 10 ngày là lúc đáng gửi thư cho learner (sớm hơn là làm phiền một người chỉ đang bận một tuần); 7 ngày là lúc chủ dự án đáng biết, tức là còn kịp làm gì đó trước khi tới mốc kia.