# Checkpoint 005 — SMTP Egress **Ngày:** 2026-04-24 **Trạng thái:** ✅ Hoàn thành **Verify:** `go build ./...` thành công --- ## Việc đã làm ### SMTP Sender (`internal/mail/smtp.go`) **Gửi reply email (requirements 4.3):** - Subject: thêm prefix `Re:` nếu chưa có - Body: `task.AIResponse` từ OpenClaw callback - Threading headers: - `In-Reply-To: ` - `References: ` - MIME: `text/plain; charset=UTF-8` **Retry logic (đúng requirements):** - Tối đa 3 lần, backoff: 1s → 5s → 15s - Mỗi lần retry: tăng `attempt_smtp`, status = `SMTP_RETRYING` - Hết retry: `status = FAILED`, ghi `last_error` - Thành công: `status = COMPLETED` **SMTP delivery:** - `net/smtp.SendMail` với `PlainAuth` - Địa chỉ: `SMTP_HOST:SMTP_PORT` - From: `SYSTEM_EMAIL` ### Wiring (`cmd/bridge/main.go`) - `smtpSender.SendReplyFunc()` → `api.NewRouter(..., onDone)` - Callback handler gọi `onDone(task)` async sau khi trả response --- ## Pipeline hoàn chỉnh 🎉 ``` IMAP IDLE → RECEIVED → AI_PROCESSING → (OpenClaw callback) → CALLBACK_DONE → SMTP reply → COMPLETED ↓ ↓ ↓ IGNORED FAILED FAILED ``` Tất cả transitions đã được implement: - IMAP → RECEIVED ✅ - RECEIVED → AI_PROCESSING ✅ - AI_PROCESSING → CALLBACK_DONE ✅ - CALLBACK_DONE → SMTP_RETRYING → COMPLETED/FAILED ✅ - Anti-loop/Whitelist → IGNORED ✅ - Retry exhausted → FAILED ✅ ## Files thay đổi - **Mới:** `internal/mail/smtp.go` - **Cập nhật:** `cmd/bridge/main.go` (wire SMTP sender) ## Tiếp theo 1. **Integration tests** — 6 scenarios từ requirements section 10