Merge pull request 'docs: reorganize README and technical overview' (#23) from docs/readme-docs-reorg into main

Reviewed-on: #23
This commit was merged in pull request #23.
This commit is contained in:
2026-04-29 00:52:41 +07:00
2 changed files with 130 additions and 53 deletions
+29 -53
View File
@@ -1,38 +1,26 @@
# Email-OpenClaw Bridge
Tự động xử lý email bằng OpenClaw AI theo luồng:
Bridge tự động xử lý email bằng OpenClaw AI theo luồng:
```
Ingress (IMAP) → Safety Checks → External Rules → Apply Context → Dispatch (OpenClaw) → Callback → Egress (SMTP reply)
```text
Ingress (IMAP) → Safety Checks → External Rules → Dispatch (OpenClaw) → Callback → Egress (SMTP reply)
```
## Tính năng
README này tập trung vào onboarding và vận hành cơ bản. Chi tiết kỹ thuật hiện hành được tách sang `docs/architecture/overview.md`.
- **IMAP IDLE** — theo dõi mailbox realtime, nhận email mới tức thì
- **Threading** — giữ nguyên email thread qua `In-Reply-To` / `References`
- **Idempotency** — chống duplicate theo `message_id`
- **Anti-loop & Whitelist** — bỏ qua email từ chính hệ thống, chỉ xử lý sender được phép
- **External Rules** — pipeline configurable: whitelist, blocklist, và rule metadata cho dispatch
- **Retry** — tối đa 3 lần với backoff 1s → 5s → 15s cho cả OpenClaw và SMTP
- **Stateful** — SQLite lưu trạng thái pipeline, không mất dữ liệu khi restart
## Tính năng chính
## Kiến trúc
- Theo dõi mailbox realtime bằng IMAP IDLE
- Giữ thread email qua `In-Reply-To``References`
- Chống duplicate theo `message_id`
- Chặn anti-loop và hỗ trợ whitelist/blocklist
- Gửi callback vào bridge rồi phản hồi lại qua SMTP
- Lưu trạng thái pipeline bằng SQLite để không mất tiến trình khi restart
```
cmd/bridge/main.go Entrypoint
internal/
├── config/ Đọc cấu hình từ .env
├── database/ SQLite + GORM, auto-migrate
├── logging/ Structured JSON logging (slog)
├── api/ HTTP server (Gin): health checks, webhook callback
├── mail/ IMAP ingress + SMTP egress
└── ai_client/ OpenClaw HTTP dispatch
```
## Yêu cầu
## Yêu cầu tối thiểu
- Go 1.23+
- Docker & Docker Compose (cho deploy)
- Docker Docker Compose nếu chạy bằng container
## Quickstart
@@ -43,7 +31,7 @@ cp .env.example .env
# Sửa .env với thông tin IMAP/SMTP/OpenClaw thực tế
```
### 2. Chạy local (development)
### 2. Chạy local
```bash
go run ./cmd/bridge
@@ -56,51 +44,39 @@ docker compose up -d
docker logs -f claw-email-bridge
```
## Cấu hình (.env)
## Cấu hình `.env`
| Biến | Bắt buộc | Mô tả |
|---|:---:|---|
| `IMAP_HOST` | ✅ | IMAP server hostname |
| `IMAP_PORT` | ✅ | IMAP port (thường `993`) |
| `IMAP_PORT` | ✅ | IMAP port, thường `993` |
| `IMAP_USER` | ✅ | IMAP username |
| `IMAP_PASS` | ✅ | IMAP password |
| `SMTP_HOST` | ✅ | SMTP server hostname |
| `SMTP_PORT` | ✅ | SMTP port (thường `587`) |
| `SMTP_PORT` | ✅ | SMTP port, thường `587` |
| `SMTP_USER` | ✅ | SMTP username |
| `SMTP_PASS` | ✅ | SMTP password |
| `OPENCLAW_URL` | ✅ | OpenClaw API endpoint |
| `OPENCLAW_API_KEY` | | OpenClaw API key (nếu cần) |
| `OPENCLAW_API_KEY` | | OpenClaw API key nếu cần |
| `BRIDGE_CALLBACK_TOKEN` | ✅ | Token xác thực webhook callback |
| `SYSTEM_EMAIL` | ✅ | Email của hệ thống (dùng cho anti-loop) |
| `SYSTEM_EMAIL` | ✅ | Email của bridge, dùng cho anti-loop |
| `WHITELIST_EMAILS` | | Danh sách email được phép, phân cách bằng dấu phẩy |
| `IMAP_PROXY_URL` | | SOCKS5 proxy cho IMAP (vd: `socks5://user:pass@host:port`) |
| `LISTEN_ADDR` | | Địa chỉ bind HTTP server cục bộ (mặc định `:8080`) |
| `CALLBACK_BASE_URL` | | Base URL public để tạo `callback_url` gửi OpenClaw (mặc định theo `LISTEN_ADDR`, ví dụ `http://localhost:8080`) |
| `BLOCKLIST_EMAILS` | | Danh sách email bị chặn, phân cách bằng dấu phẩy |
| `IMAP_PROXY_URL` | | Proxy cho IMAP, hỗ trợ `socks5://`, `http://`, `https://` |
| `LISTEN_ADDR` | | Địa chỉ bind HTTP server, mặc định `:8080` |
| `CALLBACK_BASE_URL` | | Base URL public để tạo `callback_url`, mặc định suy ra từ `LISTEN_ADDR` |
## Health Checks
## Health checks
| Endpoint | Mục đích |
|---|---|
| `GET /healthz` | Liveness process còn sống |
| `GET /readyz` | Readiness DB writable + config hợp lệ |
| `GET /healthz` | Liveness check, xác nhận process còn sống |
| `GET /readyz` | Readiness check, xác nhận DB writable config bắt buộc hợp lệ |
## Pipeline trạng thái
## Đọc thêm
```
RECEIVED → AI_PROCESSING → CALLBACK_DONE → COMPLETED
↓ ↓ ↓
IGNORED FAILED SMTP_RETRYING → FAILED
```
## Công nghệ
| Thành phần | Thư viện |
|---|---|
| HTTP Server | [gin-gonic/gin](https://github.com/gin-gonic/gin) |
| Database | [GORM](https://gorm.io) + [modernc.org/sqlite](https://pkg.go.dev/modernc.org/sqlite) (pure Go, no CGO) |
| IMAP | [emersion/go-imap](https://github.com/emersion/go-imap) |
| Logging | [log/slog](https://pkg.go.dev/log/slog) (stdlib) |
| Config | [joho/godotenv](https://github.com/joho/godotenv) |
- [Technical overview](docs/architecture/overview.md)
- [Architecture Decision Records](docs/adr/README.md)
## License
+101
View File
@@ -0,0 +1,101 @@
# Technical Overview
## Mục đích
Tài liệu này là technical overview hiện hành của `Email-OpenClaw Bridge`. `README.md` chỉ giữ phần onboarding và vận hành cơ bản; phần này giữ các chi tiết kỹ thuật bền vững hơn về flow, package layout, state machine và công nghệ chính.
## Luồng xử lý
Bridge xử lý email theo pipeline sau:
```text
Ingress (IMAP) → Safety Checks → External Rules → Dispatch (OpenClaw) → Callback → Egress (SMTP reply)
```
Các giai đoạn runtime chính:
1. IMAP watcher theo dõi `INBOX` bằng IDLE và fetch email chưa đọc.
2. Safety checks loại bỏ mail từ chính hệ thống và chặn duplicate theo `message_id`.
3. External rules pipeline áp whitelist/blocklist và sinh `DispatchContext`.
4. Thread resolution gắn `thread_id` dựa trên quan hệ email đã biết.
5. Task được lưu vào SQLite với trạng thái pipeline hiện tại.
6. OpenClaw nhận request xử lý và callback về bridge.
7. Callback cập nhật `AIResponse`, sau đó bridge gửi phản hồi lại qua SMTP.
## Package layout
- `cmd/bridge`
- Entrypoint của process, wiring config, DB, IMAP watcher, HTTP router và SMTP egress.
- `internal/config`
- Đọc `.env`, chuẩn hóa default như `LISTEN_ADDR`, `CALLBACK_BASE_URL`, và validate biến bắt buộc.
- `internal/database`
- Khởi tạo SQLite qua GORM, định nghĩa `Task` model, repository helpers và health check DB.
- `internal/mail`
- Chứa IMAP ingress, thread resolution, proxy support cho IMAP, retry logic và SMTP egress.
- `internal/rules`
- External rules pipeline, whitelist/blocklist rules và rule metadata dùng cho dispatch.
- `internal/ai_client`
- HTTP client gọi OpenClaw và gửi metadata/callback information ra ngoài.
- `internal/api`
- HTTP router cho `healthz`, `readyz``POST /callback`.
- `internal/logging`
- Helper tạo structured logger theo `task_uuid`, `thread_id`, `message_id`.
## Task state machine
Task được lưu trong SQLite và đi qua các trạng thái sau:
```text
RECEIVED → AI_PROCESSING → CALLBACK_DONE → COMPLETED
↓ ↓ ↓
IGNORED FAILED SMTP_RETRYING → FAILED
```
- `IGNORED`
- Mail bị anti-loop, duplicate, hoặc bị external rules reject.
- `RECEIVED`
- Task đã được lưu và sẵn sàng dispatch.
- `AI_PROCESSING`
- Request đã được gửi sang OpenClaw.
- `CALLBACK_DONE`
- Callback hợp lệ đã cập nhật `AIResponse`.
- `SMTP_RETRYING`
- Đang retry gửi email phản hồi.
- `COMPLETED`
- Toàn bộ pipeline kết thúc thành công.
- `FAILED`
- Hết retry hoặc gặp lỗi không recoverable.
## HTTP và health behavior
- `GET /healthz`
- Trả `200 {"status":"ok"}` nếu process đang sống.
- `GET /readyz`
- Trả `200` khi DB writable và `BRIDGE_CALLBACK_TOKEN` có mặt.
- Trả `503` nếu DB không writable hoặc config bắt buộc cho callback chưa sẵn sàng.
- `POST /callback`
- Yêu cầu header `X-Bridge-Token`.
- Nhận payload callback từ OpenClaw, cập nhật task và kích hoạt SMTP egress bất đồng bộ.
## Công nghệ chính
- Go
- Runtime chính, phù hợp với service nhỏ gọn và dễ deploy.
- SQLite + GORM
- Giữ state cục bộ đơn giản, không cần service DB riêng cho v1.
- `github.com/emersion/go-imap/v2`
- Hỗ trợ IMAP IDLE và xử lý mailbox theo flow hiện tại.
- `gin-gonic/gin`
- Cung cấp HTTP router tối giản cho health endpoints và callback.
- `log/slog`
- Structured logging chuẩn thư viện chuẩn của Go.
## ADR liên quan
- [ADR 0001: IMAP thread resolution prefers In-Reply-To and falls back to References](../adr/0001-imap-thread-resolution.md)
- [ADR 0002: Ingress uses a configurable external rules pipeline before dispatch](../adr/0002-external-rules-pipeline.md)
- [ADR index](../adr/README.md)
## Tài liệu lịch sử
- Historical design input: [docs/specs/2026-04-24-email-openclaw-bridge-design.md](../specs/2026-04-24-email-openclaw-bridge-design.md)