# Reported issues for Apple Mail MCP by imdinu

Pod holds 20 of 77 GitHub reports that passed its relevance review. This can include external user reports, maintainer-confirmed bugs, and concrete feature gaps. Treat them as evidence to inspect, not a count of distinct defects.

Back to [Apple Mail MCP by imdinu](/mcp/apple-mail-mcp-by-imdinu).

## Most discussed

### get_email type coercion + search mailbox scope + scheduled mode failures

## Bug Report — Three related issues in scheduled/automated mode

### Environment
- Version: v0.1.8
- Running via: Claude Cowork scheduled tasks (automated, unattended)

---

### Bug 1: `get_email` — message_id type coercion in scheduled mode

When called from a scheduled task, `message_id` is passed as a string instead 
of an integer. The tool rejects it with a type error, making it impossible to 
read email bodies in any automated context.

**Workaround:** None reliable. Triage falls back to m

[Read the thread](https://github.com/imdinu/apple-mail-mcp/issues/67) · 2026-03-27 · closed · external user · 3 comments

### Large mailboxes timeout on startup

I have a lot of emails (400,000+). I can build the index, but every time I open Claude, the MCP server takes too long to traverse all the email (needs about 2 minutes) and as a result Claude pops up an error message saying that it cannot connect to the MCP server. 

It would be great if you can find a way to support large mailboxes. Perhaps the software could do the start-up scan in the background, so that it can still respond to Claude when it tries to connect to the MCP server?

Thanks

[Read the thread](https://github.com/imdinu/apple-mail-mcp/issues/51) · 2026-03-04 · closed · external user · 3 comments

### search() cannot distinguish a missing index from a genuine no-match, so an unbuilt index reads as an empty mailbox

`search()` cannot distinguish "no index" from "no match", so an unbuilt or stale index looks exactly like a genuinely empty result. On my install that cost roughly four months of silently empty searches, on a mailbox of 18,232 emails that would have matched constantly.

Filing this with the backing of the Dex project, where the same problem is tracked as davekilleen/Dex#446. Dave (the maintainer there) asked me to bring it here directly since I have the reproduction. Happy to send a PR if the sh

[Read the thread](https://github.com/imdinu/apple-mail-mcp/issues/110) · 2026-08-12 · closed · outside contributor · 2 comments

### PermissionError escapes both no-FDA fallbacks: get_emails() fails outright, and attachment reads report "not found"

Running without Full Disk Access — which the docs describe as supported ("The MCP server itself does **not** need Full Disk Access — only the `index` and `rebuild` commands do", `docs/troubleshooting.md`) — two code paths fail in ways that look like different bugs but share one root cause.

`PermissionError` subclasses `OSError`, not `FileNotFoundError`. Both sites below have a handler that clearly intends to cover an unreadable Mail store, and `PermissionError` walks straight past it.

Happy to

[Read the thread](https://github.com/imdinu/apple-mail-mcp/issues/109) · 2026-08-07 · open · external user · 2 comments

### Feature request: APPLE_MAIL_INDEX_EXCLUDE_ACCOUNTS for account-level index exclusion

## Summary

Request a new environment variable `APPLE_MAIL_INDEX_EXCLUDE_ACCOUNTS` (comma-separated, like the existing `APPLE_MAIL_INDEX_EXCLUDE_MAILBOXES`) that excludes entire accounts from the index at build time.

## Motivation

`APPLE_MAIL_INDEX_EXCLUDE_MAILBOXES` matches by mailbox name only, with no account-qualified syntax. This works fine for excluding category folders like Drafts (the default), but fails for the common case of wanting to exclude an entire account whose mailboxes have g

[Read the thread](https://github.com/imdinu/apple-mail-mcp/issues/90) · 2026-05-22 · closed · external user · 2 comments

### Attachment Download Error

Always got error: attachment not found when run with cloude coworker. But can 
got it when via MCP Inspector.

get_email_attachment
Request

{
  "message_id": 437629,
  "filename": "GCEMEARSD0000290714-2.pdf",
  "account": "info@playlingo.app",
  "mailbox": "[Gmail]"
}
Error

Error calling tool 'get_email_attachment': Attachment 'GCEMEARSD0000290714-2.pdf' not found in email 437629.

[Read the thread](https://github.com/imdinu/apple-mail-mcp/issues/71) · 2026-04-03 · closed · external user · 2 comments

### Use SQL-based diffing in sync instead of in-memory inventory comparison

## Problem

`sync_from_disk()` loads the full disk inventory and full DB inventory into Python dicts to compute the diff. For users with 200K+ emails, this causes significant memory spikes.

## Proposed Solution

1. Create a temporary SQLite table (`disk_inventory_temp`)
2. Walk the disk, inserting paths into the temp table
3. Use SQL `EXCEPT` or `LEFT JOIN` queries to find NEW/DELETED/MOVED
4. Let SQLite handle the diffing — optimized for this and uses disk, not RAM

## Current Impact

Low for 

[Read the thread](https://github.com/imdinu/apple-mail-mcp/issues/60) · 2026-03-23 · closed · 2 comments

### Two concurrent --watch instances (Claude Desktop spawns MCP servers twice) cause write storm, unbounded WAL growth and blocked FTS searches

## Environment
- apple-mail-mcp 0.4.2
- macOS 26.5.2
- Claude Desktop as MCP client
- Observed on 2026-07-15

## Summary
Claude Desktop structurally spawns **two instances** of every configured MCP server — one for Desktop chats and one for the Claude Code bridge. When both instances run with `serve --watch`, the two watchfiles watchers operate on the same SQLite database (`~/.apple-mail-mcp/index.db`, WAL mode) and get into a sustained write storm.

## Symptoms
- Log spam every few seconds: `In

[Read the thread](https://github.com/imdinu/apple-mail-mcp/issues/106) · 2026-07-15 · closed · external user · 1 comment

## Most recent

### get_emails() silently returns [] for Gmail-backed accounts: Envelope Index fast path misses label-based mailbox membership

## Problem

On 0.4.0/0.4.1, `get_emails(account, mailbox)` returns an empty list for Gmail-backed accounts even when the mailbox has plenty of mail. No error is raised, so the JXA fallback never runs and the caller gets a silently wrong empty result.

## Repro (real mailbox, macOS 14, Mail V10)

`get_emails(account="<gmail account>", mailbox="INBOX")` returned `[]` for an INBOX that AppleScript confirms holds 104 messages.

## Root cause

The Strategy-0 fast path assumes mailbox membership is ex

[Read the thread](https://github.com/imdinu/apple-mail-mcp/issues/102) · 2026-06-12 · closed · outside contributor · 0 comments

### search() docstring: document the empty-result hint shape

## Problem

`search()` declares `-> list[SearchResult] | dict` and returns `{"result": [], "hint": "..."}` when nothing matches, but the docstring's Returns section only describes the list shape. The hint-on-empty pattern is good LLM ergonomics and should stay — it just needs to be documented so clients and harnesses iterating the result know both shapes exist.

## Proposed Solution

Document the empty-result shape in the Returns section. (The larger return-type unification question is part of t

[Read the thread](https://github.com/imdinu/apple-mail-mcp/issues/99) · 2026-06-11 · closed · 0 comments

### MCP boundary: limit/offset unclamped, before/after dates unvalidated, STRATEGY3_* env vars unbounded

## Problem

Three input-validation gaps at the MCP tool boundary, all producing silent misbehavior rather than correctable errors:

1. **`limit`/`offset` are unclamped.** Negative values flow into SQL, where `LIMIT -1` means *unlimited* in SQLite. Huge limits force the full result set into memory and into the model's context. They're also inlined into JXA scripts via `builders.py`.
2. **`before`/`after` aren't validated.** The docstring promises YYYY-MM-DD, but a malformed date like `2026-6-1` g

[Read the thread](https://github.com/imdinu/apple-mail-mcp/issues/96) · 2026-06-11 · closed · 1 comment

### Watcher: no rollback on sqlite3.Error; a failed batch can poison the next commit

## Problem

`watcher.py::_process_pending()` runs deletes and adds inside one `try`, commits once at the end, and the outer `except sqlite3.Error` only logs. Python's `sqlite3` opens an implicit transaction on the first DML and holds it until commit/rollback — so a mid-batch failure leaves the connection sitting in an open transaction with partial work. The *next* batch's `commit()` then persists that stale partial state alongside the new batch.

Related: both `watcher.py` and `sync.py` fetch ro

[Read the thread](https://github.com/imdinu/apple-mail-mcp/issues/95) · 2026-06-11 · closed · 1 comment

### Inline images without MIME filename are dropped from `_extract_attachments`

## Problem

`_extract_attachments` in `disk.py` skips MIME parts that have no `filename` attribute and aren't marked `Content-Disposition: attachment`, even when they have a `Content-ID` header and are physically stored on disk by Apple Mail.

Real example from a `multipart/related` HTML email in a 72K-message mailbox:

```
Part [4]:
  Content-Type: image/png
  Content-Disposition: inline
  Content-ID: <RO_BCR_Email_94c8b886-d7d1-4c...>
  filename: <none>
```

Apple Mail saved the image to `Atta

[Read the thread](https://github.com/imdinu/apple-mail-mcp/issues/86) · 2026-05-14 · closed · 0 comments

### Sync inventory walk dominates wall-clock at >100k mailboxes — disk-walk + per-file parse layer

## Problem

The SQL-temp-table sync diff (#60) shipped in v0.3.0 and works as designed at the diff layer.
But for users with very large mailboxes (>100k messages), wall-clock time for `apple-mail-mcp index` is dominated by the layer *before* the diff — the unconditional disk inventory walk plus per-file parse — not the diff itself.

## Source

External report from @chrispyness77 in [#60 (comment)](https://github.com/imdinu/apple-mail-mcp/issues/60#issuecomment-4413618196).

Three back-to-back `a

[Read the thread](https://github.com/imdinu/apple-mail-mcp/issues/84) · 2026-05-10 · open · 0 comments

### Read Apple's Envelope Index directly for metadata ops (list_accounts, list_mailboxes, get_emails, search_subject)

## Background

The v0.3.0 benchmark refresh (~72K-message mailbox) revealed that two competitors — `BastianZim/apple-mail-mcp` and `like-a-freedom/rusty_apple_mail_mcp` — are **dramatically faster than us on every metadata-only operation**:

| Op | Ours | BastianZim | Speedup |
|----|------|-----------|---------|
| `list_accounts` | 128.3 ms | 1.2 ms | **~107x** |
| `get_emails` (50) | 847.0 ms | 1.6 ms | **~530x** |
| `search_subject` | 6.9 ms | 2.8 ms | ~2.5x |
| `get_email` | 2.8 ms | 1.3 ms 

[Read the thread](https://github.com/imdinu/apple-mail-mcp/issues/82) · 2026-05-07 · closed · 1 comment

### Memory spike in _estimate_attachment_size from chained .replace() calls

## Problem

`disk.py::_estimate_attachment_size` decodes the encoded payload via `part.get_payload(decode=False)`, then computes the decoded byte size by stripping whitespace and counting:

```python
raw = part.get_payload(decode=False)
# ...
stripped = raw.replace("\n", "").replace("\r", "")
clean_len = len(stripped.replace(" ", ""))
```

For a 20 MB base64 attachment (well under the 25 MB `MAX_EMLX_SIZE` cap), this allocates **three intermediate string copies** of approximately 20 MB each — ~8

[Read the thread](https://github.com/imdinu/apple-mail-mcp/issues/81) · 2026-05-07 · closed · 0 comments

### APPLE_MAIL_READ_ONLY config flag is set up but never enforced at MCP tool boundaries

## Problem

`config.py` exposes `APPLE_MAIL_READ_ONLY` (env var) and `set_read_only_mode()` / `is_read_only()` accessors. `cli.py::serve` accepts `--read-only` and calls `set_read_only_mode(True)`. The flag is documented in `CLAUDE.md` and `README.md` as a way to "Disable write operations".

But: there are no write operations in v0.3.0. Every MCP tool currently registered (`list_accounts`, `list_mailboxes`, `get_emails`, `get_email`, `search`, `get_email_links`, `get_email_attachment`, `get_atta

[Read the thread](https://github.com/imdinu/apple-mail-mcp/issues/80) · 2026-05-07 · closed · 0 comments

### Attachment cache files inherit umask permissions (should be 0o600)

## Problem

`server.py::_cleanup_old_attachments` and the attachment-extraction path in `get_email_attachment` write extracted attachment content under `~/.apple-mail-mcp/attachments/`. The cache *directory* is created with mode `0o700` (good — only the owner can list it). But the *files* themselves are written via `Path.write_bytes()` (or whatever the extraction path uses), which means they inherit the user's umask — typically `0o644` on macOS.

On a single-user machine this is fine. On a share

[Read the thread](https://github.com/imdinu/apple-mail-mcp/issues/79) · 2026-05-07 · closed · 0 comments

### index://status resource walks the disk on every call (need TTL cache for disk_email_count)

## Problem

The `index://status` MCP resource (added in v0.3.0 via #12) calls `IndexManager.get_stats()`, which calls `get_disk_inventory(mail_dir)` to populate `disk_email_count`. That walks the filesystem under `~/Library/Mail/V*/` — potentially 100K+ files for users with large mailboxes.

Today the call is wrapped in `asyncio.to_thread()` to avoid blocking the event loop, but if an MCP client polls the resource on a tight loop (some agent UIs do), the asyncio thread pool gets pinned and the d

[Read the thread](https://github.com/imdinu/apple-mail-mcp/issues/78) · 2026-05-07 · closed · 0 comments

### Watcher silently swallows DLQ insert failures

## Problem

In `index/watcher.py::_process_pending`, when the failed-parse DLQ insert (added in v0.3.0 via #58) raises `sqlite3.Error`, the failure is logged at WARNING level but the underlying error is otherwise swallowed:

```python
except sqlite3.Error as e:
    logger.warning(
        "Could not record parse failure for %s: %s",
        path, e,
    )
```

This is fine for a one-off transient error (lock contention, etc.). But if the disk fills up, the DB is corrupted, or the schema is someh

[Read the thread](https://github.com/imdinu/apple-mail-mcp/issues/77) · 2026-05-07 · closed · 0 comments

The remaining reports are on [the project's issue tracker](https://github.com/imdinu/apple-mail-mcp/issues).
