Skip to content

Commit c0d129e

Browse files
docs: update send_email docs and add changelog for multipart support
- docs/mcp-tools.md: document 'multipart' bodyFormat value and textBody/htmlBody parameters with M365/Outlook.com limitation note - Skills/email.md: update send_email signature and parameter descriptions - changelogs/2026-06-09-multipart-email.md: new changelog entry Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent c424fed commit c0d129e

3 files changed

Lines changed: 64 additions & 3 deletions

File tree

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# 2026-06-09: Multipart/Alternative Email Sending
2+
3+
## Summary
4+
5+
Adds `bodyFormat: "multipart"` to `send_email`, allowing agents to provide
6+
both a plain-text fallback and an HTML body in a single message
7+
(`multipart/alternative` MIME). This eliminates formatting failures that
8+
occurred when agents sent plain text with `bodyFormat: "html"` or vice versa.
9+
10+
## New parameters
11+
12+
| Parameter | Required when | Description |
13+
|------------|---------------------------|--------------------------------------|
14+
| `textBody` | `bodyFormat="multipart"` | Plain-text fallback body |
15+
| `htmlBody` | `bodyFormat="multipart"` | HTML body (must be real HTML markup) |
16+
17+
## Example
18+
19+
```json
20+
{
21+
"to": ["recipient@example.com"],
22+
"subject": "Hello",
23+
"bodyFormat": "multipart",
24+
"textBody": "Plain text fallback for clients that cannot render HTML.",
25+
"htmlBody": "<html><body><h1>Hello</h1><p>Rich content.</p></body></html>"
26+
}
27+
```
28+
29+
## Provider behavior
30+
31+
| Provider | Behavior |
32+
|----------------|--------------------------------------------------------------------------|
33+
| Google (Gmail) | True `multipart/alternative` MIME via MimeKit `BodyBuilder` |
34+
| IMAP | True `multipart/alternative` MIME via MimeKit `BodyBuilder` |
35+
| Microsoft 365 | `htmlBody` sent as `BodyType.Html`; `textBody` dropped (Graph SDK limit)|
36+
| Outlook.com | `htmlBody` sent as `BodyType.Html`; `textBody` dropped (Graph SDK limit)|
37+
38+
When `bodyFormat` is `"multipart"` on an M365 or Outlook.com account the
39+
provider logs a `Warning` explaining that the plain-text body will not be
40+
included.
41+
42+
## Backward compatibility
43+
44+
Existing calls using `body` + `bodyFormat: "html"` or `"text"` are unchanged.
45+
`textBody` and `htmlBody` are ignored unless `bodyFormat` is `"multipart"`.

docs/mcp-tools.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,15 @@ Send email from specific account (requires explicit account selection or smart r
254254
- `to`: Recipient email address (can be array)
255255
- `subject`: Email subject
256256
- `body`: Email body content
257-
- `bodyFormat` (default: "html"): "html" or "text"
257+
- `bodyFormat` (default: "html"): `"html"`, `"text"`, or `"multipart"`
258+
- `"html"`: `body` must contain real HTML markup (Markdown is not converted)
259+
- `"text"`: `body` is sent as plain text
260+
- `"multipart"`: sends a `multipart/alternative` message with both a plain-text
261+
fallback and an HTML part. Requires `textBody` and `htmlBody` instead of `body`.
262+
**Note:** Microsoft 365 and Outlook.com do not support native multipart/alternative
263+
via the Graph API; for those providers only `htmlBody` is sent (a warning is logged).
264+
- `textBody` (optional): plain-text body, required when `bodyFormat` is `"multipart"`
265+
- `htmlBody` (optional): HTML body, required when `bodyFormat` is `"multipart"`
258266
- `cc` (optional): CC recipients
259267
- `attachments` (optional): File attachments. JSON array of objects. Each item
260268
must use one of two shapes:

src/CalendarMcp.Core/Skills/email.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,18 @@ omitted. Same return shape as `get_emails`.
4141
Returns full body, recipients, and the `attachments[]` array. Each
4242
attachment has `attachmentId` — feed that to `get_email_attachment`.
4343

44-
### `send_email(to[], subject, body, accountId?, bodyFormat="html", cc?[], attachments?[])`
44+
### `send_email(to[], subject, body, accountId?, bodyFormat="html", cc?[], attachments?[], textBody?, htmlBody?)`
4545

4646
- `to` is an array of strings. Single recipient: `["alice@x"]`.
47-
- `bodyFormat` defaults to `"html"`. Set `"text"` for plain.
47+
- `bodyFormat` defaults to `"html"`. Options:
48+
- `"html"`: `body` must be real HTML markup (Markdown is not converted).
49+
- `"text"`: `body` is sent as plain text.
50+
- `"multipart"`: sends a `multipart/alternative` message. Requires `textBody`
51+
and `htmlBody` instead of `body`. Use when you want a plain-text fallback for
52+
clients that can't render HTML. **Note:** Microsoft 365 / Outlook.com only
53+
transmit the `htmlBody` (Graph SDK limitation; a warning is logged).
54+
- `textBody`: plain-text body for multipart messages. Required when `bodyFormat="multipart"`.
55+
- `htmlBody`: HTML body for multipart messages. Required when `bodyFormat="multipart"`.
4856
- `accountId` is *optional but you should usually pass it.* When omitted,
4957
smart routing picks based on first recipient's domain (see `accounts`).
5058
- `attachments`: see `attachments` guide. Pass either `{attachmentId: "..."}`

0 commit comments

Comments
 (0)