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.
This commit is contained in:
Kayos 2026-05-21 06:50:25 -07:00
commit 2240bf745e
11 changed files with 3552 additions and 0 deletions

27
config.example.toml Normal file
View file

@ -0,0 +1,27 @@
# mail-mcp config — copy to ~/.config/mail-mcp/config.toml, chmod 600.
#
# Passwords are NEVER inline. Each account names an env var (`password_env`)
# AND a fallback file (`password_file`). Lookup order:
# 1. env var
# 2. shell-format file (`KEY=VALUE` per line)
# 3. hard fail with a vault-pointer hint
#
# Vault canonical: bw.sulkta.com → "kayos@sulkta.com — IMAP/SMTP".
default_account = "kayos"
[accounts.kayos]
from_name = "Kayos"
from_addr = "kayos@sulkta.com"
smtp_host = "mail.sulkta.com"
smtp_port = 587
smtp_starttls = true
imap_host = "mail.sulkta.com"
imap_port = 993
imap_tls = true
username = "kayos@sulkta.com"
password_env = "KAYOS_SMTP_PASS"
password_file = "~/.config/kayos-mail/smtp.env"
# Optional: pin Message-ID domain. Defaults to the part of `from_addr`
# after the @ if unset.
# message_id_domain = "sulkta.com"