Skip to content

Commit 1e62b31

Browse files
guo-yuclaude
andcommitted
Update skill.md and README for v1.1.0
New in docs: - Inbox search (--query) - Attachment sending (--attach) and receiving - Remote provider (light client) - Self-hosted Worker setup with AUTH_TOKEN - worker_url / worker_token config - searchInbox SDK export - Updated test counts (125 unit + 42 E2E) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 8b1ddbb commit 1e62b31

2 files changed

Lines changed: 175 additions & 77 deletions

File tree

README.md

Lines changed: 83 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@ Email infrastructure for AI agents. Send and receive emails programmatically.
99

1010
## Features
1111

12-
- **Send emails** via Resend (more providers coming)
12+
- **Send emails** via Resend with attachment support
1313
- **Receive emails** via Cloudflare Email Routing Worker
14+
- **Search inbox** — keyword search across subject, body, sender, code
1415
- **Verification code extraction** — auto-extracts codes from emails (EN/ZH/JA/KO)
15-
- **Storage providers** — local SQLite (default) or [db9.ai](https://db9.ai) cloud PostgreSQL
16-
- **Zero dependencies** — Resend provider uses raw `fetch()`, no SDK needed
17-
- **Agent-first** — designed for AI agents with `skill.md` integration guide
18-
- **Cloud service**`@mails.dev` addresses with x402 micropayments (coming soon)
16+
- **Attachments** — send files via CLI (`--attach`) or SDK, receive and parse MIME attachments
17+
- **Storage providers** — local SQLite, [db9.ai](https://db9.ai) cloud PostgreSQL, or remote Worker API
18+
- **Zero runtime dependencies** — Resend provider uses raw `fetch()`
19+
- **Hosted service** — free `@mails.dev` mailboxes via `mails claim`
20+
- **Self-hosted** — deploy your own Worker with optional AUTH_TOKEN
1921

2022
## Install
2123

@@ -29,34 +31,55 @@ npx mails
2931

3032
## Quick Start
3133

34+
### Hosted (mails.dev)
35+
3236
```bash
33-
# Configure
37+
mails claim myagent # Claim myagent@mails.dev
3438
mails config set resend_api_key re_YOUR_KEY
3539
mails config set default_from "Agent <agent@yourdomain.com>"
36-
37-
# Send an email
3840
mails send --to user@example.com --subject "Hello" --body "World"
41+
mails inbox # List received emails
42+
mails inbox --query "password" # Search emails
43+
```
44+
45+
### Self-Hosted
46+
47+
```bash
48+
cd worker && wrangler deploy # Deploy your own Worker
49+
mails config set worker_url https://your-worker.example.com
50+
mails config set worker_token YOUR_TOKEN
51+
mails config set mailbox agent@yourdomain.com
52+
mails inbox # Queries your Worker API
3953
```
4054

4155
## CLI Reference
4256

43-
### Send
57+
### claim
58+
59+
```bash
60+
mails claim <name> # Claim name@mails.dev (max 10 per user)
61+
```
62+
63+
### send
4464

4565
```bash
4666
mails send --to <email> --subject <subject> --body <text>
4767
mails send --to <email> --subject <subject> --html "<h1>Hello</h1>"
4868
mails send --from "Name <email>" --to <email> --subject <subject> --body <text>
69+
mails send --to <email> --subject "Report" --body "See attached" --attach report.pdf
4970
```
5071

51-
### Inbox
72+
### inbox
5273

5374
```bash
54-
mails inbox # List recent emails
55-
mails inbox --mailbox agent@test.com # Specific mailbox
56-
mails inbox <id> # View email details
75+
mails inbox # List recent emails
76+
mails inbox --mailbox agent@test.com # Specific mailbox
77+
mails inbox --query "password reset" # Search emails
78+
mails inbox --query "invoice" --direction inbound --limit 10
79+
mails inbox <id> # View email details + attachments
5780
```
5881

59-
### Verification Code
82+
### code
6083

6184
```bash
6285
mails code --to agent@test.com # Wait for code (default 30s)
@@ -65,19 +88,18 @@ mails code --to agent@test.com --timeout 60 # Custom timeout
6588

6689
The code is printed to stdout for easy piping: `CODE=$(mails code --to agent@test.com)`
6790

68-
### Config
91+
### config
6992

7093
```bash
7194
mails config # Show all config
7295
mails config set <key> <value> # Set a value
7396
mails config get <key> # Get a value
74-
mails config path # Show config file path
7597
```
7698

7799
## SDK Usage
78100

79101
```typescript
80-
import { send, getInbox, waitForCode } from 'mails'
102+
import { send, getInbox, searchInbox, waitForCode } from 'mails'
81103

82104
// Send
83105
const result = await send({
@@ -86,28 +108,28 @@ const result = await send({
86108
text: 'World',
87109
})
88110

111+
// Send with attachment
112+
await send({
113+
to: 'user@example.com',
114+
subject: 'Report',
115+
text: 'See attached',
116+
attachments: [{ path: './report.pdf' }],
117+
})
118+
89119
// List inbox
90-
const emails = await getInbox('agent@yourdomain.com', { limit: 10 })
120+
const emails = await getInbox('agent@mails.dev', { limit: 10 })
121+
122+
// Search inbox
123+
const results = await searchInbox('agent@mails.dev', {
124+
query: 'password reset',
125+
direction: 'inbound',
126+
})
91127

92128
// Wait for verification code
93-
const code = await waitForCode('agent@yourdomain.com', { timeout: 30 })
129+
const code = await waitForCode('agent@mails.dev', { timeout: 30 })
94130
if (code) console.log(code.code) // "123456"
95131
```
96132

97-
### Direct Provider Usage
98-
99-
```typescript
100-
import { createResendProvider } from 'mails'
101-
102-
const resend = createResendProvider('re_YOUR_KEY')
103-
await resend.send({
104-
from: 'Agent <agent@yourdomain.com>',
105-
to: ['user@example.com'],
106-
subject: 'Hello',
107-
text: 'Direct provider usage',
108-
})
109-
```
110-
111133
## Email Worker
112134

113135
The `worker/` directory contains a Cloudflare Email Routing Worker for receiving emails.
@@ -117,80 +139,78 @@ The `worker/` directory contains a Cloudflare Email Routing Worker for receiving
117139
```bash
118140
cd worker
119141
bun install
120-
# Edit wrangler.toml — set your D1 database ID
121142
wrangler d1 create mails
143+
# Edit wrangler.toml — set your D1 database ID
122144
wrangler d1 execute mails --file=schema.sql
123145
wrangler deploy
124146
```
125147

126148
Then configure Cloudflare Email Routing to forward to this worker.
127149

150+
### Secure the Worker (optional)
151+
152+
```bash
153+
wrangler secret put AUTH_TOKEN # Set a secret token
154+
```
155+
156+
If `AUTH_TOKEN` is set, all `/api/*` endpoints require `Authorization: Bearer <token>`. `/health` is always public.
157+
128158
### Worker API
129159

130160
| Endpoint | Description |
131161
|----------|-------------|
132162
| `GET /api/inbox?to=<addr>&limit=20` | List emails |
163+
| `GET /api/inbox?to=<addr>&query=<text>` | Search emails |
133164
| `GET /api/code?to=<addr>&timeout=30` | Long-poll for verification code |
134-
| `GET /api/email?id=<id>` | Get email by ID |
135-
| `GET /health` | Health check |
165+
| `GET /api/email?id=<id>` | Get email by ID (with attachments) |
166+
| `GET /health` | Health check (always public) |
136167

137168
## Storage Providers
138169

170+
The CLI auto-detects the storage provider:
171+
- `api_key` in config → remote (mails.dev hosted)
172+
- `worker_url` in config → remote (self-hosted Worker)
173+
- Otherwise → local SQLite
174+
139175
### SQLite (default)
140176

141177
Local database at `~/.mails/mails.db`. Zero config.
142178

143179
### db9.ai
144180

145-
Cloud PostgreSQL for AI agents.
181+
Cloud PostgreSQL for AI agents. Full-text search with ranking.
146182

147183
```bash
148184
mails config set storage_provider db9
149185
mails config set db9_token YOUR_TOKEN
150186
mails config set db9_database_id YOUR_DB_ID
151187
```
152188

189+
### Remote (Worker API)
190+
191+
Queries the Worker HTTP API directly. Auto-enabled when `api_key` or `worker_url` is configured.
192+
153193
## Config Keys
154194

155195
| Key | Default | Description |
156196
|-----|---------|-------------|
157-
| `mode` | `hosted` | `hosted` or `selfhosted` |
158-
| `domain` | `mails.dev` | Email domain |
159197
| `mailbox` | | Your receiving address |
160-
| `send_provider` | `resend` | Send provider |
161-
| `storage_provider` | `sqlite` | `sqlite` or `db9` |
198+
| `api_key` | | API key for mails.dev hosted service |
199+
| `worker_url` | | Self-hosted Worker URL |
200+
| `worker_token` | | Auth token for self-hosted Worker |
162201
| `resend_api_key` | | Resend API key |
163202
| `default_from` | | Default sender address |
164-
| `db9_token` | | db9.ai API token |
165-
| `db9_database_id` | | db9.ai database ID |
203+
| `storage_provider` | auto | `sqlite`, `db9`, or `remote` |
166204

167205
## Testing
168206

169207
```bash
170-
bun test # Run all tests (78 unit + 1 E2E)
208+
bun test # Unit + mock E2E tests
171209
bun test:coverage # With coverage report
172210
bun test:live # Live E2E with real Resend + Cloudflare (requires .env)
173211
```
174212

175-
### Test Coverage
176-
177-
```
178-
---------------------------------|---------|---------|
179-
File | % Funcs | % Lines |
180-
---------------------------------|---------|---------|
181-
All files | 100.00 | 100.00 |
182-
src/cli/commands/help.ts | 100.00 | 100.00 |
183-
src/core/config.ts | 100.00 | 100.00 |
184-
src/core/send.ts | 100.00 | 100.00 |
185-
src/core/types.ts | 100.00 | 100.00 |
186-
src/providers/send/resend.ts | 100.00 | 100.00 |
187-
src/providers/storage/db9.ts | 100.00 | 100.00 |
188-
src/providers/storage/sqlite.ts | 100.00 | 100.00 |
189-
worker/src/extract-code.ts | 100.00 | 100.00 |
190-
---------------------------------|---------|---------|
191-
192-
78 unit tests + 8 live E2E tests (real Resend + Cloudflare Email Routing)
193-
```
213+
125 unit tests + 42 E2E tests across 6 test suites.
194214

195215
## License
196216

0 commit comments

Comments
 (0)