Ba lượt gọi, và không có gì cần thiết lập
Toàn bộ giao diện chỉ gồm ba endpoint dưới https://grabmail.io/api/v1, cộng thêm một địa chỉ cho tệp đính kèm mà các lượt gọi kia đã dựng sẵn cho bạn. Không có lượt gọi nào tạo một hộp thư, và sự vắng mặt đó không phải là một thiếu sót: một địa chỉ bắt đầu tồn tại khi thư đến đó, nên không có việc gì để một lượt gọi như vậy phải làm.
| Lượt gọi | Trả lời điều gì | Bạn truyền vào gì |
|---|---|---|
GET /mailbox | Mọi thứ đang chờ ở một địa chỉ, mới nhất trước. | address, và tùy chọn thêm limit và before |
GET /message/{id} | Một thư đầy đủ: phần văn bản thuần, phần HTML, và mọi tệp đính kèm kèm sẵn một URL đã dựng sẵn. | mailbox |
DELETE /message/{id} | Xóa ngay bây giờ thay vì chờ khoảng thời gian lưu trữ trôi qua. | mailbox |
GET /attachment/{id} | Các byte của một tệp, đúng như khi chúng đến. | mailbox |
Mọi phản hồi đều là JSON, kể cả mọi lỗi. Mọi mốc thời gian đều là UTC theo định dạng RFC 3339. Id của thư không mang cấu trúc gì để bạn dựa vào: chỉ cần truyền lại nguyên vẹn, không bao giờ tự tách chúng ra.
Lượt gọi đầu tiên, và một địa chỉ trống trả lời điều gì
Chọn một cái tên, ghép nó với một trong các tên miền công khai, rồi đọc nó. Không có gì cần tồn tại trước, và không có gì được tạo ra chỉ vì bạn hỏi.
$ curl -sG https://grabmail.io/api/v1/mailbox \
--data-urlencode "address=k7fq2m@grabmail.io"{
"address": "k7fq2m@grabmail.io",
"alias": "q4v8n2mt7xkd@example.net",
"count": 1,
"next": null,
"messages": [
{
"id": "3QK7ZB5M9WVXR2HD4TNFJ0PC6A",
"from": "no-reply@example.com",
"from_name": "Example",
"subject": "Your verification code",
"preview": "Your code is 481920. It expires in 10 minutes.",
"has_html": false,
"date": "2026-08-29T09:14:02Z",
"seen": false,
"attachments": 0,
"expires_at": "2026-09-03T09:14:02Z"
}
]
}Năm trường, và hai trong số đó thú vị hơn vẻ ngoài của chúng:
count- Có bao nhiêu thư trong câu trả lời này — chứ không phải hộp thư đang giữ bao nhiêu thư. Ngay khi bạn truyền
limit, đó là hai con số khác nhau. next- Con trỏ cho trang tiếp theo sau trang này, hoặc
nullkhi không còn gì sau nó. Đó chính là id của thư cuối cùng bạn vừa nhận được, nên việc phân trang không tốn thêm một lượt gọi nào để tìm ra nó. messages- Chính là danh sách đó, mới nhất trước. Mỗi mục đã mang sẵn
subject,from,date,seen, một đoạnpreviewngắn của phần văn bản, có hay không một phần HTML, và có bao nhiêu tệp đính kèm. alias- Một địa chỉ thứ hai cũng chuyển thư về đây nhưng không tiết lộ gì về địa chỉ này. Đưa nó cho một biểu mẫu thay vì địa chỉ thật; bất kỳ ai có được nó và gõ vào dịch vụ này cũng chỉ thấy một hộp thư trống.
address- Địa chỉ như hệ thống đã hiểu, đã chuyển về chữ thường và cắt khoảng trắng thừa. Hãy đối chiếu nó với những gì bạn đã gửi nếu bạn đang ghép địa chỉ từ nhiều phần.
Đọc qua trang sau năm mươi thư đầu tiên
Theo mặc định, một lượt gọi trả về tối đa năm mươi thư, và tối đa hai trăm nếu bạn tự nới rộng. Một hộp thư catch-all bận rộn vượt qua cả hai mốc đó chỉ trong một buổi chiều, và phần mà người đọc hay đoán sai là bước tiếp theo — vì đó không phải một số thứ tự trang.
limit- Trả về bao nhiêu trong lượt gọi này, từ 1 đến 200. Giá trị nằm ngoài khoảng đó bị ép về giới hạn chứ không bị từ chối, nên
limit=5000âm thầm cho bạn 200. before- Id của thư cũ nhất bạn đang có sẵn. Bạn sẽ nhận về những thư đến sau nó. Hãy truyền lại đúng giá trị mà câu trả lời trước đã đặt vào
next. nextnullnghĩa là bạn đã đọc đến hết hộp thư. Đó là tín hiệu kết thúc danh sách đáng tin cậy duy nhất: một trang ngắn không phải là tín hiệu đó, vì một trang chỉ ngắn khi máy chủ quyết định như vậy.
limit giới hạn một câu trả lời, next nêu tên vị trí câu trả lời đó dừng lại, và before yêu cầu những gì nằm sau vị trí đó.ADDR="k7fq2m@grabmail.io"
CURSOR=""
while :; do
PAGE=$(curl -fsG https://grabmail.io/api/v1/mailbox \
--data-urlencode "address=$ADDR" \
--data-urlencode "limit=200" \
${CURSOR:+--data-urlencode "before=$CURSOR"})
printf '%s' "$PAGE" | jq -c '.messages[]'
CURSOR=$(printf '%s' "$PAGE" | jq -r '.next // empty')
[ -n "$CURSOR" ] || break
sleep 1
doneLặp trong khi next khác null, và bạn sẽ có toàn bộ hộp thư, dù nó đã phình to đến đâu. Mỗi lượt gọi là một lượt đọc theo khoảng trên một chỉ mục chứ không phải theo độ lệch (offset), nên trang thứ một nghìn tốn chi phí y hệt trang đầu tiên.
Một con trỏ từ một hộp thư khác, hoặc một con trỏ đã hết hạn, không phải là một lỗi: bạn nhận về một trang rỗng và next: null. Đó là câu trả lời đúng — vì lặp lại trang mới nhất thay vào đó sẽ đưa cho script những thư nó đã xử lý rồi — nhưng điều đó cũng có nghĩa một con trỏ đã cũ trông giống hệt như đã đến cuối danh sách.
Mở một thư, và khi nào bạn không cần làm vậy
Id lấy từ danh sách cộng với hộp thư mà nó được chuyển đến sẽ cho bạn chính thư đó. Cả hai đều bắt buộc: một id bị rò rỉ ra khỏi một hộp thư không thể dùng để đọc một hộp thư khác, vì mọi lượt tra cứu đều bị giới hạn theo cả địa chỉ nữa.
$ curl -sG https://grabmail.io/api/v1/message/3QK7ZB5M9WVXR2HD4TNFJ0PC6A \
--data-urlencode "mailbox=k7fq2m@grabmail.io"{
"id": "3QK7ZB5M9WVXR2HD4TNFJ0PC6A",
"from": "no-reply@example.com",
"to": "k7fq2m@grabmail.io",
"subject": "Your verification code",
"date": "2026-08-29T09:14:02Z",
"expires_at": "2026-09-03T09:14:02Z",
"text": "Your code is 481920. It expires in 10 minutes.",
"html": null,
"attachments": []
}text- Phần văn bản thuần. Hãy phân tích phần này khi nó có sẵn: nó ổn định, không mang theo markup nào, và một mã sáu chữ số trong đó đúng là một mã sáu chữ số.
html- Phần HTML, hoặc
nullkhi người gửi không gửi kèm. Liên kết xác nhận thường chỉ tồn tại ở đây. attachments- Mỗi tệp một mục, mỗi mục đã có sẵn URL để tải nó. Một danh sách rỗng, chứ không phải
null, khi không có tệp nào. expires_at- Thời điểm thư này bị xóa, theo cùng định dạng RFC 3339 như
date. Hãy đọc giá trị này thay vì tự tính toán — khoảng thời gian lưu trữ không phải một cấu hình bạn có thể chắc chắn từ bên ngoài.
Rất thường xuyên, bạn có thể bỏ qua hoàn toàn lượt gọi này. Danh sách đã trả về sẵn tiêu đề, người gửi, thời điểm và một đoạn xem trước ngắn của phần văn bản, đủ để quyết định một thư không phải là thư bạn đang chờ. Tải về từng thư trong một hộp thư chỉ để phát hiện ra bạn không cần thư nào trong số đó là cách phổ biến nhất khiến một script trở nên chậm chạp.
Lấy một tệp ra ngoài
Mỗi tệp đính kèm mang theo url riêng của nó, và chi tiết đáng biết trước khi bạn viết vòng lặp là đây là một đường dẫn trên chính origin này chứ không phải một địa chỉ tuyệt đối — đã có sẵn tham số mailbox bên trong. Ghép thêm origin ở phía trước, tải nó, và không còn gì khác cần truyền, không có gì cần cấp quyền.
ADDR="k7fq2m@grabmail.io"
ID="3QK7ZB5M9WVXR2HD4TNFJ0PC6A"
curl -fsG https://grabmail.io/api/v1/message/$ID \
--data-urlencode "mailbox=$ADDR" \
| jq -r '.attachments[] | "\(.url)\t\(.filename)"' \
| while IFS=$'\t' read -r path name; do
curl -fs "https://grabmail.io$path" -o "$name"
doneNó luôn trả lời bằng application/octet-stream kèm Content-Disposition: attachment, bất kể người gửi đã gắn nhãn tệp đó là gì. Đây là chủ ý — nếu lặp lại nguyên văn text/html của một người lạ, tệp đính kèm đó có thể chạy như một trang trên chính origin này — nên một script quan tâm đến loại tệp cần đọc nó từ JSON của thư, nơi nó chỉ là dữ liệu chứ không phải một chỉ thị.
Toàn bộ thư, kể cả tệp đính kèm, bị giới hạn ở 5 MB. Giới hạn đó thực sự có ý nghĩa gì một khi base64 đã xử lý xong một tệp nhị phân là một chủ đề riêng, và có một hướng dẫn về tệp đính kèm nói về điều đó.
Hai giới hạn tốc độ, không phải một
Đây là phần đáng biết và cũng dễ bỏ sót: liệt kê một địa chỉ và đọc từ địa chỉ đó được đo lường riêng biệt, vì chúng không mang cùng một rủi ro. Bất kỳ ai biết một địa chỉ đều thăm dò được danh sách của nó; đọc một thư lại cần một id, và không có gì để đoán ở đó cả.
| Bạn đang gọi gì | Giới hạn | Ý nghĩa trong thực tế |
|---|---|---|
GET /mailbox | Một yêu cầu mỗi giây, cho mỗi địa chỉ | Đúng bằng nhịp độ thăm dò được thiết kế sẵn, và không bao giờ bị hãm tốc độ ở nhịp đó. Nhanh hơn sẽ bị từ chối, và cũng chẳng ích gì hơn. |
GET /message/{id}, GET /attachment/{id}, DELETE | Rộng rãi hơn nhiều, cho mỗi địa chỉ | Xử lý dồn dập trọn một trang thư mà không cần tạm dừng giữa các lượt. Đây là lý do một giao diện có thể mở một thư ngay trong cùng giây mà một lượt thăm dò vừa chạy. |
| Tất cả cộng lại | 1200 yêu cầu mỗi phút, cho mỗi client | Hai mươi địa chỉ được thăm dò mỗi giây một lần — vượt xa mọi nhu cầu tự động hóa thực tế, và là một điểm chặn với một host đang lần lượt duyệt qua mười nghìn địa chỉ. |
Vượt quá bất kỳ giới hạn nào trong số đó, bạn sẽ nhận 429 kèm thời gian chờ, tính bằng giây, trong tiêu đề Retry-After. Hãy tuân theo con số đó thay vì tự nghĩ ra một khoảng lùi lại của riêng bạn: đó chính là máy chủ đang nói cho bạn biết chính xác khi nào nó sẽ đồng ý.
read_box() {
local wait
while :; do
BODY=$(curl -s -D /tmp/gm.h -G https://grabmail.io/api/v1/mailbox \
--data-urlencode "address=$1")
grep -qi '^HTTP/[0-9.]* 429' /tmp/gm.h || { printf '%s' "$BODY"; return 0; }
wait=$(awk 'tolower($1) == "retry-after:" { print $2 + 0 }' /tmp/gm.h)
sleep "${wait:-1}"
done
}Cách chờ một thư chưa đến — dùng một mốc thời gian thay vì đếm số lần thử lại, và việc cần làm khi mốc đó trôi qua — là chủ đề của hướng dẫn kiểm thử các luồng xác minh. Vòng lặp ở đó cũng chính là vòng lặp mà một tác vụ theo lịch cần đến.
Xóa thư, và giới hạn cứng bên dưới tất cả những điều đó
Một thư bạn đã xử lý xong có thể bị xóa ngay lập tức thay vì chờ hết khoảng thời gian lưu trữ. Lượt gọi này có tính idempotent: xóa cùng một id hai lần vẫn trả lời 200 cả hai lần, nên một yêu cầu bị gửi lại không bao giờ trông giống như một thất bại.
$ curl -s -X DELETE -G https://grabmail.io/api/v1/message/3QK7ZB5M9WVXR2HD4TNFJ0PC6A \
--data-urlencode "mailbox=k7fq2m@grabmail.io"- Xóa ngay khi bạn đã lấy được thứ mình cần
- Một script xử lý một thư rồi để nguyên nó ở đó sẽ xử lý lại thư đó ở lượt chạy tiếp theo, trừ khi nó tự giữ một danh sách riêng những gì đã thấy. Xóa thư là cách ghi sổ ít tốn kém hơn.
- Đừng dựa vào việc xóa để có sự riêng tư
- Trong khoảng thời gian từ lúc đến cho tới lúc bị xóa, bất kỳ ai biết địa chỉ đều có thể đã đọc nó. Xóa thư chỉ đóng lại khoảng thời gian đó; nó không xóa được những gì đã xảy ra.
- Dù thế nào thì mọi thứ cũng biến mất sau 5 ngày
- Đã đọc hay chưa, đã xóa hay chưa, một thư sẽ biến mất 5 ngày sau khi nó đến. Đó là một giới hạn cứng chứ không phải một cấu hình, và không có tham số nào kéo dài thêm được.
Các mã lỗi để rẽ nhánh, và trường không bao giờ nên đọc
Mọi thất bại đều là JSON với cùng hai trường. error là một mã ổn định mà máy đọc được; message dành cho con người và có thể được viết lại bất cứ lúc nào. Rẽ nhánh theo trường thứ hai là cách một script gãy vào đúng ngày chẳng có gì thay đổi cả.
| Mã trạng thái và slug | Chuyện gì đã xảy ra | Script nên làm gì |
|---|---|---|
400 invalid_address | Địa chỉ bị thiếu, hoặc không có hình dạng của một địa chỉ. | Thất bại ngay lập tức. Thử lại bao nhiêu lần cũng không sửa được một lỗi gõ. |
400 bad_cursor | before không phải là một id thư. | Thất bại ngay lập tức, và kiểm tra xem bạn có đang truyền lại đúng next thay vì một giá trị bạn tự tạo ra hay không. |
404 unknown_domain | Tên miền đó không được lưu trữ ở đây. | Thất bại ngay lập tức. Trên tên miền của riêng bạn, đây là vấn đề ở bản ghi MX — xem kết nối một tên miền. |
404 not_found | Không có thư như vậy trong hộp thư đó, hoặc nó đã qua khoảng thời gian lưu trữ. | Hãy coi như nó đã biến mất. Đây cũng là kết quả bạn nhận được khi đọc một id hợp lệ nhưng với sai hộp thư. |
429 rate_limited | Một trong các giới hạn nêu ở trên. | Ngủ trong đúng số giây ghi ở Retry-After rồi tiếp tục. Không bao giờ tính đây là một lượt chạy thất bại. |
Một tác vụ dọn sạch một địa chỉ mỗi giờ
Ghép các phần lại, một tác vụ theo lịch trở nên ngắn gọn. Tác vụ này lấy mọi thư đang chờ ở một địa chỉ, ghi nó ra đĩa dưới dạng JSON, rồi xóa nó — nên lượt chạy tiếp theo luôn bắt đầu từ một hộp thư trống và không bao giờ xử lý cùng một thư hai lần.
#!/usr/bin/env bash
set -euo pipefail
ADDR="orders@example.com"
OUT="/var/lib/mailsink"
API="https://grabmail.io/api/v1"
mkdir -p "$OUT"
while :; do
page=$(curl -fsG "$API/mailbox" \
--data-urlencode "address=$ADDR" \
--data-urlencode "limit=200")
ids=$(printf '%s' "$page" | jq -r '.messages[].id')
[ -n "$ids" ] || break
for id in $ids; do
curl -fsG "$API/message/$id" \
--data-urlencode "mailbox=$ADDR" > "$OUT/$id.json"
curl -fs -X DELETE -G "$API/message/$id" \
--data-urlencode "mailbox=$ADDR" > /dev/null
done
sleep 1
done17 * * * * /usr/local/bin/drain.shCó bốn đặc tính đáng nêu tên, vì chính chúng phân biệt một tác vụ bạn có thể để chạy một mình với một tác vụ bạn phải luôn để mắt tới:
- An toàn khi chạy hai lần cùng lúc. Hai bản sao khởi động cùng lúc làm cùng một việc theo thứ tự khác nhau và xóa cùng những thư đó; bản thứ hai gặp một hộp thư trống và dừng lại.
- Ghi trước rồi mới xóa. Nếu đĩa đầy hoặc tiến trình bị kill, thư vẫn còn trong hộp thư ở lượt chạy tiếp theo. Làm ngược lại thứ tự đó sẽ mất thư đúng vào ngày nó quan trọng nhất.
- Dọn sạch chứ không chỉ đọc. Vì mỗi thư biến mất ngay khi đã an toàn trên đĩa, lượt liệt kê tiếp theo trả về hai trăm thư kế tiếp — nên một hộp thư nhận bốn trăm thư giữa hai lượt chạy sẽ được dọn sạch hoàn toàn, chứ không chỉ còn lại năm mươi thư mới nhất.
- Thất bại một cách ồn ào. Một mã thoát khác không chính là thứ khiến cron gửi output cho bạn. Một tác vụ tự nuốt lỗi của chính nó là một tác vụ đã hỏng suốt cả tháng trời mà không ai hay.
Những gì API này sẽ không làm thay bạn
Bốn điều nó không làm, mỗi điều đều có chủ đích và không có điều nào sẽ được bổ sung sau này. Tốt hơn hết là thiết kế xoay quanh những giới hạn đó ngay từ đầu, thay vì phát hiện ra chúng từ một script đã âm thầm chạy nửa vời:
- Nó không bao giờ gửi thư
- Chỉ nhận. Không có endpoint nào đưa một thư lên đường truyền, đó là lý do không có gì ở đây dùng để gửi thư từ một địa chỉ bạn không sở hữu được.
- Nó không bao giờ đẩy thông báo
- Không có webhook và không có callback: bạn hỏi, nó trả lời. Một AI agent muốn chặn lại cho đến khi thư đến thay vào đó có
wait_for_messagequa MCP — xem hướng dẫn dành cho agent. - Nó không bao giờ tìm kiếm
- Không có tham số truy vấn nào cho người gửi hay tiêu đề. Việc lọc diễn ra ở phía bạn, trên danh sách trả về — đây cũng là một lý do vì sao danh sách đó mang theo một đoạn xem trước.
- Nó không bao giờ xác thực, trên một tên miền công khai
- Bất kỳ ai biết địa chỉ đều đọc được hộp thư đó. Địa chỉ chính là toàn bộ bí mật, nên hãy đối xử với nó như một bí mật thật sự: không bao giờ suy ra nó từ tên của một khách hàng, và không bao giờ trỏ bất cứ thứ gì bạn ngại đọc to lên về phía một tên miền dùng chung.
Câu trả lời cho điều cuối cùng này là một tên miền của riêng bạn. Trỏ bản ghi MX của nó về smtp.grabmail.io và mọi địa chỉ trên tên miền đó sẽ trả lời trên đúng ba endpoint này, không cần học thêm một API thứ hai và không cần xoay vòng khóa nào — và, nếu yêu cầu, có thể được đóng lại để chỉ một bearer key mới mở được nó. Kết nối một tên miền chỉ cần một bản ghi DNS.
10 smtp.grabmail.io
Trước khi bạn để nó tự chạy
Sáu điều đáng kiểm tra trên một tác vụ sẽ chạy mà không có bạn theo dõi:
- Không thăm dò nhanh hơn một lần mỗi giây cho mỗi địa chỉ, và tuân theo
Retry-Afterkhi bạn được yêu cầu chờ. - Theo
nextđến hết, thay vì cho rằng một lượt gọi đã là toàn bộ hộp thư. - Rẽ nhánh theo mã trạng thái và
error, không bao giờ theomessage. - Ghi lại bất cứ thứ gì bạn cần giữ trước khi xóa nó, và nhớ rằng 5 ngày là một giới hạn cứng bạn không thể dời đi.
- Neo bất cứ thứ gì bạn trích xuất vào đúng khuôn mẫu của riêng bạn. Một mẫu sáu chữ số trần trụi sẽ vô tư khớp với một năm, một mức giá, hoặc một mã đơn hàng đến trước đó.
- Mặc định coi địa chỉ là công khai trừ khi nó nằm trên một tên miền do bạn kiểm soát, và đặt bất cứ điều gì quan trọng lên một tên miền như vậy.
Không điều nào trong số đó cần một tài khoản. Nếu bạn phát triển vượt quá các tên miền công khai, thứ duy nhất thay đổi là tên miền trong địa chỉ — ba lượt gọi nêu trên vẫn giữ nguyên như cũ.
Câu hỏi
Tôi có cần API key không?
Không. Trên các tên miền công khai không có tài khoản, không có token và không có gì cần đăng ký, và một tên miền bạn trỏ về đây cũng trả lời trên cùng những endpoint đó mà không cần khóa nào. Ngoại lệ duy nhất là một tên miền đã bị đóng theo yêu cầu, được đọc bằng tiêu đề Authorization: Bearer.
Tôi có thể thăm dò nhanh đến mức nào?
Một lần mỗi giây cho mỗi địa chỉ đối với việc liệt kê, đó chính là nhịp độ được thiết kế sẵn và không bao giờ bị hãm tốc độ. Đọc một thư hay một tệp đính kèm được đo lường riêng và rộng rãi hơn nhiều, nên bạn có thể xử lý dồn dập trọn một trang thư. Tất cả cộng lại bị giới hạn ở 1200 yêu cầu mỗi phút cho mỗi client.
Làm sao tôi biết khi nào mình đã đọc hết toàn bộ hộp thư?
Khi next trả về null. Đừng suy luận điều đó từ một trang ngắn: máy chủ quyết định thế nào là một trang, và một trang ngắn hơn limit tự nó không có nghĩa là đã hết.
Tôi có thể gọi API này từ một trình duyệt không?
Có. Phản hồi luôn mang theo Access-Control-Allow-Origin: *, nên một trang trên bất kỳ origin nào cũng gọi thẳng được các endpoint mà không cần một proxy của bạn ở giữa. Việc cấp quyền ở đây không bao giờ dựa vào cookie, nên mở rộng đến mức đó không tốn kém gì cả.
Điều gì xảy ra nếu tôi hỏi về một thư đã hết hạn?
404 kèm not_found, giống hệt như với một id chưa từng tồn tại. Mọi thứ đều bị xóa 5 ngày sau khi đến, dù đã đọc hay chưa, và không có tham số nào kéo dài thêm được điều đó.
Tôi có thể nhận một webhook khi thư đến không?
Không — REST API hoạt động theo kiểu hỏi rồi mới đáp, không có callback nào cả. Nếu điều bạn cần là đoạn code chặn lại cho đến khi thư đến, máy chủ MCP có wait_for_message, làm chính xác việc đó và được thiết kế cho các agent.
Dùng một địa chỉ công khai trong môi trường production có an toàn không?
Chỉ an toàn cho những gì bạn không ngại một người lạ đọc được. Bất kỳ ai biết địa chỉ đều đọc được hộp thư của nó, qua API giống hệt như qua trang web. Với bất cứ điều gì khác, hãy trỏ một tên miền của riêng bạn về đây — các lượt gọi không thay đổi gì cả.
Vì sao một thư tôi chưa từng mở lại hiện là đã đọc?
Vì có thứ gì đó đã mở nó. Đọc một thư qua API sẽ bật cờ seen của nó, và cờ đó được chia sẻ cho tất cả mọi người đang xem địa chỉ đó. Một script và một người cùng theo dõi một hộp thư sẽ liên tục khiến nhau bất ngờ, nên hãy lọc theo các id bạn đã xử lý thay vì theo seen.
Tôi có bắt buộc phải xóa thư không?
Không — mọi thứ tự hết hạn sau 5 ngày. Nhưng việc xóa vẫn đáng làm trong một tác vụ theo lịch, vì một hộp thư đã được dọn sạch là bản ghi đơn giản nhất có thể có về những gì bạn đã xử lý xong.


