mail-mcp/README.md
Kayos 2240bf745e mail-mcp v0.1 — Rust MCP server for Sulkta email
Phase A: mail_send + mail_inbox_list + mail_inbox_read. Replaces
scripts/kayos_mail.py with a typed MCP server. Outbound guarantees Date,
Message-ID (own-domain), User-Agent, MIME-Version, multipart/alternative
for HTML+text, multipart/mixed for attachments, In-Reply-To +
References for threading.

Single account in v0.1 (default_account from config). Phase B adds
multi-account + threading + search; Phase C adds mark + attachments +
reply helper.

Stack: rmcp 0.1 (matches aldabra), lettre 0.11 + tokio-rustls, async-imap
0.10, mail-parser 0.9. Stderr-only logging (stdout is the MCP transport).

Smoke verified 2026-05-21: send -> land -> read kayos@sulkta.com round
trip, DKIM-Signature + Authentication-Results pass at the rspamd relay.
2026-05-21 06:50:25 -07:00

73 lines
3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# mail-mcp
Rust MCP server for Sulkta-hosted email. SMTP send + IMAP read with RFC-correct headers, multipart/alternative when HTML is included, multipart/mixed for attachments, threading via `In-Reply-To`/`References`.
Replaces the `scripts/kayos_mail.py` CLI path that lived in `kayos/openclaw-workspace` since 2026-04-23.
## Why a server, not a CLI
`kayos_mail.py` shipped without `Date` or `Message-ID` headers until a 2026-05-18 patch — exactly the kind of header-discipline regression a typed Rust server prevents at compile time. The "no spam bin" framing is mostly upstream of any client (Rackham postfix + rspamd DKIM-sign at the relay; mail-tester scored 10/10 and port25 SpamAssassin 7.31 on 2026-05-20), but a correct client doesn't trip filters with bad MIME structure, broken threading, or missing headers.
## Tools (v0.1)
- `mail_send` — send mail. Args: `account?`, `to`, `cc[]?`, `bcc[]?`, `subject`, `body`, `body_html?`, `attachments[]?`, `in_reply_to?`, `references[]?`. Returns `{message_id, sent_at}`.
- `mail_inbox_list` — list folder messages newest-first. Args: `account?`, `since?` (YYYY-MM-DD), `unread_only?`, `limit?` (default 50, max 500), `folder?` (default INBOX). Uses `BODY.PEEK` so it does not toggle `\Seen`.
- `mail_inbox_read` — fetch one message by UID. Args: `account?`, `uid`, `folder?`, `format?` (`text`|`html`|`raw_eml`). Attachment payloads are not inlined — only filename/mime_type/size metadata.
## Headers we guarantee on outbound
- `Date` — UTC, RFC 5322 (lettre auto)
- `Message-ID``<UUIDv4@<from_addr_domain>>` — own-domain, never the container hostname
- `From``name <addr>`
- `MIME-Version: 1.0`
- `User-Agent: mail-mcp/<version>`
- `In-Reply-To` + `References` when threading args present
- `Content-Type` correct for the body shape (text-only / alternative / mixed)
DKIM-Signature is applied by the relay (rspamd on Rackham), not the client.
## Build
```bash
cargo build --release
```
Binary lands at `target/release/mail-mcp`.
## Config
```bash
mkdir -p ~/.config/mail-mcp
cp config.example.toml ~/.config/mail-mcp/config.toml
chmod 600 ~/.config/mail-mcp/config.toml
```
Edit accounts as needed. Passwords are NEVER inline:
1. Looked up from the env var named in `password_env`
2. Falling back to `password_file` (shell-format: `KEY=VALUE` per line)
3. Hard-failing with a vault-pointer hint if neither resolves
Vault canonical: `bw.sulkta.com``kayos@sulkta.com — IMAP/SMTP`.
## MCP wiring (Claude Code / kayos-house)
```json
{
"mcpServers": {
"mail-mcp": {
"command": "/usr/local/bin/mail-mcp",
"args": []
}
}
}
```
Logging is stderr-only — stdout is the JSON-RPC transport.
## Future phases
- **Phase B** (~200 LOC): multi-account routing across all configured `[accounts.*]`, plus `mail_thread` and `mail_search`.
- **Phase C** (~150 LOC): `mail_mark` (read/unread/flag/trash/archive), `mail_attachment_get`, `mail_reply` helper.
Full locked spec: `kayos/openclaw-workspace``memory/spec-mail-mcp.md`.