Skip to main content
Composes a message and files it into the user’s Drafts folder. Nothing is sent and nobody outside the mailbox learns anything: the draft appears in Langmail exactly as one written by hand, for the user to review, edit, or send. This is the staging half of the sending surface. To actually send, call send_draft — or leave the draft for the user. To draft a reply, pass inReplyTo. The recipients, the Re: subject, and the In-Reply-To/References headers are all derived server-side from the message being replied to, so the reply lands in the same conversation in every mail client, not just in Langmail’s own threading. An agent never assembles a header itself.

Parameters

string[]
Recipients. Each entry is a bare address (person@example.com) or the Name <person@example.com> form that search_contacts returns — both are accepted. Up to 50 entries.
string[]
Carbon-copy recipients, same forms as to.
string[]
Blind-copy recipients, same forms as to. Delivered but not shown in the sent message’s headers.
string
Subject line, up to 500 characters. Defaults to Re: <original subject> when inReplyTo is set.
string
Plain-text body. Either text or html (or both) is required.
string
HTML body. Pass text as well when both are wanted; they are sent as alternatives of the same message.
object[]
Files to attach, up to 10. Each entry names its file either by blobId or by base64 content — giving both is an error. filename is the name the recipient sees; mimeType is guessed from its extension when omitted, defaulting to application/octet-stream.
  • blobId — a file already in the mailbox, as reported by search_emails, get_email, or get_draft. Nothing is transferred: the new message re-references the blob the server already holds, which is how an attachment is forwarded without downloading it. filename is required here — a blob carries bytes and nothing else, so without it the forwarded file would arrive unnamed and as an unrecognised download. Whatever listed the blobId printed the filename on the same line.
  • content — base64 bytes of a file you generated. These travel through the conversation, so they are capped at 25 MB across all content entries in one call; blobId entries are not counted against it.
There is no path: the MCP server runs elsewhere and cannot read the agent’s filesystem.
string
Id of the message this draft replies to, as returned by search_emails or get_thread. Sets the threading headers and defaults the subject and recipients from that message.
boolean
With inReplyTo: also Cc everyone the original was addressed to, minus every address belonging to this account. Cannot be combined with to, cc, or bcc — see the note below. Ignored without inReplyTo.
string
Sending address. Defaults to the authenticated account’s own address. Only an address the account is configured to send as (one of its aliases) is accepted — anything else is an error rather than a silent substitution.
string
Client-chosen key that makes the call safe to retry: a repeat with the same key returns the first call’s answer instead of staging a second draft. Keys are scoped to the account and to this tool — reusing this key on send_draft is not a retry. Remembered for 15 minutes.

Example

Call
Result

Notes

  • The original message is not quoted into a reply. Include whatever context the recipient needs in text.
  • Files are attached with attachments. Each entry names its file either by blobId — one already in the mailbox, as search_emails, get_email, or get_draft reports it — or by base64 content for a file you generated. Prefer blobId whenever the file is already there: it transfers nothing, which is what makes forwarding an attachment free. At most 10 files, and the content entries may come to at most 25 MB between them. filename is always worth setting; mimeType is guessed from its extension when omitted.
  • A file path cannot be used. The MCP server runs on a different machine from the agent and cannot read its filesystem, so there is no path parameter — read the file and pass its bytes as content.
  • Explicit to/cc/bcc override the recipients derived from inReplyTo; an empty array is an explicit “nobody”. Combining them with replyAll is rejected rather than resolved — “reply to everyone, but only these people” has no defensible reading, and per-field precedence would silently drop the person being answered.
  • Every address the account can send as is excluded from a derived reply, not just the one it is going out as. A message addressed to one of the user’s aliases does not put that alias on the reply.
  • Replying to the user’s own message leaves no recipient (every address on it is theirs) and is refused; pass to explicitly for a follow-up.
  • The draft is marked $draft and $seen, so it shows up as an unsent draft rather than unread mail.

Errors

  • Provide a body: text, html, or both. — no body was given.
  • Not a valid email address: … — a recipient was neither a bare address nor the Name <address> form. Nothing was staged.
  • This account cannot send as … — the from address is not one of the account’s sending identities. The available addresses are listed.
  • Provide recipients: to (or cc/bcc), or inReplyTo to derive them… — a draft with no recipients could never be sent, so it is refused at staging time rather than at send time. An empty array counts as no recipients.
  • replyAll cannot be combined with to/cc/bcc. … Nothing was staged.
  • Cannot reply: message not found: … — the inReplyTo id doesn’t exist.
  • Cannot stage a reply to <id>: it leaves no recipient. — replying to the user’s own mail.
  • This account cannot send as …, or Could not tell which address to send as… when the signed-in address is not one of several sending identities.
  • This account has no Drafts folder, so a draft cannot be staged.
  • Attachment <n> names no file. — an entry gave neither blobId nor content. A file path is not accepted; read the file and pass its bytes as content.
  • <file> gives both blobId and content, so it is ambiguous which file was meant.
  • Attachment <n> gives a blobId but no filename… — a blob carries no name of its own; pass the filename listed beside it.
  • The content of <file> is not valid base64… — encode the file’s raw bytes, not its text and not a data: URL.
  • The content of <file> is empty… — the payload decoded to zero bytes, so the file was never written or was read back empty.
  • These attachments come to more than the 25 MB of new files a message can carry… — checked before anything is uploaded, so nothing was staged. Attach a file already in the mailbox by blobId instead of re-uploading it, or link to the large one.
  • The server refused this draft (invalidProperties). — most often an attachment blobId the server does not recognise; blobIds belong to one account and do not outlive the message they were read from. Re-read it and use the blobId reported now, or pass the file as content.