Phạm Văn Thư
Quản trị doanh nghiệp · AI-assisted content

listmonk: tự vận hành hệ thống gửi thư hàng loạt cho nhà xe vận tải hành khách

Đăng ngày 12/10/2026

Mục lục bài nghiên cứu
Hình đại diện listmonk — phần mềm quản trị doanh nghiệp mã nguồn mở

listmonk có đáng để một nhà xe tự vận hành hệ thống gửi thư không?

listmonk là phần mềm quản lý danh sách thư và bản tin chạy độc lập, tự lưu trữ, đóng gói thành một tệp nhị phân và dùng PostgreSQL làm nơi lưu dữ liệu. [1] Nó phục vụ ba việc chính: lưu người nhận cùng thuộc tính của họ, gửi chiến dịch hàng loạt tới các danh sách, và gửi thông điệp giao dịch từng người qua API. [4] Phần mềm được cấp phép AGPLv3. [1][2]

Nên cân nhắc khi một doanh nghiệp có tập khách hàng đủ lớn để việc gửi thủ công qua tài khoản thư thông thường trở nên khó kiểm soát, đồng thời muốn giữ danh sách khách trên máy chủ của mình thay vì thuê bao theo số người nhận. Không nên chọn nếu không có ai đủ kỹ năng quản trị cơ sở dữ liệu và cấu hình gửi thư, vì phần khó nhất của gửi thư hàng loạt là danh tiếng máy chủ gửi và việc tuân thủ, chứ không phải phần mềm. Phần này là nhận định của người viết, không rút ra từ một nguồn cụ thể.

Bài này là nghiên cứu tài liệu tại một commit cố định. Chưa có thao tác cài đặt, gửi thư thật hay đo thông lượng nào được thực hiện, nên mọi nhận định về hiệu năng chỉ dựa trên điều tài liệu của dự án tự mô tả.

Bài toán của nhà xe: nhắc đúng khách, đúng tuyến, đúng lúc

Một nhà xe khách liên tỉnh thường có ba nhóm người cần liên lạc: khách đã từng đặt vé, khách quan tâm một tuyến nhưng chưa đặt, và đối tác như đại lý bán vé. Mỗi nhóm cần nội dung khác nhau, từ thông báo đổi giờ xuất bến đến ưu đãi mùa lễ. Nếu mọi thứ đi qua một tài khoản thư và bảng tính, rất khó biết ai đã hủy đăng ký, ai chưa xác nhận, và ai cần được loại khỏi đợt gửi.

listmonk nhắm đúng lớp việc đó. Khái niệm người đăng ký gắn với địa chỉ thư, tên và một bộ thuộc tính tùy ý dạng JSON; người đăng ký thuộc một hay nhiều danh sách, và mỗi quan hệ có trạng thái chưa xác nhận, đã xác nhận hoặc đã hủy. [4] Cấu trúc này khớp với việc phân loại khách theo tuyến, nhưng chỉ khi nhà xe thật sự thu thập và giữ thuộc tính một cách có kỷ luật.

Có một giới hạn cần nói trước: phần mềm không tạo ra sự đồng ý của người nhận. Tài liệu khái niệm mô tả danh sách single opt-in và double opt-in, nhưng việc thu thập chấp thuận hợp lệ theo pháp luật Việt Nam là trách nhiệm của đơn vị gửi. [4] Nhà xe cần đối chiếu quy định hiện hành về tin nhắn quảng cáo và dữ liệu cá nhân với tư vấn pháp lý, vì nguồn đã đọc không bàn về luật Việt Nam.

Một tệp nhị phân Go, một cơ sở dữ liệu Postgres, một giao diện quản trị

README cho biết backend viết bằng Go, frontend dùng Vue với Buefy, và ứng dụng gói trong một tệp nhị phân duy nhất, dữ liệu nằm trong PostgreSQL. [1] Tài liệu cài đặt nêu rõ cần phiên bản Postgres từ 12 trở lên và bước khởi tạo bảng bằng cờ install. [6] Như vậy phần phải vận hành gồm hai thành phần: tiến trình listmonk và cơ sở dữ liệu.

Tài liệu cấu hình cho biết một hoặc nhiều tệp TOML có thể được nạp, nhưng ngoài vài biến cấp thấp và cấu hình cơ sở dữ liệu, các thiết lập khác được quản lý ngay trong trang Settings của giao diện quản trị. Biến môi trường tiền tố LISTMONK_ với hai dấu gạch dưới thay cho dấu chấm cũng được hỗ trợ. [5] Điều này giúp triển khai bằng container gọn hơn, vì cấu hình nhạy cảm có thể đi qua biến môi trường.

Về mở rộng, khái niệm Messenger cho phép thêm kênh gửi ngoài SMTP: một Messenger là một dịch vụ web nhận thông điệp chiến dịch dạng JSON rồi tự phát đi dưới dạng SMS, thông báo đẩy hoặc kênh khác. [4] Nói cách khác, listmonk không tự cung cấp cổng SMS; nó chỉ có chỗ để cắm cổng do bạn hoặc nhà cung cấp viết.

Từ một dòng khách hàng đến một thư nằm trong hộp thư

Bắt đầu từ người đăng ký. Một khách có thể được nhập hàng loạt, thêm qua API hoặc tự đăng ký qua trang công khai. Thuộc tính của họ được lưu dạng JSON và có thể dùng để lọc thành nhóm nhỏ hơn hoặc chèn vào nội dung thư. [4] Với các danh sách double opt-in, người đăng ký chỉ nhận chiến dịch sau khi bấm xác nhận trong thư xác nhận. [4]

Khi chạy chiến dịch, tài liệu cấu hình mô tả tham số batch size là số người đăng ký được lấy tuần tự từ cơ sở dữ liệu trong một chu kỳ khoảng năm giây. Tăng giá trị này dùng nhiều bộ nhớ hơn nhưng giảm số vòng truy vấn, và tài liệu nói nó hữu ích với danh sách hàng triệu người. [5] Thư đi qua nhóm kết nối SMTP; cài đặt thử lại cho phép gửi lại lặng lẽ bằng kết nối khác, và thư vẫn lỗi sau các lần thử đó bị ghi nhận lỗi rồi bỏ qua. [5]

Phần quay lại là theo dõi và bounce. Tài liệu khái niệm mô tả điểm ảnh theo dõi để đo lượt xem, theo dõi liên kết để đo lượt bấm, và xử lý thư bị trả về từ hộp POP hoặc API của nhà cung cấp như AWS SES, Sendgrid; người nhận trả thư hỏng có thể bị chặn hoặc xóa tự động theo cài đặt. [4] Hai kiểu theo dõi đều có hàm ý riêng tư và có thể bật ở chế độ ẩn danh. [4]

Tính năng đã có trong tài liệu, tách khỏi những gì cần tự ghép

Ở mức người dùng, tài liệu khái niệm liệt kê người đăng ký có thuộc tính, danh sách single hoặc double opt-in, chiến dịch gửi tới một hay nhiều danh sách, thông điệp giao dịch qua API, mẫu HTML dùng biểu thức Go template, Messenger, điểm ảnh theo dõi, theo dõi bấm liên kết và xử lý bounce. [4] Tài liệu cũng nhắc việc phân đoạn người đăng ký theo thuộc tính. [4]

Về quản trị, từ phiên bản 4.0.0 trở đi hệ thống có tài khoản người dùng với quyền chi tiết, gồm vai trò người dùng và vai trò danh sách; đăng nhập bằng mật khẩu hoặc OIDC nếu kết nối nhà cung cấp danh tính. [8] Người dùng loại API nhận một mã bí mật sinh tự động để gọi API bằng chương trình. [8]

Cần phân biệt thứ có sẵn với thứ phải tự dựng. Gửi SMS, tích hợp phần mềm bán vé, đồng bộ dữ liệu khách từ hệ thống đặt chỗ: các việc này nằm ở Messenger, API hoặc nhập dữ liệu, tức là phải có công sức tích hợp. Trong nguồn đã đọc không có đề cập đến một mô-đun bán vé hay quản lý chuyến xe. Ngoài ra, bản nightly được tài liệu cài đặt cảnh báo là chưa kiểm thử và có thể lỗi, nên không phải tính năng ổn định. [6]

Những tổ chức hợp với listmonk, và những tổ chức nên dùng dịch vụ gửi thư trả phí

Người dùng điển hình là đội có kỹ năng kỹ thuật vừa phải, cần gửi bản tin hoặc chiến dịch cho tập khách vài nghìn đến hàng trăm nghìn người, và muốn kiểm soát dữ liệu. README nhắm tới nhà phát triển với phần hướng dẫn đóng góp, và bản thân dự án mô tả mình là phần mềm tự lưu trữ. [1] Các ngành có khách quay lại theo chu kỳ như vận tải hành khách, giáo dục, phòng khám hay cửa hàng bán lẻ đều có thể nằm trong nhóm này.

Nhóm nên cân nhắc dịch vụ gửi thư có sẵn là đơn vị không có người vận hành, hoặc chỉ gửi vài chục thư mỗi tháng. Gánh nặng vận hành, sao lưu và theo dõi danh tiếng gửi sẽ lớn hơn lợi ích. Người dùng cũng cần biết rằng listmonk gửi qua SMTP hay dịch vụ bên thứ ba, không tự bảo đảm thư vào hộp thư đến; thư đi qua cấu hình SMTP do bạn chọn. [5]

Với các đội muốn nhiều người cùng làm trên một hệ thống, mô hình vai trò giúp chia việc: một người soạn nội dung, một người duyệt và một người có quyền gửi. Tài liệu nhấn mạnh quyền gửi chiến dịch tách khỏi quyền quản lý chiến dịch. [8]

Tình huống giả định: nhà xe liên tỉnh gửi thông báo chuyến và ưu đãi theo tuyến

Giả sử một nhà xe khách chạy vài tuyến liên tỉnh có hệ thống đặt vé riêng và khoảng vài chục nghìn địa chỉ thư của khách cũ. Đây là đề xuất áp dụng, không phải mô tả một nhà xe đã triển khai. Mục tiêu là hai luồng: thông báo giao dịch cho khách đã đặt vé và bản tin theo tuyến cho khách quan tâm.

Luồng thứ nhất dùng API thông điệp giao dịch: khi hệ thống đặt vé xác nhận chỗ, nó gọi listmonk để gửi thư xác nhận theo mẫu, đúng kiểu ví dụ xác nhận đơn hàng mà tài liệu khái niệm đưa ra. [4] Người gọi API là một tài khoản loại API chỉ có quyền gửi giao dịch, theo mô hình quyền tx:send. [8] Luồng thứ hai là các danh sách theo tuyến, ví dụ khách thường đi một tuyến nhất định, được lọc từ thuộc tính do nhà xe tự nhập, kèm double opt-in để có bằng chứng xác nhận. [4]

Nếu muốn nhắn SMS cho thay đổi giờ xe, nhà xe phải dựng hoặc thuê một Messenger làm cầu nối tới cổng tin nhắn, vì listmonk chỉ đẩy JSON tới dịch vụ đó. [4] Mọi nội dung quảng cáo cần có đường hủy đăng ký rõ ràng và kiểm tra pháp lý trước khi gửi. Nhà xe cũng nên tách thư giao dịch khỏi thư quảng cáo ở cấp thiết kế để một đợt quảng cáo bị khiếu nại không kéo theo việc thư xác nhận vé vào mục rác.

Dựng lên và giữ cho chạy: Docker Compose, nâng cấp, tuyến mạng và nhật ký

Có hai đường cài đặt chính. Đường thứ nhất là tải tệp compose mẫu và chạy docker compose up, sau đó vào cổng 9000 để tạo tài khoản Super Admin. Đường thứ hai là tải tệp nhị phân, sinh cấu hình, chạy lệnh cài đặt cơ sở dữ liệu rồi chạy ứng dụng. [1][6] Tài liệu còn nói có thể đặt tên và mật khẩu Super Admin qua biến môi trường ở lần cài đầu. [6]

README mô tả cờ upgrade cho cơ sở dữ liệu hiện có, và nói rằng nâng cấp có tính lũy đẳng nên chạy nhiều lần không gây tác dụng phụ. [1] Tài liệu cài đặt cũng có chart Helm cho Kubernetes nhưng ghi rõ là do cộng đồng duy trì. [6] Trước khi nâng cấp hoặc dùng bản nightly, cần sao lưu Postgres, đúng như tài liệu khuyến cáo cho bản nightly. [6]

Về mạng, tài liệu cấu hình phân biệt các đường dẫn riêng tư như /api, /admin và webhook bounce với các đường dẫn công khai như /subscription, /link, /campaign, /public và /uploads. Khi đặt sau proxy hay tường lửa ứng dụng web, nên chỉ mở nhóm công khai ra internet. [5] Nhật ký ghi ra stdout; trang Settings hiển thị một nghìn dòng cuối và bị xóa khi khởi động lại, nên cần thu gom nhật ký ra tệp hoặc trình điều khiển nhật ký của Docker. [5] Cũng cần hỏi nhà cung cấp máy chủ vì một số nơi chặn cổng SMTP 25 và 465. [5]

Rủi ro đã được tác giả công bố và cách thu hẹp

Tệp SECURITY.md ngắn, chỉ yêu cầu đọc trang các báo cáo không được coi là lỗ hổng trước khi báo. [3] Trang đó là tài liệu đáng đọc nhất cho người vận hành, vì nó nói thẳng những rủi ro mà tác giả chấp nhận. Truy vấn người đăng ký chạy được biểu thức SQL tùy ý ở chế độ chỉ đọc, và vì không thể chặn mọi hàm Postgres nên tính năng này nằm sau quyền subscribers:sql_query. [7]

Tệp tải lên không bị biến đổi: có thể chứa HTML, JS hoặc SVG kèm script, và quản trị viên có thể giới hạn kiểu tệp trong Settings. HTML của chiến dịch cũng có thể chứa script và sẽ chạy khi chiến dịch được công khai ở dạng trang lưu trữ. Mẫu Go template cùng hàm Sprig đủ mạnh để viết vòng lặp gây quá tải. [7] Tất cả được tác giả xếp vào rủi ro chấp nhận, nên trách nhiệm phân quyền nằm ở quản trị viên.

Với nhà xe, hệ quả là chỉ cấp quyền cao cho người tin cậy. Tài liệu quyền ghi rõ sql_query vượt cả quyền theo từng danh sách, và gợi ý tạo vai trò Postgres hạn chế nếu cấp quyền này rộng. [8] Thêm vào đó, tài liệu khái niệm cảnh báo theo dõi mở thư và bấm liên kết có ảnh hưởng quyền riêng tư và nên dùng tuân thủ quy định như GDPR. [4]

AGPLv3: điều kiện khi sửa mã và phục vụ qua mạng

Tệp LICENSE tại commit ghim là văn bản GNU Affero General Public License, và README khẳng định listmonk theo AGPLv3. [1][2] Ngôn ngữ của giấy phép nêu mục đích thiết kế dành riêng cho phần mềm chạy trên máy chủ mạng, nơi người dùng tương tác từ xa; đây là điểm khác với GPL thông thường. [2] Nếu doanh nghiệp sửa mã rồi cho người khác tương tác qua mạng, cần xem lại nghĩa vụ cung cấp mã nguồn của bản sửa với luật sư.

Dùng nguyên bản để gửi thư cho khách của chính mình thường không kéo theo việc phải công bố gì khác, nhưng đây là diễn giải thận trọng chứ không phải tư vấn pháp lý, nên cần kiểm tra theo hoàn cảnh cụ thể. Khi tích hợp, nhúng mã vào sản phẩm khác hay phân phối lại là những trường hợp cần phân tích riêng.

Giấy phép chỉ bao phủ mã nguồn tại commit này. Nó không bao phủ dữ liệu người đăng ký của bạn, nhà cung cấp SMTP hay dịch vụ bounce, cổng SMS tự dựng, chart Helm do cộng đồng viết, dịch vụ hosting bên thứ ba hay các thư viện phụ thuộc có giấy phép riêng. [6] Trong nguồn đã đọc không thấy ghi chú về CLA hay điều khoản thương hiệu riêng, và cũng không thấy bản thương mại đóng.

Chi phí: nguồn lực con người, máy chủ và thư đi

README mô tả phần mềm gói trong một tệp nhị phân, nhưng nguồn không đưa ra số liệu tài nguyên cụ thể, nên bài không ước lượng cấu hình máy chủ. [1] Loại nguồn lực gồm một máy chủ hoặc máy ảo cho ứng dụng, một cơ sở dữ liệu Postgres có sao lưu, tên miền với chứng chỉ TLS, và kết nối tới nhà cung cấp SMTP hoặc dịch vụ gửi thư trung gian.

Chi phí thường bị bỏ sót là thời gian: một người cấu hình SPF, DKIM và theo dõi bounce, một người viết nội dung và mẫu, và thời gian tuân thủ. Hạng mục này không nằm trong nguồn đã đọc; đây là kinh nghiệm chung của vận hành thư hàng loạt. Nếu cần SMS, thêm chi phí dựng Messenger và phí cổng tin nhắn của nhà cung cấp.

Có các nền tảng bên thứ ba cung cấp triển khai một chạm, được liệt kê trong tài liệu cài đặt, nhưng giá và điều khoản của họ nằm ngoài nguồn nên bài không so sánh. [6] Khi lập ngân sách thử nghiệm, nên dự toán theo số giờ vận hành mỗi tháng, thay vì chỉ theo giá máy chủ.

Đặt cạnh các hướng khác: dịch vụ email marketing, tự dựng bằng SMTP, CRM tích hợp

Hướng thứ nhất là dịch vụ email marketing trả phí như Mailchimp hay các nền tảng tương tự. Ưu điểm là hạ tầng gửi và hỗ trợ có sẵn; đánh đổi là dữ liệu khách nằm ở nhà cung cấp và chi phí thường tăng theo quy mô. listmonk phù hợp hơn khi ưu tiên quyền sở hữu dữ liệu và có người vận hành. [1]

Hướng thứ hai là tự viết script gửi thư qua SMTP. Nhanh cho thử nghiệm nhỏ, nhưng phải tự xây phần xác nhận đăng ký, hủy đăng ký, xử lý bounce và phân quyền, tức đúng những phần listmonk đã gói sẵn. [4][8] Hướng thứ ba là dùng module email trong CRM hoặc phần mềm bán hàng. Nó tiện vì dữ liệu khách đã ở đó, nhưng khả năng phân đoạn, mẫu và quyền thường phụ thuộc từng sản phẩm.

Bài không so sánh tốc độ hay giá giữa các lựa chọn. Tiêu chí chọn nên là: ai sở hữu dữ liệu, ai chịu trách nhiệm về danh tiếng gửi, ai vận hành, và có cần SMS hay không. Với listmonk, SMS đòi hỏi tích hợp riêng. [4]

Những điều listmonk không làm thay bạn

Điểm yếu cốt lõi không nằm ở mã mà ở phạm vi. listmonk quản lý danh sách và gửi thư; không quản lý chuyến xe, vé hay thanh toán, và không đảm bảo thư vào hộp thư đến. [4][5] Cổng SMS hay kênh nhắn tin khác phải được tích hợp qua Messenger. [4]

Mô hình rủi ro mà tài liệu bảo mật công bố đòi hỏi quản trị viên cẩn trọng: ai có quyền sql_query, quyền tải tệp hay quyền soạn HTML đều có thể làm những việc mạnh hơn vẻ ngoài. [7][8] Nếu nhà xe có nhân sự quay vòng, cần kiểm soát cấp và thu hồi quyền.

Không nên dùng khi chưa có người chịu trách nhiệm sao lưu cơ sở dữ liệu, khi chưa có kế hoạch thu thập chấp thuận và xử lý yêu cầu xóa dữ liệu, hoặc khi cần cam kết dịch vụ có hợp đồng. Cũng không nên dùng bản nightly cho môi trường thật. [6] Dự án không công bố trong nguồn đã đọc một thỏa thuận mức dịch vụ.

Thử nghiệm sáu tuần trên một tuyến xe

Tuần một và hai: dựng listmonk bằng Docker Compose trên máy thử, kết nối một nhà cung cấp SMTP riêng cho thử nghiệm, tạo tài khoản theo vai trò và đặt biến môi trường cho cấu hình. [5][6] Tiêu chí qua cổng: gửi được thư thử tới ít nhất ba nhà cung cấp hộp thư mà đội đang dùng, và khôi phục được bản sao lưu Postgres sang máy khác.

Tuần ba và bốn: chọn một tuyến, nhập danh sách khách đã đồng ý, bật double opt-in và gửi hai chiến dịch nhỏ. Đồng thời nối hệ thống đặt vé với API giao dịch ở môi trường thử. Đo số đo do nhà xe tự ghi: tỷ lệ thư bị trả về, số lượt hủy đăng ký, số thư xác nhận gửi thành công so với số đặt vé thử, và thời gian từ lúc đặt tới lúc thư xuất hiện. Ngưỡng do nhà xe đặt từ trước, bài không đưa số mẫu.

Tuần năm và sáu: kiểm tra phân quyền, thử quy trình nâng cấp lũy đẳng theo README, và rà soát quyền riêng tư của theo dõi mở thư. [1][4][8] Tiêu chí dừng: nếu tỷ lệ bounce cao kéo dài, nếu không giải quyết được yêu cầu hủy đăng ký trong thời hạn nội bộ, hoặc nếu chi phí giờ công vượt mức chấp nhận, chuyển sang dịch vụ gửi thư trả phí.

Kết luận

listmonk là lựa chọn gọn cho doanh nghiệp muốn tự giữ danh sách khách và gửi thư hàng loạt: một tệp nhị phân Go, cơ sở dữ liệu Postgres, quyền hạn chi tiết và API giao dịch. [1][4][8] Với nhà xe, giá trị nằm ở việc tách rõ thông báo chuyến khỏi quảng cáo và giữ dữ liệu khách trong tầm kiểm soát.

Cái giá là trách nhiệm vận hành, tuân thủ pháp lý và giới hạn phạm vi: không phải hệ thống bán vé, SMS cần tích hợp và AGPLv3 đòi hỏi suy xét khi sửa mã. [2][4][7] Một cá nhân hay nhóm xây hệ thống tri thức như phamvanthu.com có thể hình dung bản tin tự lưu trữ gửi bài nghiên cứu mới cho người đã đăng ký; đây chỉ là ví dụ ứng dụng, không có nghĩa trang đó đang dùng listmonk.

Bước hợp lý tiếp theo là chạy thử sáu tuần trên một tuyến, đo bằng các chỉ số tự đặt, rồi quyết định.

Nguồn, commit và giới hạn của nghiên cứu

Dự án được chọn từ một kho lưu độc lập các danh sách GitHub Trending theo ngôn ngữ, có lần quan sát đầu tiên ngày 05/01/2026 ở danh sách Go. Kho lưu này chỉ bao phủ Python, Go, JavaScript và Swift, thiếu dữ liệu ngày 03/09 và 12/10, và không phải bảng xếp hạng Top 100 chính thức. [9]

Đối chiếu kỹ thuật dùng README, LICENSE, SECURITY.md và bốn tài liệu: khái niệm, cấu hình, cài đặt, báo cáo bảo mật và quyền hạn, tại commit 99b492d0869dd7e5c7c1a498927450e07f005667 của knadh/listmonk, ghi nhận ngày 12/10/2026. [1][2][3][4][5][6][7][8] Nội dung tài liệu được coi là dữ liệu tham chiếu. Tài liệu nằm ở nhánh chính nên có thể mô tả khả năng mới hơn bản phát hành bạn cài.

Đây là nghiên cứu tài liệu có hỗ trợ AI, chưa cài đặt, gửi thư hay đo hiệu năng listmonk, và không phải bài báo khoa học được phản biện. Các phần tình huống Việt Nam, chi phí và thử nghiệm là phân tích, đề xuất.

Xem mã nguồn listmonk trên GitHub

Khám phá nghiên cứu của BDSG Foundation

Trao đổi về ứng dụng công nghệ cho doanh nghiệp