Outcome
Send reviewed content from a discovered mailbox to explicitly approved recipients.
Before you start
- Verify the intended environment, credential and authorized organization context before discovery.
- Discover Mail, the exact action and its messages:send permission. Pass the accessible workspace resource binding separately from action input.
- Review the actual change, recipients, provider/AI costs and any irreversible effects before confirmation; fixture IDs authorize no live operation.
Discover the target
- Run credential-scoped Mail discovery and topolo workspaces list topolo-mail; select an authorized canonical workspace.
- Resolve mailbox IDs through mailboxes.collection.list in that workspace. Resolve message, draft, thread, folder and scheduled IDs through the related published reads; never reuse fixture IDs or another context.
topolo whoami --json
topolo apps get topolo-mail --json
topolo actions get app_topolo_mail.messages.send --json
topolo workspaces list topolo-mail --json
Request
Create payload.json using the current input schema and discovered identifiers. Plan the unchanged request before execution.
topolo actions validate app_topolo_mail.messages.send --data @payload.json --json
topolo actions plan app_topolo_mail.messages.send --resource-type workspace --resource-id <discovered-workspace-id> --data @payload.json --confirm --json
topolo actions call app_topolo_mail.messages.send --resource-type workspace --resource-id <discovered-workspace-id> --data @payload.json --confirm --json
For MCP, use topolo_get_action, topolo_validate_action and topolo_plan_action; execute with topolo_call_action with confirm:true only after approval. Pass resourceType workspace and the discovered resourceId separately from input. An absent service/action or non-executable plan blocks that operation.
Input fields
| Field | Required | Meaning |
|---|---|---|
mailboxId | Yes | Mailbox ID from mailboxes.collection.list in the selected workspace; it is distinct from the workspace resource ID. |
to | Yes | Non-empty array of approved recipient email addresses. Saving a draft does not authorize sending to them. |
cc | No | Optional non-empty array of approved copied recipient email addresses. |
bcc | No | Optional non-empty array of approved blind-copy recipient email addresses. |
subject | Yes | Reviewed message subject; non-empty for message/draft payloads, optional summary snapshot for snooze. |
bodyText | No | Fallback plain-text body when text is absent or empty; the handler uses non-empty text first. Prefer one reviewed plain-text representation. |
bodyHtml | No | Fallback HTML body when html is absent or empty; the handler uses non-empty html first. Review rendered content before sending and prefer one reviewed HTML representation. |
text | No | Preferred plain-text message body when non-empty; bodyText is the fallback. This field is not an audio upload. |
html | No | Preferred HTML message body when non-empty; bodyHtml is the fallback. This field is not a template identifier. |
attachments | No | Mailbox attachment objects passed to the mailbox tool. The action publishes no attachment-field schema or generic file upload descriptor; inspect the current contract before supplying files. |
from | No | Optional sender display-name header whose email must match the bound mailbox address; it cannot impersonate another address. |
threadId | No | Thread ID returned with a message in this mailbox. For agent read it is used when messageId is absent. |
trackOpens | No | Optional explicit open-tracking choice. A tracking-pixel fetch is not reliable proof a human read the message. |
Effects
- Requests immediate outbound delivery through the mailbox transport.
- trackOpens optionally creates tracking metadata and injects a tracking pixel; this requires approval of the actual recipient/content and tracking choice.
Interpret the response
HTTP 201 contains the transport result in data, including messageId when supplied by the mailbox tool. Acceptance does not prove recipient receipt, inbox placement or open tracking. The handler locks From to the mailbox address and restricts Reply-To to its domain.
Worked requests and responses
Successful fixture request · HTTP 201
Input
{
"mailboxId": "mbx_mail_fixture",
"to": [
"recipient@example.test"
],
"subject": "Synthetic fixture",
"bodyText": "Synthetic content for review."
}
SDK response or error
{
"success": true,
"data": {
"messageId": "sent_mail_fixture",
"transport": "fixture-only"
}
}
Refused requests
Unauthenticated caller · HTTP 401
Input
{
"mailboxId": "mbx_mail_fixture",
"to": [
"recipient@example.test"
],
"subject": "Synthetic fixture",
"bodyText": "Synthetic content for review."
}
SDK response or error
{
"code": "auth_error",
"status": 401,
"message": "Fixture authentication refused"
}
Service HTTP body
{
"success": false,
"error": {
"message": "Fixture authentication refused"
}
}
Permission denied · HTTP 403
Input
{
"mailboxId": "mbx_mail_fixture",
"to": [
"recipient@example.test"
],
"subject": "Synthetic fixture",
"bodyText": "Synthetic content for review."
}
SDK response or error
{
"code": "permission_denied",
"status": 403,
"message": "TopoloMail permission denied"
}
Service HTTP body
{
"success": false,
"error": {
"message": "TopoloMail permission denied"
}
}
Other organization · HTTP 403
Input
{
"mailboxId": "mbx_mail_fixture",
"to": [
"recipient@example.test"
],
"subject": "Synthetic fixture",
"bodyText": "Synthetic content for review."
}
SDK response or error
{
"code": "permission_denied",
"status": 403,
"message": "Mailbox does not belong to your organization"
}
Service HTTP body
{
"success": false,
"error": {
"message": "Mailbox does not belong to your organization"
}
}
Other verified workspace · HTTP 404
Input
{
"mailboxId": "mbx_mail_fixture",
"to": [
"recipient@example.test"
],
"subject": "Synthetic fixture",
"bodyText": "Synthetic content for review."
}
SDK response or error
{
"code": "http_error",
"status": 404,
"message": "Mailbox not found"
}
Service HTTP body
{
"success": false,
"error": {
"message": "Mailbox not found"
}
}
Refused semantic request · HTTP 403
Input
{
"mailboxId": "mbx_mail_fixture",
"to": [
"recipient@example.test"
],
"subject": "Synthetic fixture",
"bodyText": "Synthetic content for review.",
"from": "other@example.test"
}
SDK response or error
{
"code": "permission_denied",
"status": 403,
"message": "From address must match this mailbox (fixture@example.test); requested other@example.test"
}
Service HTTP body
{
"success": false,
"error": {
"message": "From address must match this mailbox (fixture@example.test); requested other@example.test"
}
}
Verify the result
- Read the returned message ID or list the sent folder; compare the approved sender, recipients and content. Transport acceptance alone is not delivery confirmation.
Recover
Email already sent cannot be recalled. On timeout or uncertain transport outcome, inspect the sent folder and provider state before any retry; automatic resending can duplicate delivery.
- HTTP 401
auth_error: Authenticate again in the intended environment and context, then repeat identity and action discovery. - HTTP 403
permission_denied: Stop for the exact permission, organization, sender or Reply-To refusal. Do not broaden access or switch credentials automatically. - HTTP 404
http_error: Rediscover the exact mailbox and child IDs in the same authorized workspace; do not guess another ID.
The captured SDK errors preserve the service code when structured, otherwise http_error and HTTP status. Do not invent a more specific code. Preserve the live request ID and inspect actual diagnostics for uncaptured failures.
Related actions
Evidence and limits
-
Actual exported Mail handler dispatcher, widget handler, domain handlers, SDK transport/projection and shipped SQLite control/delivery/tracking migrations.
-
Identity, permissions, verified workspace grants, provider connection state, OAuth URL generation, mailbox Durable Object operations and content protection are synthetic ports.
-
Nexus AI and Auth archive are allowlisted in-process responses. No paid generation, billing, live OAuth, encryption custody, email delivery, asynchronous delivery or deployed outcome is proved. External network egress is refused.
The captured requests use synthetic identities and .test recipients. They demonstrate handler and SDK response behavior; they do not authorize delivery, provider consent, paid generation, deletion or other live effects. Current catalog discovery and environment proof remain separate release requirements.