SMTP relay
SMTP relay cho phép mọi ứng dụng biết gửi thư qua SMTP dùng Hạ Tầng: WordPress, Laravel, Django, Rails, Spring Boot, một server Postfix, thậm chí máy in. Thư đi qua đúng các bước kiểm tra như POST /emails, nên cũng hiện ở Email → Email với trạng thái, sự kiện và webhook.
Trước khi bắt đầu
- Một tên miền đã xác minh cho địa chỉ
From. Xem Tên miền. - API key có phạm vi
email:send. Key này chính là mật khẩu SMTP.
Thông tin kết nối
| Thiết lập | Giá trị |
|---|---|
| Host | smtp.hatang.dev |
| Cổng | 5870 |
| Mã hoá | STARTTLS (kết nối bắt đầu ở dạng thường rồi nâng cấp bằng lệnh STARTTLS) |
| Tên đăng nhập | hatang |
| Mật khẩu | API key của bạn, ht_... |
| Xác thực | PLAIN hoặc LOGIN |
Các giá trị này cũng có ở Cài đặt email → Thông tin kết nối trong dashboard.
Đừng bật "SSL", "implicit TLS" hay secure: true cho cổng 5870: client sẽ bắt tay TLS trước khi server chào và bị treo cho tới khi hết thời gian chờ. Hãy chọn STARTTLS, có ứng dụng gọi là "TLS". Server từ chối xác thực cho tới khi kết nối đã được nâng cấp bằng STARTTLS, nên API key không bao giờ đi qua mạng ở dạng rõ.
Hạ Tầng đọc thư thế nào
| Phần của thư | Hạ Tầng xử lý ra sao |
|---|---|
Header From | Người gửi. Tên miền phải đã xác minh và thuộc doanh nghiệp của API key. Không có header From thì dùng envelope sender (MAIL FROM). |
Header To và Cc | Người nhận to và cc. |
Người nhận trong envelope (RCPT TO) không có trong To hay Cc | Gửi dưới dạng bcc. |
Reply-To, Subject, phần HTML và văn bản, tệp đính kèm, ảnh nhúng | Giữ nguyên. |
Message-ID | Giữ nguyên, nên các chuỗi thư trong hệ thống của bạn vẫn khớp. |
Header bắt đầu bằng X- | Chuyển tiếp như header riêng, giống trường headers của API. Các header riêng khác bị bỏ. |
X-Tags | Được đọc thành tag và không chuyển tiếp. Giá trị là một mảng JSON: X-Tags: [{"name":"category","value":"welcome"}]. Giá trị không phải JSON hợp lệ bị bỏ qua. |
ToNếu thư chỉ có người nhận Bcc, Hạ Tầng chuyển người đầu tiên sang To, nơi mọi người nhận khác đều thấy. Hãy đặt ít nhất một địa chỉ trong header To.
Giới hạn
| Giới hạn | Giá trị |
|---|---|
| Người nhận mỗi thư | 50 người nhận trong envelope (RCPT TO) |
| Kích thước thư | Thư trên 40 MB bị từ chối. |
| Đăng nhập sai | Sau 10 lần đăng nhập sai từ một địa chỉ IP, mọi lần đăng nhập từ địa chỉ đó bị từ chối cho tới khi đủ 15 phút kể từ lần sai cuối cùng. |
| Hạn mức ngày | Dùng chung với API: mỗi thư tính là một email. |
Mã phản hồi SMTP
| Phản hồi | Mã mở rộng | Ý nghĩa | Cần làm gì |
|---|---|---|---|
250 | 2.0.0 | Đã nhận. Phần chữ kết thúc bằng queued as <id email>. | Không cần làm gì. |
530 | 5.7.0 | Cần đăng nhập. | Đăng nhập trước lệnh MAIL FROM. |
535 | 5.7.8 | API key sai hoặc đã bị thu hồi. | Kiểm tra mật khẩu. |
421 | 4.7.0 | Quá nhiều lần đăng nhập sai từ địa chỉ IP của bạn. | Sửa mật khẩu và chờ rồi mới thử lại. |
452 | 5.5.3 | Quá 50 người nhận. | Tách thư ra. |
550 | 5.7.1 | Tên miền của From chưa xác minh hoặc không thuộc doanh nghiệp, API key bị giới hạn vào tên miền khác, hoặc doanh nghiệp đang tạm dừng gửi. Phần chữ nói rõ lý do. | Xác minh tên miền hoặc sửa địa chỉ From. |
553 | 5.6.0 | Thư bị từ chối vì không hợp lệ, ví dụ header From sai. | Sửa thư. Gửi lại y nguyên sẽ lại lỗi. |
451 | 4.3.0 | Lỗi tạm thời, kể cả khi đã hết hạn mức ngày. | Thử lại sau. Các mail server như Postfix tự thử lại. |
Kiểm tra kết nối
Kiểm tra STARTTLS hoạt động:
openssl s_client -starttls smtp -connect smtp.hatang.dev:5870 -crlf -quiet
Gửi thư thử bằng swaks:
swaks --server smtp.hatang.dev:5870 --tls \
--auth PLAIN --auth-user hatang --auth-password "$HATANG_API_KEY" \
--header "Subject: Thử SMTP" --body "Chạy rồi."
Hoặc bằng thư viện chuẩn của Python:
import os
import smtplib
from email.message import EmailMessage
msg = EmailMessage()
msg["Subject"] = "Thử SMTP"
msg["X-Tags"] = '[{"name":"category","value":"test"}]'
msg.set_content("Chạy rồi.")
with smtplib.SMTP("smtp.hatang.dev", 5870) as smtp:
smtp.starttls()
smtp.login("hatang", os.environ["HATANG_API_KEY"])
smtp.send_message(msg)
Cấu hình mẫu
Nodemailer
import nodemailer from "nodemailer";
const transporter = nodemailer.createTransport({
host: "smtp.hatang.dev",
port: 5870,
secure: false, // bắt buộc là false: cổng 5870 dùng STARTTLS
requireTLS: true, // không gửi nếu không nâng cấp được STARTTLS
auth: { user: "hatang", pass: process.env.HATANG_API_KEY },
});
const info = await transporter.sendMail({
subject: "Chào mừng bạn đến với Shop",
html: "<p>Chào mừng!</p>",
text: "Chào mừng!",
headers: { "X-Tags": JSON.stringify([{ name: "category", value: "welcome" }]) },
});
console.log(info.response); // 250 2.0.0 Ok: queued as <id email>
secure: true nghĩa là TLS ngầm định và không chạy trên cổng 5870.
Laravel
Trong .env:
MAIL_MAILER=smtp
MAIL_HOST=smtp.hatang.dev
MAIL_PORT=5870
MAIL_USERNAME=hatang
MAIL_PASSWORD=ht_123...
MAIL_FROM_NAME="Shop"
Mailer của Laravel tự nâng cấp kết nối bằng STARTTLS khi server hỗ trợ, và smtp.hatang.dev luôn hỗ trợ. Để trống MAIL_SCHEME hoặc đặt là smtp; đừng dùng smtps. Với Laravel 10 trở về trước, đặt MAIL_ENCRYPTION=tls.
Django
Trong settings.py:
import os
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
EMAIL_HOST = "smtp.hatang.dev"
EMAIL_PORT = 5870
EMAIL_HOST_USER = "hatang"
EMAIL_HOST_PASSWORD = os.environ["HATANG_API_KEY"]
EMAIL_USE_TLS = True # STARTTLS
EMAIL_USE_SSL = False # TLS ngầm định: phải tắt
Ruby on Rails
Trong config/environments/production.rb:
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address: "smtp.hatang.dev",
port: 5870,
user_name: "hatang",
password: ENV.fetch("HATANG_API_KEY"),
authentication: :plain,
enable_starttls_auto: true
}
Spring Boot
Trong application.properties:
spring.mail.host=smtp.hatang.dev
spring.mail.port=5870
spring.mail.username=hatang
spring.mail.password=${HATANG_API_KEY}
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
WordPress (WP Mail SMTP)
Cài plugin WP Mail SMTP, mở WP Mail SMTP → Settings và chọn mailer Other SMTP:
| Thiết lập | Giá trị |
|---|---|
| From Email | Một địa chỉ trên tên miền đã xác minh, ví dụ [email protected]. Bật Force From Email. |
| SMTP Host | smtp.hatang.dev |
| Encryption | TLS (trong WP Mail SMTP, đây là STARTTLS) |
| SMTP Port | 5870 |
| Auto TLS | Bật |
| Authentication | Bật |
| SMTP Username | hatang |
| SMTP Password | API key của bạn |
Để không lưu key trong database, khai báo trong wp-config.php:
define( 'WPMS_ON', true );
define( 'WPMS_MAILER', 'smtp' );
define( 'WPMS_SMTP_HOST', 'smtp.hatang.dev' );
define( 'WPMS_SMTP_PORT', 5870 );
define( 'WPMS_SSL', 'tls' );
define( 'WPMS_SMTP_AUTH', true );
define( 'WPMS_SMTP_USER', 'hatang' );
define( 'WPMS_SMTP_PASS', 'ht_123...' );
define( 'WPMS_MAIL_FROM_FORCE', true );
Sau đó gửi thử ở WP Mail SMTP → Tools → Email Test.
PHPMailer
<?php
use PHPMailer\PHPMailer\PHPMailer;
$mail = new PHPMailer(true);
$mail->isSMTP();
$mail->Host = 'smtp.hatang.dev';
$mail->Port = 5870;
$mail->SMTPAuth = true;
$mail->Username = 'hatang';
$mail->Password = getenv('HATANG_API_KEY');
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->CharSet = 'UTF-8';
$mail->Subject = 'Chào mừng bạn đến với Shop';
$mail->isHTML(true);
$mail->Body = '<p>Chào mừng!</p>';
$mail->AltBody = 'Chào mừng!';
$mail->addCustomHeader('X-Tags', '[{"name":"category","value":"welcome"}]');
$mail->send();
Postfix relayhost
Để mọi thư từ một server đi qua Hạ Tầng, đặt Hạ Tầng làm relay host trong /etc/postfix/main.cf:
relayhost = [smtp.hatang.dev]:5870
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_tls_security_level = encrypt
Ghi thông tin đăng nhập vào /etc/postfix/sasl_passwd:
[smtp.hatang.dev]:5870 hatang:ht_123...
Sau đó khoá quyền tệp và nạp lại:
sudo chmod 600 /etc/postfix/sasl_passwd
sudo postmap /etc/postfix/sasl_passwd
sudo systemctl reload postfix
Chỉ thư có địa chỉ From trên tên miền đã xác minh mới được nhận. Hãy đổi người gửi của thư hệ thống (ví dụ bằng smtp_generic_maps) để root@localhost thành một địa chỉ trên tên miền của bạn.
Bước tiếp theo
- Gửi email: REST API, có gửi theo lô, hẹn giờ và idempotency.
- Theo dõi mở và nhấp: theo dõi cũng áp dụng cho thư gửi qua SMTP.
- Danh sách chặn và thư trả lại