Skip to content

Releases

v1.1.0

Choose a tag to compare

@github-actions github-actions released this 23 Aug 20:51
3bf846d

What's Changed

Full Changelog: v1.0.0...v1.1.0

v1.0.0

Choose a tag to compare

@github-actions github-actions released this 17 Aug 14:29
99c8d12

First release of the Go rewrite. This replaces the Python poke-mail server entirely — different language, different architecture, and no Poke integration. Treat it as a new project that happens to share a repository.

What this is

An MCP server that gives AI agents controlled access to IMAP and SMTP mailboxes — read, search, organize, and send — without ever handing them your credentials.

Tools take an opaque account_id. The server resolves it against a config file that stays on the server and makes the connection itself, so a remote agent has no way to reconstruct how to reach your mailbox.

Breaking changes from poke-mail

Everything Poke-specific is gone: the inbound webhook, the IMAP IDLE watcher, the polling fallback, and the poke tunnel integration. The server no longer initiates anything on its own — it only answers tool calls.

  • POKE_WEBHOOK_URL, POKE_API_KEY, POKE_TUNNEL removed. No replacement; the forwarding feature does not exist.
  • MCP_API_KEY is now mandatory on the HTTP transport. The server refuses to start without it — there is no unauthenticated mode, and no tunnel exemption.
  • watch_folders and mark_as_read removed from account config. Both existed only to feed the watcher.
  • Every tool renamed or reshaped. Message-scoped tools no longer take account_id, and uid + folder are replaced by a single opaque message_id.
  • Sending and deleting are disabled by default. Set allow_send / allow_delete, globally or per account.
  • STARTTLS is mandatory, never opportunistic. A provider that was silently falling back to plaintext will now fail loudly rather than transmitting your password in the clear.

Existing config.yml files load unchanged — the flat imap_host / smtp_username style keys are folded into the nested form automatically.

Correctness fixes carried over from the Python version

  • Message identity is now safe. Tools previously took a bare (uid, folder) pair with no UIDVALIDITY check. If a server renumbered a mailbox, a cached uid silently pointed at a different message, so an archive or move could hit the wrong mail. Handles now carry account, folder, UIDVALIDITY, and uid together, verified on every operation, and a stale handle produces an explicit error instead of acting.
  • send_email returned an empty message_id. It read a header that smtplib never sets, so callers always got "". Message-IDs are now generated locally and returned.
  • No timeouts existed on SMTP. smtplib was called with no timeout, so a hung server blocked a worker indefinitely. Every network operation is now bounded.
  • Recipient lists were split naively on commas, breaking "Doe, John" <j@x.com>. Addresses are parsed properly and header injection via embedded newlines is rejected.

New capabilities

  • Attachments on send, from a file path or inline base64.
  • reply_email with reply-all, self-address exclusion, derived Re: subject, and a correct References chain.
  • forward_email carrying the original's attachments and quoting it below your note.
  • get_attachment writes a chosen file to disk and returns the path. Attachment bytes never enter a tool response, so a large PDF cannot flood the context window.
  • Sent-folder copies written from the exact delivered bytes, with a provider-aware default: Gmail and Zoho file their own copy on submission, while iCloud, Office 365, and generic relays do not.
  • verify_account tests IMAP and SMTP without sending or reading anything.
  • stdio transport for local clients, alongside authenticated HTTP.
  • Pooled IMAP connections, health-checked and reused, removing a TLS handshake and LOGIN from every tool call.

Install

docker run -d --name mail-mcp \
  -p 3000:3000 \
  -v "$PWD/config.yml:/config.yml:ro" \
  -e MCP_API_KEY="$(openssl rand -hex 32)" \
  ghcr.io/kacperkwapisz/mail-mcp:1.0.0

Or grab a binary below. Multi-arch images are published for linux/amd64 and linux/arm64.

See the README for configuration, and config.example.yml for an annotated template.

Verified

gofmt, go vet, and golangci-lint clean; full suite green under -race. The binary is exercised end to end: it refuses to start without a token, rejects bad tokens with 401, returns an empty 404 off-path, and serves all 18 tools over both HTTP and stdio.

Not yet exercised against a live mail server — validation so far is unit tests plus protocol-level handshakes.