diff --git a/.env.example b/.env.example index 71cbc60..d7a2948 100644 --- a/.env.example +++ b/.env.example @@ -18,6 +18,7 @@ OPENCLAW_API_KEY= BRIDGE_CALLBACK_TOKEN=a-strong-random-token SYSTEM_EMAIL=bridge@example.com WHITELIST_EMAILS=user1@example.com,user2@example.com +BLOCKLIST_EMAILS= # === Optional === IMAP_PROXY_URL= diff --git a/README.md b/README.md index 014ad0c..69f3daf 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Tự động xử lý email bằng OpenClaw AI theo luồng: ``` -Ingress (IMAP) → Dispatch (OpenClaw) → Callback → Egress (SMTP reply) +Ingress (IMAP) → Safety Checks → External Rules → Apply Context → Dispatch (OpenClaw) → Callback → Egress (SMTP reply) ``` ## Tính năng @@ -12,6 +12,7 @@ Ingress (IMAP) → Dispatch (OpenClaw) → Callback → Egress (SMTP reply) - **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 diff --git a/docs/adr/0002-external-rules-pipeline.md b/docs/adr/0002-external-rules-pipeline.md new file mode 100644 index 0000000..f86859c --- /dev/null +++ b/docs/adr/0002-external-rules-pipeline.md @@ -0,0 +1,30 @@ +--- +type: ADR +id: "0002" +title: "Ingress uses a configurable external rules pipeline before dispatch" +status: active +date: 2026-04-28 +--- + +## Context + +The IMAP ingress flow previously hardcoded whitelist and idempotency checks directly in processMessage. There was no extension point for operator-defined policy such as sender blocking or context-based routing. The flow mixed internal safety rules (anti-loop) with configurable policy (whitelist). + +## Decision + +Separate internal safety checks (anti-loop, idempotency) from external configurable rules. External rules run in a pipeline after safety checks. Each rule implements a `Rule` interface that evaluates `EmailContext` and returns `RuleResult` (accept/reject + metadata). Rule metadata is persisted as `DispatchContext` on the Task and passed to OpenClaw dispatch. + +Pipeline order: anti-loop (internal) → idempotency (internal) → external rules → threading → save → dispatch. + +## Options considered + +- **Pipeline with Rule interface** (chosen): extensible, testable, each rule is isolated. +- **Keep everything in processMessage**: simpler but not configurable or testable. +- **Plugin-based rules via config files**: more flexible but over-engineered for current needs. + +## Consequences + +New rules can be added by implementing the Rule interface and registering in config. +Whitelist and blocklist are now env-configurable and independently testable. +Future rules (domain routing, context selection) fit the same pipeline. +Task model has a new DispatchContext column (auto-migrated). diff --git a/docs/adr/README.md b/docs/adr/README.md index 74d212a..18f416b 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -73,3 +73,4 @@ Optional. Capture important external input or review notes. | ID | Title | Status | |----|-------|--------| | 0001 | IMAP thread resolution prefers In-Reply-To and falls back to References | active | +| 0002 | Ingress uses a configurable external rules pipeline before dispatch | active |