Module: Mailmate::CLI::Send Private
Overview
This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.
mm-send — send mail through MailMate's emate CLI with a markdown body.
Replaces the 6-line bash wrapper that previously lived at
~/.claude/skills/email/send-email. All flags pass through to emate mailto; --markup markdown is enforced.
Constant Summary collapse
- EMATE_PATH =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
"/Applications/MailMate.app/Contents/Resources/emate"- PREAMBLE =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
<<~PREAMBLE mm-send — thin wrapper around `emate mailto` with `--markup markdown` enforced. Body is read from stdin. All other flags pass through to emate (its help follows). Replies and threading MailMate auto-generates the outgoing Message-ID — never your job. In-Reply-To and References are PURE PASS-THROUGH: whatever you set via `--header` ships verbatim; what you don't set is absent (and recipients' clients will see the message as a fresh thread, no matter how `Re:` the subject looks). To make a reply land in-thread, pass both: mm-send -f you@x -t them@y -s "Re: foo" \\ --header "In-Reply-To: <parent-message-id@domain>" \\ --header "References: <root-mid> <parent-mid>" \\ --send-now <<<"body" References is constructed as the source message's References header (if any) with the source's Message-ID appended. If the source is a thread root with no References, just use its Message-ID alone. Identity selection `-f <address>` picks which of MailMate's configured identities sends. Without `-f`, MailMate uses its default identity. See `mmdiscover` to list available addresses. ──────────────────────────── emate help follows ──────────────────────────── PREAMBLE
Instance Method Summary collapse
-
#run(argv) ⇒ Object
private
Returns the exit status of the spawned
emateinvocation.
Instance Method Details
#run(argv) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns the exit status of the spawned emate invocation.
emate must NEVER inherit the caller's real stdin/stdout. Inside the
MCP server, fd 0/1 are the JSON-RPC transport, and the previous
system(...) handed both to emate: it blocked reading the protocol
pipe for a body and consumed the next frame as one (a cancelled turn
produced a MailMate draft whose entire body was a
notifications/cancelled frame — the composed body, swapped in via
the Ruby-level $stdin global, was silently discarded). So: read the
body through $stdin (honors the MCP's StringIO swap AND a shell
pipe), hand it to emate on a private pipe that capture3 EOFs (no
more hanging until the server dies), and re-emit emate's output
through the $stdout/$stderr globals so the MCP's capture sees it
instead of the protocol stream getting corrupted.
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/mailmate/cli/send.rb', line 60 def run(argv) Mailmate::PlatformError.check_darwin!(component: "mm-send") unless File.executable?(EMATE_PATH) warn "mm-send: emate not found at #{EMATE_PATH}. Is MailMate installed?" return 1 end help = argv.include?("--help") || argv.include?("-h") warn PREAMBLE if help # --help never reads a body; consuming stdin here would hang an # interactive `mm-send --help` waiting for Ctrl-D. body = help ? "" : $stdin.read.to_s out, err, status = Open3.capture3(EMATE_PATH, "mailto", "--markup", "markdown", *argv, stdin_data: body) $stdout.write(out) $stderr.write(err) # exitstatus is nil for a signal-killed child; the exe shims do # `exit run(ARGV)`, which needs an Integer. status.exitstatus || 1 end |