Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .agents/plugins/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"plugins": [
{
"name": "apple-mail",
"version": "2.10.2",
"version": "2.10.3",
"source": {
"source": "local",
"path": "./codex"
Expand Down
4 changes: 2 additions & 2 deletions .antigravity-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"name": "apple-mail-mcp",
"metadata": {
"description": "Apple Mail integration marketplace for Claude Code, Codex, Hermes, and Antigravity.",
"description": "Apple Mail integration marketplace for Claude Code, Codex, and Antigravity.",
"version": "1.0.0"
},
"plugins": [
{
"name": "apple-mail",
"version": "2.10.2",
"version": "2.10.3",
"description": "Manage Apple Mail through natural language - read, search, send, reply, forward, and organize emails and mailboxes, with diagnostics, attachments, templates, and mail-merge support (macOS only).",
"source": {
"source": "local",
Expand Down
2 changes: 1 addition & 1 deletion .antigravity-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "apple-mail",
"version": "2.10.2",
"version": "2.10.3",
"description": "Manage Apple Mail through natural language - read, search, send, reply, forward, and organize emails and mailboxes, with diagnostics, attachments, templates, and mail-merge support (macOS only).",
"author": {
"name": "Rob Sweet",
Expand Down
21 changes: 20 additions & 1 deletion .antigravity-plugin/skills/apple-mail/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Use this skill when the user:
| `unflag-message` | Remove flag from a message |
| `delete-message` | Move a message to Trash |
| `move-message` | Move a message to a different mailbox |
| `resolve-message-id` | Convert `imap:` ids to numeric Mail.app ids (needed for flag colors) |
| `resolve-message-id` | Convert `imap:` ids to numeric Mail.app ids needed **only** for `reply-to-message` / `forward-message`, which are numeric-id only. **Not** for flag colors: since 2.10.0 `flag-message`/`batch-flag-messages` write the color over IMAP directly |
| `list-attachments` | List a message's attachments (name, MIME type, size) |
| `save-attachment` | Save an attachment to disk |
| `fetch-attachment` | Fetch an attachment's bytes inline as base64 |
Expand Down Expand Up @@ -74,6 +74,25 @@ Use this skill when the user:
|------|---------|
| `list-accounts` | List configured email accounts |

### Smart Mailbox Operations

Smart mailboxes are **criteria-based virtual views**, not real folders — use these
when the user wants a saved filter/search rather than moving mail. They work on
localized macOS because they edit `SyncedSmartMailboxes.plist` directly (backed up
and atomic; existing smart mailboxes are never rewritten).

| Tool | Purpose |
|------|---------|
| `list-smart-mailboxes` | List smart mailboxes and their criteria |
| `create-smart-mailbox` | Create one (needs at least one of fromContains / subjectContains / bodyContains) |
| `delete-smart-mailbox` | Delete one by name |
| `create-newsletter-smart-mailboxes` | Propose "NL: <sender>" views for newsletter senders — **defaults to `dryRun: true`**; pass `dryRun: false` to actually create them |

Requires Full Disk Access for the Node runtime (`~/Library/Mail` is TCC-protected);
without it these report "no smart mailboxes" rather than a permission error.
Changes appear the next time Mail is launched — **have the user quit Mail first**
for reliable results. These tools never quit or restart Mail themselves.

### Rules

| Tool | Purpose |
Expand Down
4 changes: 2 additions & 2 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://anthropic.com/claude-code/marketplace.schema.json",
"name": "apple-mail-mcp",
"version": "2.10.2",
"version": "2.10.3",
"description": "Apple Mail integration for Claude Code and Codex via MCP",
"owner": {
"name": "Rob Sweet",
Expand All @@ -12,7 +12,7 @@
"name": "apple-mail",
"displayName": "Apple Mail",
"description": "Manage Apple Mail through natural language - read, search, send, and organize emails (macOS only)",
"version": "2.10.2",
"version": "2.10.3",
"author": {
"name": "Rob Sweet",
"email": "rob@superiortech.io"
Expand Down
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "apple-mail",
"version": "2.10.2",
"version": "2.10.3",
"description": "Manage Apple Mail through natural language - read, search, send, and organize emails (macOS only)",
"author": {
"name": "Rob Sweet",
Expand Down
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,19 @@
### Security
- **Moved both dev-only `brace-expansion` paths onto their complete fixes for GHSA-mh99-v99m-4gvg / CVE-2026-14257 (high)** — `1.1.18` on the v1 line and `5.0.9` on the v5 line. The two majors are floored independently because they are not API-compatible: ESLint reaches `brace-expansion` through `minimatch@3.1.5`, which requires the v1 CommonJS API, so forcing the v5 line the advisory names as patched into that path fails with `expand is not a function`; the upstream v1 backport is the only fix that applies without crossing that boundary. `minimatch@10.2.6` reaches the v5 line independently. Both floors are written as two-sided ranges (`>=1.0.0 <1.1.18`, `>=5.0.0 <5.0.9`) — a bare `<5.0.9` also matches `1.1.18` under semver and would drag the CommonJS path onto v5. The advisory's own first-patched versions (`1.1.17` / `5.0.8`) are **not sufficient**: they bound the accumulator in `combine` but never thread `maxLength` into `expandSequence`, leaving the sequence path (`{1..N}`, `{a..z..k}`) capped only by item count, so a padded sequence still materialises ~100,000 intermediate strings before the outer bound truncates (measured 4,606 ms / 176 MB RSS on `1.1.17` vs 9 ms / 61 MB on `1.1.18`, identical final output). `1.1.18` and `5.0.9` add the missing bound. Both were adopted only after clearing this repo's 24-hour `minimumReleaseAge` supply-chain gate, with no `minimumReleaseAgeExclude` carve-out and no audit suppression — `pnpm audit` will keep reporting the advisory until GitHub's metadata (which still lists `5.0.8` as first-patched, and so marks the entire v1 line vulnerable under semver) catches up. Dev toolchain only: `brace-expansion` is not in the shipped bundle, so the published package is unaffected, the committed bundle is byte-identical, and no version bump is owed. Thanks to @jjoanna2-debug (#119, #121, #123).

## [2.10.3] - 2026-08-03

### Fixed
- **`search-contacts` now returns the phone numbers it has always claimed to return.** The tool description promised phones twice ("find their email address(es)/phone(s)" and "Returns: … and phone numbers"), as did the README and `CLAUDE.md` — four claims, zero code paths. `contactsDb` was already reading phones in the same query that reads emails, and the handler discarded them one line before serialization, from both the rendered text and `structuredContent`. An agent asked to look up someone's number got a result with no phone and could only conclude the contact had none on file. Phones now appear in both projections; the query is unchanged, so this costs nothing.
- **Two setup-failure errors gained the mandated docs URL + `doctor` pointer** — the IMAP Keychain-password failure and the server-side mailbox refusal both explained the problem without telling the user where to go next.

### Documentation
- **Reconciled 22 verified claims against the live 50-tool surface.** The valuable class is docs the code disproves: the README documented a `search-contacts` `limit` (default 10) that does not exist and never truncated anything, so a complete result set reads as clipped; it said `get-unread-count` with no `mailbox` returns a cross-mailbox total, which 2.8.15 deliberately changed to INBOX-only because summing double-counted on Gmail; it listed `fetch-attachment` as numeric-id only when the schema accepts `imap:` ids; and **Known Limitations still said "No smart mailboxes" while the same README documents the four smart-mailbox tools shipped in 2.9.0**.
- **`skills/apple-mail/SKILL.md` still told agents `resolve-message-id` is "needed for flag colors"** — the eighth surviving copy of the text 2.10.1 corrected everywhere else, and the most consequential one, since an agent planning from the skill's tool table would resolve `imap:` ids purely to color a flag and reintroduce the AppleScript/TCC dependency 2.10.0 removed. The skill also had no smart-mailbox section at all; one was added (noting `create-newsletter-smart-mailboxes` defaults to `dryRun: true`). Edited at the canonical root `skills/` only, then `pnpm run sync:skills`.
- **Documented what was only true in the code:** `get-message`'s `mailbox`/`account` parameters (the documented cure for large-folder timeouts, previously undiscoverable), `get-mail-stats`'s `account` scope, `flagColorIndex` as the way to *read* a flag color, and the fact that `search-contacts` needs **Node 22.5+** (`node:sqlite`) and Full Disk Access — returning an **empty list rather than an error** without them, so "no contacts found" could mean "cannot read Contacts". Smart-mailbox tools likewise need Full Disk Access and reported every read failure as "no smart mailboxes".
- **Removed obsolete guidance:** `docs/IMAP-SETUP.md` still taught the pre-2.6.0 rule that reads require a matching `account` argument to route to IMAP (since 2.6.0 they prefer IMAP automatically and fan out across configured accounts); the Development block told contributors to run `npm install`, which `package.json`'s own `preinstall` guard hard-fails; `SECURITY.md` described a numeric-only message-id regex superseded by `imap:` ids; and the Antigravity marketplace still advertised the removed Hermes packaging.
- **Corrected the privacy claim in `SECURITY.md` and the README.** Both said no data is sent to external servers. That is false once the opt-in IMAP/SMTP backends are configured — they connect to your provider, which is their purpose. Reframed as no **third** parties: nothing goes to this project or anyone else, everything stays on-device with the default AppleScript backend.

## [2.10.2] - 2026-08-03

### Security
Expand Down
Loading