API gửi thư

Cho phép hệ thống khác gửi thư dưới danh nghĩa tên miền của Minh Trung — đơn hàng, thông báo, xác nhận, báo cáo tự động.

Nội dung
  1. Bắt đầu nhanh
  2. Xác thực
  3. Gửi thư
  4. Tệp đính kèm
  5. Bảng mã lỗi
  6. Giới hạn
  7. Ví dụ theo ngôn ngữ

1. Bắt đầu nhanh

Xin khoá API từ quản trị viên (mục Cài đặt → Khoá API trong hộp thư). Thử kết nối trước khi gửi thật:

curl https://mail.tamiload.com/api/v1/ping \
  -H "Authorization: Bearer KHOA_CUA_BAN"
{
  "ok": true,
  "ten_khoa": "Hệ thống đặt hàng Derma",
  "mien_duoc_gui": ["dermatreatment.com.vn"],
  "tran_ngay": 200,
  "da_dung_hom_nay": 0,
  "con_lai_hom_nay": 200
}

2. Xác thực

Mỗi yêu cầu phải mang khoá API, theo một trong hai cách:

Authorization: Bearer mtm_live_xxxxxxxxxxxx
X-API-Key: mtm_live_xxxxxxxxxxxx
Khoá chỉ hiện đúng một lần lúc tạo. Máy chủ chỉ giữ bản băm, không giữ khoá gốc — mất là phải tạo khoá mới, không lấy lại được. Đừng nhúng khoá vào mã chạy ở trình duyệt; khoá chỉ dùng ở phía máy chủ.

Mỗi khoá bị giới hạn tên miền được phép đặt vào ô người gửi. Khoá cấp cho hệ thống Derma chỉ gửi được từ @dermatreatment.com.vn, không mượn được tên miền khác.

3. Gửi thư

POST https://mail.tamiload.com/api/v1/send

Các trường

TrườngKiểuBắt buộcÝ nghĩa
fromchuỗi Địa chỉ người gửi. Tên miền phải nằm trong phạm vi của khoá.
fromNamechuỗiKhông Tên hiển thị của người gửi.
tochuỗi hoặc mảng Người nhận. Nhiều địa chỉ thì cách nhau bằng dấu phẩy, hoặc truyền mảng.
cc, bccchuỗi hoặc mảngKhông bcc không xuất hiện trong thư người nhận thấy.
replyTochuỗiKhông Địa chỉ nhận thư trả lời, nếu khác người gửi.
subjectchuỗiTiêu đề. Có dấu tiếng Việt được.
htmlchuỗiCó ít nhất mộtNội dung dạng HTML.
textchuỗitrong hai Nội dung chữ trơn. Bỏ trống thì máy chủ tự sinh từ html.
attachmentsmảngKhôngXem mục 4.
inReplyTo,
references
chuỗiKhông Mã thư gốc, để thư này nối đúng mạch hội thoại bên máy người nhận.

Trả về khi thành công

{
  "ok": true,
  "messageId": "<abc123@dermatreatment.com.vn>",
  "id": "mub08fs1-u2glvqf7",
  "con_lai_hom_nay": 199
}

messageId là mã thư theo chuẩn thư điện tử — lưu lại để sau này nối hội thoại hoặc đối soát. id là mã trong hộp thư Minh Trung, dùng để tra lại ở mục Đã gửi.

Trả về khi hỏng

{
  "ok": false,
  "ma": "MIEN_CHUA_BAT",
  "error": "Tên miền \"abc.com\" chưa bật gửi thư. Tên miền dùng được: ..."
}

Luôn có ma để máy đọc và rẽ nhánh, và error là câu tiếng Việt để ghi nhật ký hoặc hiện cho người vận hành. Đừng bắt lỗi theo câu chữ — câu chữ có thể sửa, còn ma thì giữ nguyên.

4. Tệp đính kèm

"attachments": [
  {
    "filename": "don-hang-12345.pdf",
    "type": "application/pdf",
    "content": "<nội dung tệp mã hoá base64>"
  }
]
Số tệp tối đa10 tệp mỗi thư
Tổng dung lượng4 MB (tính theo byte gốc, trước khi mã hoá base64)
Đuôi bị chặnexe bat cmd com cpl scr msi jar vbs js ps1 sh dll lnk reg hta

5. Bảng mã lỗi

HTTPNghĩa & cách xử lý
400JSON_HONGThân yêu cầu không phải JSON hợp lệ.
400THIEU_NGUOI_NHANto rỗng hoặc không có địa chỉ hợp lệ.
400THIEU_NGUOI_GUIfrom không phải địa chỉ email.
400THIEU_TIEU_DEThiếu subject.
400THIEU_NOI_DUNGThiếu cả html lẫn text.
400QUA_NHIEU_NGUOI_NHANTổng to + cc + bcc vượt 60.
400TEP_BI_CHANTệp có đuôi nguy hiểm.
400TEP_HONGcontent không phải base64 hợp lệ.
401THIEU_KHOAKhông gửi kèm khoá.
401KHOA_SAIKhoá không tồn tại. Kiểm tra lại, đừng thử lại vòng lặp.
403KHOA_TATKhoá bị quản trị tắt. Liên hệ quản trị.
403KHOA_KHONG_DUOC_MIENKhoá không được gửi từ tên miền đó.
403MIEN_CHUA_BATTên miền chưa bật gửi thư trên hệ thống.
413TEP_QUA_NANGTệp đính kèm vượt 4 MB.
429QUA_TRAN_NGAYHết lượt của khoá trong hôm nay. Chờ sang ngày mới.
429QUA_TRAN_NHA_MANGChạm trần của Cloudflare. Thử lại sau vài phút.
502GUI_THAT_BAIKhông gửi được. Thử lại có thể thành công.
500LOI_MAY_CHULỗi phía hệ thống. Thử lại có thể thành công.
Cách thử lại cho đúng: chỉ thử lại với 429 · 502 · 500, và phải giãn dần (1 giây, 2 giây, 4 giây…). Các lỗi 4xx còn lại là sai dữ liệu — thử lại bao nhiêu lần cũng hỏng, chỉ tốn lượt gửi.

6. Giới hạn

Trần gửi mỗi khoáDo quản trị đặt khi tạo khoá (mặc định 500 thư/ngày). Đếm lại từ 0 lúc nửa đêm giờ Việt Nam.
Người nhận mỗi thưtối đa 50 ở to, tổng cả cc + bcc là 60
Kích thước thưCloudflare chặn thư ra lớn hơn 5 MiB
Xác thực thư điMọi thư đều được ký DKIM theo tên miền gửi, và có DMARC — nên vào hộp thư chính, không rơi vào thư rác

Mọi thư gửi qua API đều được lưu vào mục Đã gửi của hộp thư Minh Trung, ghi rõ khoá nào đã gửi, để đối soát khi cần.

7. Ví dụ theo ngôn ngữ

cURL

curl -X POST https://mail.tamiload.com/api/v1/send \
  -H "Authorization: Bearer $MT_MAIL_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "donhang@dermatreatment.com.vn",
    "fromName": "Derma - Đơn hàng",
    "to": "khach@vidu.com",
    "subject": "Đơn hàng #12345 đã được xác nhận",
    "html": "<p>Cảm ơn anh/chị đã đặt hàng.</p>"
  }'

JavaScript / Node.js

const res = await fetch('https://mail.tamiload.com/api/v1/send', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.MT_MAIL_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    from: 'donhang@dermatreatment.com.vn',
    fromName: 'Derma - Đơn hàng',
    to: 'khach@vidu.com',
    subject: 'Đơn hàng #12345 đã được xác nhận',
    html: '<p>Cảm ơn anh/chị đã đặt hàng.</p>',
  }),
});
const kq = await res.json();
if (!kq.ok) throw new Error(`${kq.ma}: ${kq.error}`);
console.log('Đã gửi:', kq.messageId);

PHP

$than = json_encode([
  'from'    => 'donhang@dermatreatment.com.vn',
  'to'      => 'khach@vidu.com',
  'subject' => 'Đơn hàng #12345 đã được xác nhận',
  'html'    => '<p>Cảm ơn anh/chị đã đặt hàng.</p>',
], JSON_UNESCAPED_UNICODE);

$ch = curl_init('https://mail.tamiload.com/api/v1/send');
curl_setopt_array($ch, [
  CURLOPT_POST           => true,
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER     => [
    'Authorization: Bearer ' . getenv('MT_MAIL_KEY'),
    'Content-Type: application/json',
  ],
  CURLOPT_POSTFIELDS     => $than,
]);
$kq = json_decode(curl_exec($ch), true);
if (empty($kq['ok'])) throw new Exception($kq['ma'] . ': ' . $kq['error']);

Python

import os, requests

r = requests.post(
    'https://mail.tamiload.com/api/v1/send',
    headers={'Authorization': f"Bearer {os.environ['MT_MAIL_KEY']}"},
    json={
        'from': 'donhang@dermatreatment.com.vn',
        'to': 'khach@vidu.com',
        'subject': 'Đơn hàng #12345 đã được xác nhận',
        'html': '<p>Cảm ơn anh/chị đã đặt hàng.</p>',
    },
    timeout=30,
)
kq = r.json()
if not kq.get('ok'):
    raise RuntimeError(f"{kq['ma']}: {kq['error']}")

Gửi kèm tệp

const fs = require('node:fs');
const tep = fs.readFileSync('don-hang-12345.pdf').toString('base64');

// … trong phần body:
attachments: [
  { filename: 'don-hang-12345.pdf', type: 'application/pdf', content: tep }
]

Hộp thư Minh Trung · quay lại hộp thư