mac-mail
Search and read the email Apple Mail has downloaded to your Mac, straight from its local Envelope Index and .emlx files, read-only. Use when asked "find the invoice from Acme last month", "what did th
Files2
View on GitHubSKILL.mdskills/mac-mail/SKILL.md
GitHubMac Mail (local, read-only)
scripts/mail.py, Python 3 stdlib only. Search the index first, then open a message by its id.
python3 scripts/mail.py mailboxes
python3 scripts/mail.py search --from acme --since 2026-09-01 --attachments
python3 scripts/mail.py search --subject invoice --mailbox Inbox --limit 50
python3 scripts/mail.py search --text "security deposit" --unread
python3 scripts/mail.py search --to dana@example.com
python3 scripts/mail.py read 48213 # headers + plain-text body (--html for raw HTML)
python3 scripts/mail.py attachments 48213 --save ./out
python3 scripts/mail.py thread 48213 --md thread.md # whole conversation, oldest first
Search rows look like 48213 *! 2026-09-14 09:02 Acme Billing <billing@example.com> Invoice 1042 [INBOX]
(* unread, ! flagged; the first column is the id).
Where the data is
~/Library/Mail/V<n>/MailData/Envelope Index: SQLite index of every message.V10on current macOS; the script takes the highestV*. Never hard-code it.~/Library/Mail/V<n>/<account-uuid>/<Mailbox>.mbox/<uuid>/Data/<d>/<d>/Messages/<ROWID>.emlx: the message itself. The id from the index is the file name.- Attachments of a
.partial.emlxsit beside it in.../Data/<d>/<d>/Attachments/<ROWID>/<part>/<file>.
Index joins: messages.sender -> addresses, messages.subject -> subjects,
messages.mailbox -> mailboxes.url, messages.summary -> summaries (the preview text),
recipients(message, address, type) with type 0 = To, 1 = Cc, attachments(message, name),
messages.conversation_id groups a thread. Dates are Unix seconds. deleted = 1 rows are gone.
Traps
- .emlx is not a plain .eml. Line 1 is the byte length of the RFC 822 message; an Apple plist
follows it. Read exactly that many bytes after the first newline, then parse with
email. .partial.emlxmeans Mail stripped the attachments out to theAttachments/folder. A tool that only parses MIME parts reports "no attachments".- Gmail paths contain
[Gmail], whichglobtreats as a character class. Useglob.escape. - Gmail labels duplicate messages. One email sits in All Mail plus each label's mailbox; the thread command dedupes by Message-ID.
- Bodies only exist if Mail downloaded them. With "Download attachments: None" or a new account,
the index row exists but the file does not;
readfalls back to the preview summary and says so. - Body text search is only over the stored preview (
summaries, the first few lines). For a full-text hunt, filter withsearchfirst, thenreadthe candidates; or use Spotlight (mdfind -onlyin ~/Library/Mail "kMDItemTextContent == '*phrase*'"). - Mailbox urls are percent-encoded (
%5BGmail%5D/All%20Mail); match on the decoded name.
Permission (TCC)
~/Library/Mail requires Full Disk Access: System Settings > Privacy & Security > Full Disk Access >
add the app running the agent, then restart it. Without it, Envelope Index will not open.
Limits
Read-only; sending or moving mail needs Mail.app or AppleScript. Only mail Mail.app has synced to this Mac is visible. For Gmail via API instead of Mail.app, use a Gmail skill.