Experimental — please test and report issues.
Email bridge for MulmoClaude. Polls an IMAP mailbox for unread mail and replies via SMTP preserving threading (In-Reply-To + References). Outbound-only — no public URL needed.
Good for async / slow workflows where you don't need instant replies: delegate tasks by email, get structured results back in your inbox.
Any IMAP+SMTP-capable mailbox works. A dedicated mailbox is strongly recommended — the bridge marks messages as \Seen after processing.
- Gmail — create an app password (requires 2FA). Use
imap.gmail.com:993/smtp.gmail.com:465(TLS) or587(STARTTLS). - Fastmail / iCloud / Outlook — similarly, prefer app passwords.
- Self-hosted (Postfix + Dovecot, mailcow, Stalwart) — use your regular credentials.
EMAIL_IMAP_HOST=imap.gmail.com \
EMAIL_IMAP_USER=mulmobot@gmail.com \
EMAIL_IMAP_PASSWORD=your-app-password \
EMAIL_SMTP_HOST=smtp.gmail.com \
EMAIL_SMTP_USER=mulmobot@gmail.com \
EMAIL_SMTP_PASSWORD=your-app-password \
EMAIL_FROM=mulmobot@gmail.com \
npx @mulmobridge/emailSend an email to the bot address — you'll get a reply threaded under your original message.
| Variable | Required | Default | Description |
|---|---|---|---|
EMAIL_IMAP_HOST |
yes | — | IMAP server hostname |
EMAIL_IMAP_USER |
yes | — | IMAP username |
EMAIL_IMAP_PASSWORD |
yes | — | IMAP password (use an app password for Gmail / Fastmail) |
EMAIL_IMAP_PORT |
no | 993 |
IMAP port |
EMAIL_IMAP_TLS |
no | true |
Use implicit TLS (false for plain + STARTTLS) |
EMAIL_SMTP_HOST |
yes | — | SMTP server hostname |
EMAIL_SMTP_USER |
yes | — | SMTP username |
EMAIL_SMTP_PASSWORD |
yes | — | SMTP password |
EMAIL_SMTP_PORT |
no | 587 |
SMTP port |
EMAIL_SMTP_TLS |
no | auto | true for implicit TLS (465), false for STARTTLS (587). Auto-detected from port if unset |
EMAIL_FROM |
yes | — | Bot's email address (usually equal to EMAIL_SMTP_USER) |
EMAIL_ALLOWED_SENDERS |
no | (all) | CSV of allowed sender addresses (case-insensitive) |
EMAIL_POLL_INTERVAL_SEC |
no | 30 |
Poll interval in seconds (min 10) |
MULMOCLAUDE_AUTH_TOKEN |
no | auto | MulmoClaude bearer token override |
MULMOCLAUDE_API_URL |
no | http://localhost:3001 |
MulmoClaude server URL |
The MulmoClaude server regenerates a fresh bearer token on every startup and writes it to ~/mulmoclaude/.session-token. The bridge reads that file once at launch and keeps the token in memory — so if the server restarts while the bridge is running, the bridge keeps using the old token and every API call returns 401, silently.
Fix: set MULMOCLAUDE_AUTH_TOKEN to the same long random value on both the server and the bridge. The server uses it verbatim instead of regenerating, so the token survives restarts and the bridge stays authenticated.
# Server (one-time setup — same value across restarts)
MULMOCLAUDE_AUTH_TOKEN=long-random-string yarn dev
# Bridge (separate process / machine — same value)
MULMOCLAUDE_AUTH_TOKEN=long-random-string \
<bridge-specific-envs> \
npx <this-package>@latestRecommended: at least 32 characters of random data (the server logs a warning at startup for shorter values).
- At startup, the bridge logs into IMAP via
imapflowand enters a poll loop onINBOX. - Every
EMAIL_POLL_INTERVAL_SEC,SEARCH UNSEENreturns new messages. Each is fetched, parsed withmailparser, and (after allowlist check) forwarded to MulmoClaude keyed by the sender's address. - The reply goes out via
nodemailerwithIn-Reply-To= originalMessage-IDandReferences= full thread chain, so mail clients render it as a proper thread reply. - Processed messages are flagged
\Seenso they aren't re-processed on restart.
| Symptom | Cause | Fix |
|---|---|---|
NO Invalid credentials |
Using raw password on Gmail / Fastmail | Create an app password with IMAP + SMTP scopes |
| Replies end up in recipient's Spam | Lack of SPF / DKIM on the bot domain | Send from a provider that already signs (Gmail, Fastmail, etc.) or set up DKIM on your own server |
| Reply not threaded in the sender's client | Client ignored References |
Some corporate clients strip threading headers — not fixable bridge-side |
| Mail loop (bridge replies to its own replies) | The bridge's own From address is in EMAIL_ALLOWED_SENDERS |
Remove it, or use a separate address for the bot |
- Use a dedicated bot mailbox. Revocation of the app password then won't affect your personal mail.
- The IMAP password is read-write — the bridge can delete mail if compromised. Store it via a secret manager, not plain env.
- Allowlist via
EMAIL_ALLOWED_SENDERSis strongly recommended. Without it, anyone who emails the bot can converse with your MulmoClaude, and spam is a real risk. - Replies include the bot's response text in plain email. Don't bridge sensitive content unless both mailboxes are under your control.
- Attachments are not processed in v0.1.0 — image / PDF forwarding may land in a follow-up.
Part of the @mulmobridge/* package family.
Shared libraries:
@mulmobridge/client— socket.io client library used by every bridge below@mulmobridge/protocol— wire types and constants@mulmobridge/chat-service— server-side relay + session store@mulmobridge/relay— Cloudflare Workers webhook proxy@mulmobridge/mock-server— mock server for local bridge development
Bridges (one npm package per platform):
@mulmobridge/bluesky— Bluesky DMs over atproto@mulmobridge/chatwork— Chatwork (Japanese business chat)@mulmobridge/cli— interactive terminal bridge@mulmobridge/discord— Discord bot via Gateway@mulmobridge/email— IMAP poll + SMTP reply, threading preserved ← this package@mulmobridge/google-chat— Google Chat via MulmoBridge relay@mulmobridge/irc— IRC (Libera, Freenode, custom)@mulmobridge/line— LINE Messaging API via MulmoBridge relay@mulmobridge/line-works— LINE Works (enterprise LINE)@mulmobridge/mastodon— Mastodon DMs + mentions@mulmobridge/matrix— Matrix / Element@mulmobridge/mattermost— Mattermost@mulmobridge/messenger— Facebook Messenger via MulmoBridge relay@mulmobridge/nostr— Nostr NIP-04 encrypted DMs@mulmobridge/rocketchat— Rocket.Chat@mulmobridge/signal— Signal via signal-cli-rest-api@mulmobridge/slack— Slack Socket Mode@mulmobridge/teams— Microsoft Teams via Bot Framework@mulmobridge/telegram— Telegram bot@mulmobridge/twilio-sms— SMS via Twilio Programmable Messaging@mulmobridge/viber— Viber Public Account bots@mulmobridge/webhook— generic HTTP webhook bridge@mulmobridge/whatsapp— WhatsApp Cloud API via MulmoBridge relay@mulmobridge/xmpp— XMPP / Jabber@mulmobridge/zulip— Zulip
Published from the MulmoClaude monorepo by Receptron.
- MulmoClaude — an open-source AI assistant platform that runs on your own computer. Claude Code as the engine, a personal wiki for long-term memory, schema-driven collections for your data, and chat that summons the right GUI (markdown, charts, forms, spreadsheets, wikis) for each task.
- MulmoTerminal — a terminal-first cockpit for running many AI coding agents in parallel. One roster showing every session's summary and PR status, tmux-backed session persistence, git-worktree isolation, one-click PRs, and mobile push with remote reply.
- MulmoTerminal manual — setup, workflows, feature reference, configuration, mobile notifications, and alternative / local model providers. Available in English and Japanese.