All tools

read_email

Email · macOS

Effect: read (strongest supported action). Status: gated.

Gated means the tool requires an installed app, a connected account, permission, or runtime availability. Check those requirements on the listed platform before using it.

macOS

Purpose

Use this when the user wants the full content of an email that lives in the Mac's Apple Mail (message ID from list_emails/search_emails). For a Microsoft 365 message ID from m365_list_emails, use m365_read_email. Pass account= (and mailbox= if known, both from list_emails/search_emails) so the lookup targets one account instead of scanning all of them. Call sequentially, not in parallel — concurrent calls serialize behind Mail.app's JXA lock and later calls will time out. Performance: body fetch is the primary latency source (avg 20s on slow IMAP). Pass include_body=false to skip it and get metadata-only (fast). Pass max_body_chars=N to cap the body at N chars after HTML stripping (default 30000; 0=unlimited). Response includes body_fetch_ms when fetch took >2s, body_omitted=true when skipped, body_truncated_at=N when cut. When a body isn't cached on this Mac, read_email returns metadata with body_omitted=true and body_omit_reason="not_downloaded" (iCloud/IMAP optimized storage) rather than making Mail fetch it (that can be slow and tie Mail up). If the user wants it anyway, retry with force_download=true to have Mail pull the body over IMAP now and return it (waits up to ~60s). Off by default; ignored while Mail is in a cooldown.

Required inputs

Permissions and confirmation

No explicit confirmation parameter is exposed in this snapshot. This does not grant permission to act: obtain user authorization before any real action.

Full input schema — macOS
{
  "properties": {
    "account": {
      "type": "string"
    },
    "force_download": {
      "default": "false",
      "type": "boolean"
    },
    "include_body": {
      "default": "true",
      "type": "boolean"
    },
    "mailbox": {
      "type": "string"
    },
    "max_body_chars": {
      "default": "30000",
      "minimum": 0,
      "type": "integer"
    },
    "message_id": {
      "type": "string"
    }
  },
  "required": [
    "message_id"
  ],
  "type": "object"
}

Documentation example

Do not execute this example. These concrete inputs refer to a fictional demonstration dataset. Resolve real handles and obtain user authorization before any real call.

{
  "message_id": "demo-message-001"
}