原始内容
name: "sendmux-send-email" description: "Send one or many emails through Sendmux using approved mailbox or agent credentials, idempotency keys, attachments, MCP, CLI, SDKs, or HTTP." version: "1.3.0" metadata: openclaw: skillKey: "sendmux-send-email" homepage: "https://github.com/Sendmux/skills" primaryEnv: "SENDMUX_API_KEY" envVars: - name: "SENDMUX_API_KEY" required: false description: "Optional Sendmux API key or scoped agent token used by CLI, SDK, HTTP, or MCP examples." - name: "SENDMUX_MBX_KEY" required: false description: "Optional Sendmux mailbox key for Mailbox and send-capable mailbox workflows."
Sendmux send email
ClawHub account note
This ClawHub skill connects OpenClaw agents to Sendmux. Some workflows require a Sendmux account and an appropriate Sendmux API key or agent token. Sendmux account usage is external to ClawHub; do not ask users to paste secrets into chat.
Use this skill when the user is ready to send outbound email through Sendmux or needs code/commands for sending.
Safety first
- Do not ask the user to paste an API key.
- Do not invent recipients, sender addresses, subject lines, or body content.
- Send only after the user supplies or confirms every recipient and message.
- For batch sends, confirm the full recipient/message set before calling a send tool.
- Use a send-capable
smx_mbx_key or owner-approved Sending-resourcesmx_agent_token for the Sending API. - Do not use a pre-claim
smx_agent_token for sending. Pre-claim self-registered agent tokens havemailbox.readandemail.receive, notemail.send. - If using a self-registered agent, obtain the Sending-resource
smx_agent_token by exchanging the savedclaim_tokenafter owner approval withresource=https://smtp.sendmux.ai/api/v1.
Choose the send path
| User task | Efficient default |
|---|---|
| One outbound email | POST /emails/send, MCP sending_send_email, CLI sending:send, or SDK sendingSendEmail. |
| More than one independent outbound email | Batch by default: POST /emails/send/batch, MCP sending_send_email_batch, CLI sending:send:batch, or SDK sendingSendEmailBatch. |
| Sending API attachment file | Upload first with sending_upload_attachment, sending_create_attachment_upload, CLI --attach, or SDK file helpers; send by attachment_id. |
| Replying while working inside one mailbox | Use mailbox send from sendmux-mailbox-agent when the workflow is mailbox-centred. |
| Existing app only supports SMTP | Use SMTP only because the existing tool requires it. For new agent or app integrations, prefer the HTTP Sending API. |
Batch sends accept up to 100 messages. A batch response can partially succeed, so inspect every result item.
Required JSON shape
Single send body:
{
"from": { "email": "sender@example.com", "name": "Sender Name" },
"to": { "email": "recipient@example.com", "name": "Recipient Name" },
"subject": "Subject line",
"html_body": "<p>Hello.</p>",
"text_body": "Hello."
}
Required fields: from, to, subject, html_body.
Useful optional fields:
text_body: plain text alternative.cc,bcc: arrays of recipients, max 100 each.reply_to: one address object.return_path: envelope sender for bounce handling.custom_headers: customX-*headers.attachments: up to 10 items. Prefer uploaded refs{ "attachment_id": "att_..." }. Inline compatibility form usesfilenameplus base64content, optionaltype, andencoding: "base64".
For real local files, do not ask the model to produce base64. Route attachment-heavy work to sendmux-attachments; use CLI --attach, SDK file helpers, sending_upload_attachment, or delegated sending_create_attachment_upload, then pass attachment_id refs. Sending uploads cap each file at 18 MiB and the final sent message at 25 MB. Mailbox blob_id refs are for mailbox sends, not Sending API sends.
Batch send body:
{
"messages": [
{
"from": { "email": "sender@example.com" },
"to": { "email": "alice@example.com" },
"subject": "Hello Alice",
"html_body": "<p>Hi Alice.</p>"
},
{
"from": { "email": "sender@example.com" },
"to": { "email": "bob@example.com" },
"subject": "Hello Bob",
"html_body": "<p>Hi Bob.</p>"
}
]
}
Idempotency
Add Idempotency-Key to every send that may be retried. Use one stable key per logical email or batch.
- Same key and same body: returns the cached response for 24 hours.
- Same key and different body: returns
409 idempotency_conflict. - Keep keys under 255 characters.
MCP
Use MCP when the user's agent already has the Sending server connected:
- One message:
sending_send_email. - Multiple messages:
sending_send_email_batch. - Local file upload before send:
sending_upload_attachmentwithfile_path. - Hosted or shell-capable upload before send:
sending_create_attachment_upload, thenPUTbytes to the returned URL with the returned headers and no Sendmux API key. - Metadata check for a temporary uploaded attachment:
sending_get_attachment.
Include an idempotency key when the client exposes the header parameter. If the MCP client does not expose headers clearly, use CLI, SDK, or direct HTTP for retry-sensitive sends. For attachments through MCP, use sendmux-attachments so the agent chooses file_path, presigned upload, or tiny inline base64 correctly.
CLI
One email:
SENDMUX_API_KEY="$SENDMUX_MBX_KEY" sendmux sending:send \
--idempotency-key "$IDEMPOTENCY_KEY" \
--body '{
"from": { "email": "sender@example.com", "name": "Sender Name" },
"to": { "email": "recipient@example.com", "name": "Recipient Name" },
"subject": "Subject line",
"html_body": "<p>Hello.</p>",
"text_body": "Hello."
}' \
--json
Batch:
SENDMUX_API_KEY="$SENDMUX_MBX_KEY" sendmux sending:send:batch \
--idempotency-key "$IDEMPOTENCY_KEY" \
--body-file ./sendmux-batch.json \
--json
Use --attach ./file.pdf for local files; the CLI uploads bytes first and injects attachment_id refs before sending. Use --body-file for larger JSON payloads or already-prepared Sending API attachment objects.
TypeScript SDK
One email:
import { createSendingClient, sendingSendEmail } from "@sendmux/sending";
const client = createSendingClient({ apiKey: process.env.SENDMUX_API_KEY! });
const response = await sendingSendEmail({
client,
headers: { "Idempotency-Key": idempotencyKey },
body: {
from: { email: "sender@example.com", name: "Sender Name" },
to: { email: "recipient@example.com", name: "Recipient Name" },
subject: "Subject line",
html_body: "<p>Hello.</p>",
text_body: "Hello.",
},
});
console.log(response.data.message_id, response.data.status);
Batch:
import { createSendingClient, sendingSendEmailBatch } from "@sendmux/sending";
const client = createSendingClient({ apiKey: process.env.SENDMUX_API_KEY! });
const response = await sendingSendEmailBatch({
client,
headers: { "Idempotency-Key": idempotencyKey },
body: {
messages,
},
});
for (const result of response.data.results) {
console.log(result.index, result.status, result.message_id, result.error);
}
Direct HTTP
Use direct HTTP only when MCP, CLI, or SDK is unavailable:
curl -X POST https://smtp.sendmux.ai/api/v1/emails/send \
-H "Authorization: Bearer $SENDMUX_MBX_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $IDEMPOTENCY_KEY" \
-d @sendmux-email.json
Responses and errors
Single send success returns a 200 success envelope with:
data.message_id:eml_...data.status:queued
Batch success returns a 200 success envelope with:
data.summary.totaldata.summary.queueddata.summary.faileddata.results[]containingindex,status,message_id, and optionalerror
Handle these errors deliberately:
401: missing, invalid, or revoked key.402: insufficient credits.403: key lacksemail.send, is not allowed for the sender, or uses the wrong surface.409: idempotency conflict.413: request body exceeds 25 MB.422: validation failed; readerror.errors.429or503: retry according to response headers.
Routing
- Setup/auth first call:
sendmux-getting-started. - Attachment file paths, presigned upload URLs, and download URLs:
sendmux-attachments. - Mailbox-centred replies:
sendmux-mailbox-agent. - CLI-only details:
sendmux-cli. - Cheapest-call decisions:
sendmux-token-efficient-usage.