mailmate 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +73 -17
- data/lib/mailmate/cli/message.rb +9 -2
- data/lib/mailmate/cli/search.rb +1 -1
- data/lib/mailmate/version.rb +1 -1
- metadata +12 -12
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5e25504c9cfa00a8d2c0c94e387b593c9151a66981150c17e1fbd328d531707d
|
|
4
|
+
data.tar.gz: 4f0ac4ca053f30eed50305e2f333e9969871bbf02565115c2a72dacb0072c023
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8953a409f2855ca1b04a1f4c574c73c4a724e29398d5a5951423b61fd0313f06a21242581219d14f1de3c28436d777f09ee1289f5cb69ca02deeb70bedb8a5ef
|
|
7
|
+
data.tar.gz: b4dc5f74fa58a58c592ce125c2e42dce062ebbeb841284d74c878e12c6202856f2624f2da4adba6bc24a2919d150a1b8f5b54c302fd71507d1c9085d6d5e4c35
|
data/README.md
CHANGED
|
@@ -148,54 +148,110 @@ The `mm` prefix is for tab completion: typing `mm<tab>` in a shell lists every c
|
|
|
148
148
|
|
|
149
149
|
A few rough edges to be aware of:
|
|
150
150
|
|
|
151
|
-
1. **
|
|
152
|
-
|
|
153
|
-
Body queries (`b <term>`, a bare term that falls through to `:message_or_body`, or explicit `m <term>` without `--headers-only`) check MailMate's `#unquoted` and `#quoted` body indexes. **Default behavior matches MailMate's UI body search** — only messages MailMate has body-indexed are searched. Sub-second on any archive size; the catch is that MailMate populates those indexes lazily (typically when you view or search messages in its UI), so a search may miss content in messages MailMate hasn't yet indexed. Coverage varies by user: a fresh install has a handful indexed; a heavy MailMate-search user has most.
|
|
154
|
-
|
|
155
|
-
Pass `--all` to fall back to reading and parsing the `.eml` on disk for messages without an index record. This finds everything but takes tens of seconds to minutes on large archives. Use `--all` when you need an exhaustive answer; stick with the default when you want a predictable-fast one.
|
|
156
|
-
|
|
157
|
-
2. **Non-move `mm-modify` actions still take over the UI.** Same-account `move` actions use a fast path — a direct `.eml` rename on disk — so they're silent and don't activate MailMate. Everything else (`read`, `flag`, `tag`, `archive`, `junk`, `delete`, etc.) still drives MailMate's UI: each invocation opens a message-viewer window via the `mid:` URL, runs AppleScript key-binding selectors against it, then closes the window. Two consequences:
|
|
151
|
+
1. **Non-move `mm-modify` actions still take over the UI.** Same-account `move` actions use a fast path — a direct `.eml` rename on disk — so they're silent and don't activate MailMate. Everything else (`read`, `flag`, `tag`, `archive`, `junk`, `delete`, etc.) still drives MailMate's UI: each invocation opens a message-viewer window via the `mid:` URL, runs AppleScript key-binding selectors against it, then closes the window. Two consequences:
|
|
158
152
|
- **Focus is stolen.** When the `mid:` URL fires, macOS brings MailMate forward and the spawned message-viewer window takes keyboard focus. Anything you were typing into another app goes to MailMate instead.
|
|
159
153
|
- **The close at the end can close the wrong window.** `mm-modify` ends by sending the standard "close window" keystroke. If focus has drifted (or another app's window has come forward in the meantime), that keystroke lands on **your** window — your editor, your browser tab — not MailMate's viewer.
|
|
160
154
|
|
|
161
155
|
For one-off changes this is just annoying; for a loop of hundreds of messages it makes the machine unusable while it runs. Batch multiple actions into one `mm-modify` invocation when you can — they share a single open/close cycle (or skip it entirely for pure-move). The `--keep-window` flag avoids the close-keystroke entirely if you don't mind cleaning up viewers manually.
|
|
162
156
|
|
|
163
|
-
|
|
157
|
+
2. **`eml-id` is machine-local; prefer `Message-ID:`.** The integer eml-id (also shown as MailMate's "Msg ID" column) is just the filename of the `.eml` on disk and differs on every install — copy/pasting an eml-id from your desktop to your laptop will refer to a different message (or none at all). For anything you want to keep, store the RFC `Message-ID:` header (which `mmmessage` prints) and pass that to the CLIs. The `mid:%3C<message-id>%3E` URL scheme works portably for the same reason.
|
|
164
158
|
|
|
165
|
-
|
|
159
|
+
3. **MailMate must be running.** Anything that goes through `mm-modify` requires MailMate open and unblocked by modal dialogs. `mm-send` likewise needs MailMate running — `emate mailto` opens a draft window in the running MailMate process, so without MailMate up there's nowhere for the draft to land (this is true with or without `--send-now`). Headless / unattended use isn't supported.
|
|
166
160
|
|
|
167
|
-
|
|
161
|
+
4. **Single-account `mm-send` defaults.** `mm-send` passes flags straight through to `emate mailto`. If you have multiple identities configured in MailMate and don't pass `-f`, MailMate picks the default identity — there's no opinionated multi-account routing in the wrapper.
|
|
168
162
|
|
|
169
163
|
## Status
|
|
170
164
|
|
|
171
|
-
|
|
165
|
+
1.1.0 — `reverse_markdown` (and its transitive `nokogiri` dep) is now opt-in rather than auto-installed. Run `gem install reverse_markdown` if you want `mmmessage --markdown`; everything else is unchanged.
|
|
166
|
+
|
|
167
|
+
1.0.0 — initial public release; API stable from this point. Breaking changes bump the major version going forward.
|
|
172
168
|
|
|
173
169
|
## Install
|
|
174
170
|
|
|
171
|
+
### Requirements
|
|
172
|
+
|
|
173
|
+
- **macOS** with **MailMate** installed (and running, for any command that drives the UI or sends mail).
|
|
174
|
+
- **Ruby ≥ 3.0**.
|
|
175
|
+
- No third-party CLI tools — the gem only shells out to macOS-bundled `plutil`, `osascript`, and `open`, plus MailMate's bundled `emate`.
|
|
176
|
+
|
|
175
177
|
```bash
|
|
176
178
|
gem install mailmate
|
|
177
179
|
```
|
|
178
180
|
|
|
179
|
-
Then bootstrap your config:
|
|
181
|
+
Then optionally bootstrap your config (will happen automatically on first invocation of any command from an interactive shell if it hasn't been run before):
|
|
180
182
|
|
|
181
183
|
```bash
|
|
182
184
|
mmdiscover
|
|
183
185
|
```
|
|
184
186
|
|
|
185
|
-
`mmdiscover` reads MailMate's `Sources.plist` and `Identities.plist`, shows you the accounts and addresses it found, and offers to write `~/.config/mailmate/config.yml` from them. It also writes `~/.config/mailmate/bundle_loader.rb` for MailMate bundles.
|
|
187
|
+
`mmdiscover` reads MailMate's `Sources.plist` and `Identities.plist`, shows you the accounts and addresses it found, and offers to write `~/.config/mailmate/config.yml` from them. It also writes `~/.config/mailmate/bundle_loader.rb` for MailMate bundles. Running it explicitly is only needed in non-TTY contexts (cron jobs, MCP servers) — there, the gem falls back to built-in defaults and warns once.
|
|
188
|
+
|
|
189
|
+
### Optional: `mmmessage --markdown`
|
|
190
|
+
|
|
191
|
+
**On the vast majority of Ruby setups (stock `arm64-darwin` or `x86_64-darwin` Ruby) this step is a no-op — nokogiri ships a precompiled binary, you can skip the rest of this section and move on.** Keep reading only if your `gem install` actually fails.
|
|
192
|
+
|
|
193
|
+
`mmmessage --markdown` renders HTML-only message bodies as readable markdown. It needs the `reverse_markdown` gem, which has `nokogiri` as a transitive dependency:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
gem install reverse_markdown
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
That single command pulls `nokogiri` in automatically — no separate `gem install nokogiri` step. This is kept out of the base install because nokogiri ships a native extension. On Ruby/platform combinations without a precompiled match nokogiri falls back to compiling from source — it vendors its own libxml2/libxslt, but it does need a C compiler, which on macOS means Xcode Command Line Tools (`xcode-select --install`). If `gem install reverse_markdown` fails, that's almost certainly the cause.
|
|
200
|
+
|
|
201
|
+
If you never use `--markdown`, you never pay any of this. If you do invoke `--markdown` without the gem already being installed (default on most Ruby versions), `mmmessage` exits with a clear install hint.
|
|
186
202
|
|
|
187
203
|
### From source (development)
|
|
188
204
|
|
|
189
|
-
If you're hacking on the gem itself, skip `gem install` and put the repo's `exe/` on your `PATH
|
|
205
|
+
If you're hacking on the gem itself, skip `gem install` and put the repo's `exe/` on your `PATH`. Clone wherever you keep source repos, then prepend its `exe/` to `PATH` from your shell's rc file (`~/.zshrc`, `~/.bashrc`, etc.):
|
|
190
206
|
|
|
191
207
|
```bash
|
|
192
|
-
git clone
|
|
193
|
-
|
|
194
|
-
|
|
208
|
+
git clone https://github.com/brianmd/mailmate.git
|
|
209
|
+
cd mailmate
|
|
210
|
+
|
|
211
|
+
# In your shell rc file, add (adjust the path to wherever you cloned):
|
|
212
|
+
# export PATH="/absolute/path/to/mailmate/exe:$PATH"
|
|
213
|
+
# Then reload the shell (open a new tab, or `source` the rc file).
|
|
195
214
|
```
|
|
196
215
|
|
|
197
216
|
Then `mmdiscover` as above.
|
|
198
217
|
|
|
218
|
+
### MCP server
|
|
219
|
+
|
|
220
|
+
The gem also ships an MCP server (`exe/mailmate-mcp`) that exposes the same surface to AI assistants as JSON-RPC tools: `search`, `message`, `modify`, `send`, `open`, `list_mailboxes`, `list_tags`, `resolve_id`. After `gem install mailmate`, `mailmate-mcp` is on your `PATH`.
|
|
221
|
+
|
|
222
|
+
#### Claude Code (global, all projects)
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
claude mcp add --scope user mailmate "$(which mailmate-mcp)"
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Or add manually to `~/.claude.json` under `"mcpServers"`:
|
|
229
|
+
|
|
230
|
+
```json
|
|
231
|
+
"mailmate": {
|
|
232
|
+
"type": "stdio",
|
|
233
|
+
"command": "/absolute/path/to/mailmate-mcp",
|
|
234
|
+
"args": [],
|
|
235
|
+
"env": {}
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
#### Claude Desktop
|
|
240
|
+
|
|
241
|
+
Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
|
|
242
|
+
|
|
243
|
+
```json
|
|
244
|
+
{
|
|
245
|
+
"mcpServers": {
|
|
246
|
+
"mailmate": {
|
|
247
|
+
"command": "/absolute/path/to/mailmate-mcp"
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Restart Claude Desktop after any change to server code or config.
|
|
254
|
+
|
|
199
255
|
## Commands
|
|
200
256
|
|
|
201
257
|
| Command | What it does |
|
data/lib/mailmate/cli/message.rb
CHANGED
|
@@ -137,8 +137,15 @@ module Mailmate
|
|
|
137
137
|
# long runs of `͏ ` in the output.
|
|
138
138
|
# 3. Collapse 3+ consecutive blank lines into a single blank line.
|
|
139
139
|
def html_to_markdown(html)
|
|
140
|
-
|
|
141
|
-
|
|
140
|
+
begin
|
|
141
|
+
require "nokogiri"
|
|
142
|
+
require "reverse_markdown"
|
|
143
|
+
rescue LoadError => e
|
|
144
|
+
warn "mmmessage --markdown needs the reverse_markdown gem (which pulls nokogiri)."
|
|
145
|
+
warn "Install it with: gem install reverse_markdown"
|
|
146
|
+
warn "(underlying: #{e.message})"
|
|
147
|
+
exit 3
|
|
148
|
+
end
|
|
142
149
|
doc = Nokogiri::HTML(html)
|
|
143
150
|
doc.css("style, script").remove
|
|
144
151
|
md = ReverseMarkdown.convert(doc.to_html)
|
data/lib/mailmate/cli/search.rb
CHANGED
|
@@ -200,7 +200,7 @@ module Mailmate
|
|
|
200
200
|
o.separator " c <term> cc contains"
|
|
201
201
|
o.separator " s <term> subject contains"
|
|
202
202
|
o.separator " a <term> any address header contains"
|
|
203
|
-
o.separator " b <term> body contains (
|
|
203
|
+
o.separator " b <term> body contains (reads MailMate's body indexes; --all for un-indexed too)"
|
|
204
204
|
o.separator " m <term> common headers OR body (same as bare term)"
|
|
205
205
|
o.separator " d <date> received date: Nd|Nw|Nm|Ny (relative), or Y, Y-M, Y-M-D"
|
|
206
206
|
o.separator " T <tag> tag / IMAP keyword contains (K is a synonym)"
|
data/lib/mailmate/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mailmate
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Brian Murphy-Dye
|
|
@@ -38,47 +38,47 @@ dependencies:
|
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
39
|
version: '3.0'
|
|
40
40
|
- !ruby/object:Gem::Dependency
|
|
41
|
-
name:
|
|
41
|
+
name: minitest
|
|
42
42
|
requirement: !ruby/object:Gem::Requirement
|
|
43
43
|
requirements:
|
|
44
44
|
- - "~>"
|
|
45
45
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: '
|
|
47
|
-
type: :
|
|
46
|
+
version: '5.0'
|
|
47
|
+
type: :development
|
|
48
48
|
prerelease: false
|
|
49
49
|
version_requirements: !ruby/object:Gem::Requirement
|
|
50
50
|
requirements:
|
|
51
51
|
- - "~>"
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: '
|
|
53
|
+
version: '5.0'
|
|
54
54
|
- !ruby/object:Gem::Dependency
|
|
55
|
-
name:
|
|
55
|
+
name: rake
|
|
56
56
|
requirement: !ruby/object:Gem::Requirement
|
|
57
57
|
requirements:
|
|
58
58
|
- - "~>"
|
|
59
59
|
- !ruby/object:Gem::Version
|
|
60
|
-
version: '
|
|
60
|
+
version: '13.0'
|
|
61
61
|
type: :development
|
|
62
62
|
prerelease: false
|
|
63
63
|
version_requirements: !ruby/object:Gem::Requirement
|
|
64
64
|
requirements:
|
|
65
65
|
- - "~>"
|
|
66
66
|
- !ruby/object:Gem::Version
|
|
67
|
-
version: '
|
|
67
|
+
version: '13.0'
|
|
68
68
|
- !ruby/object:Gem::Dependency
|
|
69
|
-
name:
|
|
69
|
+
name: reverse_markdown
|
|
70
70
|
requirement: !ruby/object:Gem::Requirement
|
|
71
71
|
requirements:
|
|
72
72
|
- - "~>"
|
|
73
73
|
- !ruby/object:Gem::Version
|
|
74
|
-
version: '
|
|
74
|
+
version: '3.0'
|
|
75
75
|
type: :development
|
|
76
76
|
prerelease: false
|
|
77
77
|
version_requirements: !ruby/object:Gem::Requirement
|
|
78
78
|
requirements:
|
|
79
79
|
- - "~>"
|
|
80
80
|
- !ruby/object:Gem::Version
|
|
81
|
-
version: '
|
|
81
|
+
version: '3.0'
|
|
82
82
|
description: |
|
|
83
83
|
mailmate is a Ruby library and CLI for working with MailMate's on-disk
|
|
84
84
|
storage and AppleScript surface. It includes a smart-mailbox filter
|
|
@@ -166,7 +166,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
166
166
|
- !ruby/object:Gem::Version
|
|
167
167
|
version: '0'
|
|
168
168
|
requirements: []
|
|
169
|
-
rubygems_version:
|
|
169
|
+
rubygems_version: 3.6.9
|
|
170
170
|
specification_version: 4
|
|
171
171
|
summary: Ruby toolkit for MailMate on macOS — search, read, modify, send, and smart-mailbox
|
|
172
172
|
evaluation
|