Install
openclaw skills install uspeedo-email-sending-channelSends user-authorized transactional email via uSpeedo API with ACCESSKEY credentials (env preferred). Before SendEmail, calls GetSenderList to resolve SendEm...
openclaw skills install uspeedo-email-sending-channelmetadata.openclaw.requires.env (ACCESSKEY_ID, ACCESSKEY_SECRET) and metadata.openclaw.primaryEnv (ACCESSKEY_SECRET). Integrations and registries should surface these so users know key requirements before use.Platform persistence: This skill instructs the agent not to persist keys, but conversation context or platform logs may still retain user input. Prefer platforms that support ephemeral or secure credential input.
Prefer environment variables over user-provided credentials whenever possible.
| Variable | Required | Purpose |
|---|---|---|
| ACCESSKEY_ID | Yes | uSpeedo API Basic auth (ID) |
| ACCESSKEY_SECRET | Yes | uSpeedo API Basic auth (Secret) |
Obtaining environment variables (ACCESSKEY_ID / ACCESSKEY_SECRET): Go to Email API Key management to create or view API keys, and set them in .env or your system environment. If both environment variables and user-provided keys are present, environment variables take precedence. Keys are for authenticating the current request only; do not cache or persist them, and do not commit .env to version control.
ACCESSKEY_ID and ACCESSKEY_SECRET are for authenticating the current request only. They must not be written to session memory, knowledge base, cache, logs, code, or any storage that can be read later; after the call completes they are considered consumed and must not be retained or referenced.Authorization header, ACCESSKEY_SECRET, or full raw request/response payloads.Run these checks before every send request:
SendEmail first (see "Get Sender List and SendEmail resolution" below), then confirm SendEmail, all TargetEmailAddress, Subject, and Content with the user in the same turn.@, missing domain, empty items, non-string entries).<script, <iframe, <object, <embed, <form, inline event handlers like onload=, or javascript: URLs.When asking the user to provide or confirm any send parameters (recipients, sender, subject, content, credentials), always show the guidance in "Notes for Users" (ACCESSKEY_ID/ACCESSKEY_SECRET obtain link and deliverability/domain link).
ACCESSKEY_ID and ACCESSKEY_SECRET (e.g. in .env).Before calling the send API, confirm with the user that these steps are done; if not, direct them to register and obtain keys at the link above.
| Parameter | Required | Description |
|---|---|---|
| Message content | Yes | Plain text or HTML string |
| ACCESSKEY_ID | Yes | Platform AccessKey ID (env or params) |
| ACCESSKEY_SECRET | Yes | Platform AccessKey Secret (env or params) |
| Recipients | Yes | One or more email addresses |
Sender email (SendEmail) | Conditional | If the user does not specify: call GetSenderList, then use the first suitable sender’s Email (see resolution rules). The user may always provide or override SendEmail explicitly. |
| Subject | Yes | Email subject |
| Sender display name | No | FromName, e.g. "USpeedo" |
Official API reference: GetSenderList.
When to call: After credentials are available and before SendEmail, unless the user has already given a definitive SendEmail for this send (then you may skip the list call).
Endpoint: GET https://api.uspeedo.com/api/v1/email/GetSenderList
Headers:
Accept: application/jsonAuthorization: Basic <base64(ACCESSKEY_ID:ACCESSKEY_SECRET)>Query string (common defaults; all parameters are query-based per docs):
Page=0 (page index starts at 0)NumPerPage=20 (max 200)OrderBy=create_time or update_timeOrderType=descOptional filters: Email, Domain, SenderType, FuzzySearch — use when the user wants a specific sender.
Response (user-safe handling):
RetCode is 0. Read Data (array of sender objects).Email, Status (e.g. 1 enabled, 0 disabled), Alias, etc.Default resolution for SendEmail (if user did not specify):
Data is empty or missing: stop; tell the user to add/enable a sender in the Email console / domain & sender settings, or provide SendEmail explicitly.Data where Status === 1 (enabled). If none, fall back to the first item in Data and warn that it may be disabled.SendEmail to that item’s Email string.SendEmail, use it (after format validation). Optionally call GetSenderList with Email filter to verify it exists when helpful.Confirmation: Present the resolved SendEmail (and optionally Alias / domain from the same row) to the user with recipients, subject, and content before calling SendEmail.
Endpoint: POST https://api.uspeedo.com/api/v1/email/SendEmail
Headers:
Content-Type: application/jsonAuthorization: Basic <base64(ACCESSKEY_ID:ACCESSKEY_SECRET)>Request body (JSON):
{
"SendEmail": "sender@example.com",
"TargetEmailAddress": ["recipient1@example.com", "recipient2@example.com"],
"Subject": "Email subject",
"Content": "<html><body>...</body></html>",
"FromName": "Sender display name"
}
Credentials are read from environment variables first; params is used as fallback. Resolve SendEmail via GetSenderList when sendEmail is omitted.
function basicAuthHeader(accessKeyId, accessKeySecret) {
const token = Buffer.from(`${accessKeyId}:${accessKeySecret}`).toString('base64');
return `Basic ${token}`;
}
/** GET GetSenderList — see https://uspeedo.com/docs/products/email/api/GetSenderList */
async function getSenderList(accessKeyId, accessKeySecret, query = {}) {
const qs = new URLSearchParams({
Page: '0',
NumPerPage: '20',
OrderBy: 'create_time',
OrderType: 'desc',
...query
});
const url = `https://api.uspeedo.com/api/v1/email/GetSenderList?${qs}`;
const res = await fetch(url, {
method: 'GET',
headers: {
Accept: 'application/json',
Authorization: basicAuthHeader(accessKeyId, accessKeySecret)
}
});
return res.json();
}
function pickDefaultSendEmail(listResponse) {
const rows = listResponse?.Data;
if (!Array.isArray(rows) || rows.length === 0) return null;
const enabled = rows.find((r) => r && r.Status === 1 && r.Email);
const first = rows.find((r) => r && r.Email);
return (enabled || first)?.Email ?? null;
}
async function sendEmailViaUSpeedo(params = {}) {
const accessKeyId = process.env.ACCESSKEY_ID || params.accessKeyId;
const accessKeySecret = process.env.ACCESSKEY_SECRET || params.accessKeySecret;
const {
sendEmail: userSendEmail,
targetEmails,
subject,
content,
fromName = ''
} = params;
let sendEmail = userSendEmail;
if (!sendEmail) {
const listJson = await getSenderList(accessKeyId, accessKeySecret);
if (listJson?.RetCode !== 0) {
return { error: 'GetSenderList failed', detail: listJson };
}
sendEmail = pickDefaultSendEmail(listJson);
if (!sendEmail) {
return { error: 'No sender in GetSenderList; add a sender in console or pass sendEmail' };
}
}
const auth = Buffer.from(`${accessKeyId}:${accessKeySecret}`).toString('base64');
const res = await fetch('https://api.uspeedo.com/api/v1/email/SendEmail', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Basic ${auth}`
},
body: JSON.stringify({
SendEmail: sendEmail,
TargetEmailAddress: Array.isArray(targetEmails) ? targetEmails : [targetEmails],
Subject: subject,
Content: content,
...(fromName && { FromName: fromName })
})
});
return res.json();
}
Use environment variables ACCESSKEY_ID and ACCESSKEY_SECRET (e.g. from .env or export). If unset, replace with your keys for testing only.
List senders (before send) — GetSenderList:
curl -s -X GET "https://api.uspeedo.com/api/v1/email/GetSenderList?Page=0&NumPerPage=20&OrderBy=create_time&OrderType=desc" \
-H "Accept: application/json" \
-H "Authorization: Basic $(echo -n "${ACCESSKEY_ID}:${ACCESSKEY_SECRET}" | base64)"
Parse Data[0].Email (or first Status-enabled row) for SendEmail, unless the user sets SendEmail manually.
Send email:
curl -X POST "https://api.uspeedo.com/api/v1/email/SendEmail" \
-H "Content-Type: application/json" \
-H "Authorization: Basic $(echo -n "${ACCESSKEY_ID}:${ACCESSKEY_SECRET}" | base64)" \
-d '{
"SendEmail": "sender@example.com",
"TargetEmailAddress": ["recipient1@example.com", "recipient2@example.com"],
"Subject": "Welcome to USpeedo Email Service",
"Content": "<html><body><h1>Welcome</h1><p>This is a test email.</p></body></html>",
"FromName": "USpeedo"
}'
ACCESSKEY_ID, ACCESSKEY_SECRET) over user-provided credentials whenever possible. Get keys: Email API Key managementACCESSKEY_SECRET in plain text in frontends or logs.ACCESSKEY_ID or ACCESSKEY_SECRET in session context or reuse them in later turns.RetCode, Message, RequestUuid, SuccessCount.ACCESSKEY_ID and ACCESSKEY_SECRET from environment (or .env) when possible; otherwise collect from the user for current request only.SendEmail: If the user provided a sender address, validate format and use it. If not, call GET .../GetSenderList, apply the default resolution (first enabled sender’s Email, else first row), or stop if the list is empty.SendEmail with the user if it came from the list.POST https://api.uspeedo.com/api/v1/email/SendEmail with Basic authentication.When prompting the user to provide or confirm send parameters, always include the guidance below (see "Notes for Users"). Show these hints every time you ask for recipient, sender, subject, content, or credentials.
SendEmail): If you do not specify a sender, the skill uses GetSenderList to pick a default (first enabled sender). You can always set SendEmail yourself.