Skip to content
This repository was archived by the owner on Jul 19, 2026. It is now read-only.

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

local-mail-mcp

A tiny local MCP server that sends email by handing a message to your machine's local sendmail (Postfix on macOS). Postfix relays it onward through an authenticated SMTP relay you configure, so the MCP server itself holds no credentials. Handy for letting an MCP client (e.g. Claude Desktop) email you reports, digests, or notifications from your own machine without wiring a cloud email API.


⚠️ Status: unsupported, provided as-is

This is a personal project shared in case it's useful. It is not supported. I do not read or respond to issues, bug reports, feature requests, or pull requests, and this repository may be archived (read-only). Fork it and adapt it freely under the terms in LICENSE. You are on your own — especially for SMTP connectivity issues with any given provider.


Quick start

After the one-time prerequisites below (a ProtonMail SMTP token — step 1), a single command installs everything: the virtualenv, the Postfix relay, and the Claude Desktop registration.

python3 install.py all --from claudeapp@yourdomain --to you@personal.com

Use a Python 3.10+ interpreter (see prerequisites) — on macOS that means a Homebrew Python, e.g. python3.12 install.py all …, not the built-in 3.9.

You'll be prompted for the SMTP token (no echo), and for your password when it sudos the Postfix steps. Then fully quit and reopen Claude. Full details, options, and the individual steps are below.


Scope & prerequisites (read this first)

  • Relay provider: ProtonMail only (as written). These instructions are for relaying through ProtonMail's SMTP submission service. Other providers may work with adaptation (different host/port/credentials), but that is untested here.
  • A ProtonMail plan with a custom domain, already configured and verified in ProtonMail. ProtonMail's SMTP submission tokens require a paid plan and a custom domain set up in your account. See Proton's official guide: https://proton.me/support/smtp-submission
  • macOS. Tested on macOS 26.5.2; likely fine on most recent macOS versions. macOS ships Postfix, disabled by default — the installer below enables and configures it.
  • ⚠️ Python 3.10 or newer — the mcp package requires it. macOS's built-in python3 (Command Line Tools) is 3.9, which is too old, so install a newer one (brew install python) and launch the installer with it, e.g. python3.12 install.py …. The installer checks the version and stops with guidance if it's too old, then creates a virtualenv and installs mcp into it for you.

Step 1 — Create a ProtonMail SMTP token

  1. Log in to your dashboard at Proton Mail.
  2. Under Identity and addresses (left), configure a custom email address if needed (e.g. claudeapp@yourdomain).
  3. Select IMAP/SMTP (left). Scroll to the bottom. Create an SMTP token with the Generate token button. Associate it with your custom email address if you created one in step 2.
  4. Store the token in your password vault. It is displayed only once. If you lose it you must delete the token configuration and create a new one — there is no "refresh token" mechanism for the token alone.

Step 2 — Run the installer

install.py does the rest for you: creates the virtualenv and installs mcp, configures Postfix to relay through ProtonMail (and sends a test message), and registers the server in Claude Desktop's config — no hand-editing of shell scripts or JSON.

Run it as your normal user, not with sudo (it elevates only the Postfix commands itself). From inside this folder:

python3 install.py all --from claudeapp@yourdomain --to you@personal.com
  • --from is the custom-domain address tied to your token — it's both the SMTP username and the From: on your outgoing mail.
  • --to is where mail should go (the relay test target and your default recipient).
  • You are prompted for the SMTP token with no echo (or set it in the PROTONMAIL_SMTP_TOKEN environment variable). The token is never passed on the command line, so it can't leak via shell history or the process list.
  • The Postfix part uses sudo, so expect a password prompt there.

Add --dry-run to see exactly what it would do — every Postfix command and the config merge — without changing anything; the token is redacted in the preview.

Confirm the test message arrives before relying on it. If it doesn't, the relay is the thing to fix (check mailq and /var/log/mail.log) — the step most likely to need provider-specific troubleshooting, which is on you.

Finally, fully quit and reopen Claude (Cmd-Q on macOS) — MCP config is read only at startup — and the local_mail_send_email tool will be available.


Running the steps individually (optional)

install.py takes a subcommand if you'd rather do one piece at a time; each accepts the same --from / --to / --dry-run flags:

python3 install.py venv       # create ./.venv and install mcp
python3 install.py relay      # configure Postfix -> ProtonMail + test send
python3 install.py register   # merge the local-mail entry into Claude's config

register finds claude_desktop_config.json for your OS, backs it up, and merges at the correct nesting level without disturbing other servers; it refuses to write if the file isn't valid JSON. Override the path with --config.

Manual config edit (what register writes)

Prefer to edit by hand? Open Settings → Developer → Edit Config in Claude Desktop (it creates ~/Library/Application Support/Claude/claude_desktop_config.json if missing) and merge this under mcpServers, minding the nesting:

{
  "mcpServers": {
    "local-mail": {
      "command": "/path/to/local-mail-mcp/.venv/bin/python",
      "args": ["/path/to/local-mail-mcp/local_mail_mcp.py"],
      "env": {
        "LOCAL_MAIL_FROM": "claudeapp@yourdomain",
        "LOCAL_MAIL_DEFAULT_TO": "you@personal.com"
      }
    }
  }
}

The Settings → Connectors page is only for remote (URL) connectors and can't launch a local process — that's why local servers live in the config file. Any MCP client that speaks stdio can run this one: just launch python local_mail_mcp.py as the server command.


The tool: local_mail_send_email

field type notes
to string[] recipients; falls back to LOCAL_MAIL_DEFAULT_TO
subject string required
body_text string required; plain-text (and fallback for HTML)
body_html string? optional; makes it multipart/alternative
from_addr string? falls back to LOCAL_MAIL_FROM; must be a relay-allowed address
cc string[] optional
attachments string[] absolute file paths
dry_run bool build & return the message without sending

Environment variables

  • LOCAL_MAIL_SENDMAIL — path to sendmail (default /usr/sbin/sendmail)
  • LOCAL_MAIL_FROM — default From address (no built-in default)
  • LOCAL_MAIL_DEFAULT_TO — default recipient

Tip: set dry_run: true to preview the exact RFC-5322 message without sending.


Security notes

  • No secret in the server. The relay token lives in Postfix (/etc/postfix/sasl_passwd, mode 600). Rotating it is a Postfix-only change.
  • The tool invokes a fixed binary path with an argument list (no shell string interpolation) and validates recipient/sender addresses before building the message.
  • You are responsible for securing your own relay, token, and machine.

License

MIT. Do whatever you like; no warranty, no liability, no support.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages