31 điểm bởi hongminhee 2025-07-14 | 6 bình luận | Chia sẻ qua WhatsApp

Xin chào. Mình xin chia sẻ một thư viện gửi email do cá nhân tự tạo ra.

Vì sao mình làm ra nó?

Gần đây khi thực hiện nhiều dự án, mình đã phải sử dụng nhiều runtime khác nhau như Node.js, Deno, Bun, v.v., và ở phần gửi email thì lần nào cũng bất tiện vì phải tìm thư viện khác nhau hoặc cấu hình lại từ đầu. Đặc biệt, trên Deno hay Bun, nhiều thư viện email dành cho Node.js thường không hoạt động đúng cách.

Vì vậy, mình đã tạo ra Upyo với suy nghĩ rằng sẽ thật tốt nếu có một thư viện email “viết một lần, chạy ở mọi nơi”.

Các đặc điểm chính

Khả năng tương thích đa runtime

Hoạt động với cùng một đoạn mã trên Node.js, Deno, Bun và cả edge functions. Không cần cấu hình khác nhau hay sửa mã theo từng runtime.

Zero dependency

Cá nhân mình không thích việc kéo theo quá nhiều dependency, nên thư viện được xây dựng theo hướng zero dependency. Ví dụ, ngay cả SMTP transport cũng không dùng gói smtp mà được tự phát triển trực tiếp.

API đơn giản

Được thiết kế để có thể gửi email chỉ với vài dòng mà không cần cấu hình phức tạp:

import { createMessage } from "@upyo/core";  
import { MailgunTransport } from "@upyo/mailgun";  
  
const message = createMessage({  
  from: "sender@example.com",  
  to: "recipient@example.com",  
  subject: "Hello from Upyo!",  
  content: { text: "Đây là một email đơn giản." },  
});  
  
const transport = new MailgunTransport({  
  apiKey: process.env.MAILGUN_KEY,  
  domain: process.env.MAILGUN_DOMAIN,  
});  
  
const receipt = await transport.send(message);  

Tính độc lập với nhà cung cấp

Hỗ trợ nhiều dịch vụ email như SMTP, Mailgun, SendGrid, v.v., và ngay cả khi đổi nhà cung cấp thì mã ứng dụng vẫn được giữ nguyên. Chỉ cần thay Transport. (Phiên bản tiếp theo cũng sẽ hỗ trợ Amazon SES.)

Thân thiện cho kiểm thử

Cung cấp MockTransport để có thể kiểm thử logic email mà không cần gửi email thật. Bạn có thể test mà không phải lo trong lúc phát triển lỡ gửi email thật đi.

Những điểm còn thiếu

  • STARTTLS trên SMTP transport vẫn chưa được triển khai
  • Trên edge functions, SMTP hiện vẫn chưa được hỗ trợ (chỉ dùng được transport dựa trên HTTP API)
  • Vẫn đang ở giai đoạn phát triển ban đầu nên API có thể sẽ thay đổi

Dùng thử

Có thể sử dụng trên nhiều runtime khác nhau:

npm  add       @upyo/core @upyo/smtp  
pnpm add       @upyo/core @upyo/smtp  
yarn add       @upyo/core @upyo/smtp  
deno add --jsr @upyo/core @upyo/smtp  
bun  add       @upyo/core @upyo/smtp  

Ngoài @upyo/smtp, các gói transport còn có @upyo/mailgun, @upyo/sendgrid, @upyo/ses, @upyo/mock, và trong tương lai sẽ tiếp tục được bổ sung thêm.

Tài liệu: https://upyo.org
Mã nguồn: https://github.com/dahlia/upyo

Kết

Dù là dự án bắt đầu từ nhu cầu cá nhân, mình nghĩ nó có thể hữu ích nên xin chia sẻ cho những ai cũng đang có cùng trăn trở. Hiện vẫn mới ở phiên bản 0.1.0, nhưng mình dự định sẽ tiếp tục cải thiện đều đặn.

Mọi phản hồi hoặc đóng góp đều luôn được chào đón!


Upyo là cái tên lấy từ từ “tem bưu chính” trong tiếng Hàn. Nó mang ý nghĩa gửi email như gửi thư bằng tem.

6 bình luận

 
davidshim 2025-08-13

Đây là một dự án rất dễ đồng cảm vì tôi cũng từng có trải nghiệm phải thay đổi API 2~3 lần. Có vẻ như cả website lẫn tài liệu đều được làm rất gọn gàng và chỉn chu. Khi vận hành dịch vụ, đôi lúc một dịch vụ mail cụ thể bị gián đoạn nên phải thiết lập failover sang dịch vụ mail khác; sẽ rất tuyệt nếu có thêm mã vận hành transport theo khái niệm pool. Cũng mong sẽ hỗ trợ cả resend.com. Nếu đến lúc tôi áp dụng mà vẫn chưa có, tôi cũng sẽ thử tự đóng góp~!

 
hongminhee 2025-08-13

Cảm ơn bạn đã phản hồi! Mình sẽ sớm bổ sung PoolTransportResendTransport!

 
nemorize 2025-07-15

Hay là đổi “郵票” trong biểu tượng thành “tem” thì sao?
Dù vậy, ngay cả bây giờ nó cũng đã rất hợp và đẹp rồi nên mình cũng hơi ngại khi nói điều này..

 
zinisuni 2025-07-15

Ồ~ hay đấy~ tốt tốt

 
cgl00 2025-07-15

Đây là dự án của một người à?? Thật đáng nể..

 
hongminhee 2025-07-15

Vâng, hiện tại tôi vẫn đang tự mình làm nó. 😅