Outlook Mail Skill
Send, read, search, reply to, and handle attachments of email using the Microsoft Graph API (Outlook / Microsoft 365).
Tool: ms_mail
Consolidated Outlook Mail tool with an operation parameter.
Operations
| Operation | Description | Required Fields |
|---|---|---|
send | Send an email | to, subject, body |
read | Read a message by ID, or list recent mail when no ID is given | (message_id optional) |
search | Search messages by text | query |
reply | Reply to a message | reply_message_id, comment |
list_attachments | List a message's attachments (metadata only, no download) | message_id |
download_attachments | Download file attachments into the workspace | message_id |
Every read/search result includes a has_attachments boolean per message —
check it before calling list_attachments / download_attachments.
send - Send an email
| Field | Type | Required | Description |
|---|---|---|---|
| operation | string | Yes | Must be "send" |
| to | string | Yes | Recipient address(es), comma-separated |
| subject | string | Yes | Email subject line |
| body | string | Yes | Email body (plain text or HTML) |
| cc | string | No | CC recipients (comma-separated) |
| bcc | string | No | BCC recipients (comma-separated) |
| body_type | string | No | "text" or "html" (default: text) |
Example - Send plain text email:
json{ "operation": "send", "to": "alice@contoso.com", "subject": "Meeting Tomorrow", "body": "Hi,\n\nJust a reminder about our meeting tomorrow at 2pm.\n\nBest regards" }
Example - Send to multiple recipients with CC:
json{ "operation": "send", "to": "alice@contoso.com, bob@contoso.com", "cc": "manager@contoso.com", "subject": "Weekly Report", "body": "<h1>Weekly Report</h1><p>Highlights...</p>", "body_type": "html" }
read - Read a message or list recent mail
| Field | Type | Required | Description |
|---|---|---|---|
| operation | string | Yes | Must be "read" |
| message_id | string | No | Message ID to fetch (with body). Omit to list recent messages. |
| max_results | integer | No | Max messages when listing (default: 10, max: 100) |
Each returned message includes has_attachments (boolean). When true, use
list_attachments / download_attachments with that message_id.
Example - Read a specific message:
json{ "operation": "read", "message_id": "AAMkAGI2..." }
Example - List the 20 most recent messages:
json{ "operation": "read", "max_results": 20 }
search - Search messages
| Field | Type | Required | Description |
|---|---|---|---|
| operation | string | Yes | Must be "search" |
| query | string | Yes | Free-text search (Microsoft Graph $search) |
| search_max_results | integer | No | Max results (default: 10, max: 100) |
Microsoft Graph search matches across subject, body, sender, and recipients.
Use natural keywords (e.g. invoice, from:jane quarterly plan); it does not
use Gmail-style operators.
Example:
json{ "operation": "search", "query": "quarterly plan", "search_max_results": 20 }
reply - Reply to a message
| Field | Type | Required | Description |
|---|---|---|---|
| operation | string | Yes | Must be "reply" |
| reply_message_id | string | Yes | ID of the message to reply to (from search/read) |
| comment | string | Yes | The reply text |
| reply_all | boolean | No | Reply to all recipients (default: false) |
Example:
json{ "operation": "reply", "reply_message_id": "AAMkAGI2...", "comment": "Thanks - looks good to me.", "reply_all": true }
list_attachments - List a message's attachments (metadata only)
| Field | Type | Required | Description |
|---|---|---|---|
| operation | string | Yes | Must be "list_attachments" |
| message_id | string | Yes | The message whose attachments to list |
| include_inline | boolean | No | Include inline body images (e.g. signature logos). Default false. |
Returns attachments: [{attachment_id, name, content_type, size, is_inline, kind}]
and count. kind is "file" for a downloadable file attachment; other values
(itemAttachment, referenceAttachment) are shown so you know they cannot be
downloaded as bytes. Inline images are excluded unless include_inline: true.
This op does NOT download bytes — it is a cheap metadata lookup.
Example:
json{ "operation": "list_attachments", "message_id": "AAMkAGI2..." }
download_attachments - Download file attachments into the workspace
| Field | Type | Required | Description |
|---|---|---|---|
| operation | string | Yes | Must be "download_attachments" |
| message_id | string | Yes | The message whose attachments to download |
| attachment_id | string | No | Download only this attachment. Omit to download all file attachments. |
| include_inline | boolean | No | Include inline body images. Default false. |
Saves each file attachment into the workflow workspace and returns:
attachments: [{filename, path, mime_type, size, ref}]—pathis the absolute file path on disk (feed it to the Document Parser'sfile_path).download_dir— the absolute directory the files landed in (feed it to the Document Parser'sinput_dirto parse all of them).count, andskipped: [{name, reason}]for anything not downloaded (inline images, item/reference attachments, or files over the size limit).
Only real file attachments are downloaded. Item/reference attachments and (by default) inline images are skipped. Bytes are never returned inline — you get a path/reference, not the file contents.
Example - download all file attachments:
json{ "operation": "download_attachments", "message_id": "AAMkAGI2..." }
Example - download one specific attachment:
json{ "operation": "download_attachments", "message_id": "AAMkAGI2...", "attachment_id": "AAMkAGI2...==" }
Parsing an attachment (e.g. a PDF)
ms_mail downloads the file; it does NOT extract text. To read a PDF's contents,
pair it with the Document Parser node on the canvas:
ms_maildownload_attachments→ returnsdownload_dir(and per-filepath).- Document Parser with
input_dir = {{msMail.download_dir}}andfile_pattern = *.pdf(orfile_path = {{msMail.attachments[0].path}}for one file). - Document Parser returns
documents[].content— the extracted text.
Common Workflows
- Triage recent mail:
readwith no ID to list recent messages, thenreada specificmessage_idfor full content. - Find a thread:
searchby keyword, take themessage_id, thenreply. - Send an update:
sendto one or more recipients, optionally as HTML. - Process an attachment: on a message with
has_attachments: true, calldownload_attachments, then run the Document Parser overdownload_dirto get the text.
Shared mailboxes
Every operation accepts an optional mailbox field. Leave it empty to use the
signed-in user's own mailbox (default). Set it to a shared/other mailbox address
(e.g. support@contoso.com) to operate on that mailbox instead — the node then
calls /users/{address}/… rather than /me/….
Requirements for a shared mailbox:
- The signed-in account must have Full Access on the mailbox (and Send As / Send on Behalf to send from it).
- The
Mail.ReadWrite.Shared/Mail.Send.Sharedscopes must be granted (reconnect in the Credentials Modal after these are added to re-consent).
Example - read a shared mailbox:
json{ "operation": "read", "mailbox": "support@contoso.com", "max_results": 20 }
Setup Requirements
- Connect the Outlook Mail node to an AI Agent's
input-toolshandle. - Authenticate with Microsoft Graph in the Credentials Modal (Work/School account).
- Ensure the Mail.Send and Mail.ReadWrite scopes are granted (plus the
.Sharedvariants if you use themailboxfield for a shared mailbox).

