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:
{
"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:
{
"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:
{
"operation": "read",
"message_id": "AAMkAGI2..."
}
Example - List the 20 most recent messages:
{
"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:
{
"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:
{
"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:
{
"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:
{
"operation": "download_attachments",
"message_id": "AAMkAGI2..."
}
Example - download one specific attachment:
{
"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:
{
"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).