Send Email Using JavaScript and the Robotomail API
Use server-side JavaScript to send email, protect the API key, handle failures and connect inbound replies to your application.
John Joubert
Founder, Robotomail

Table of contents
Send email from server-side JavaScript when the operation needs a private API key. A browser should submit an authorized request to your own server; that server validates the request and calls the email provider.
This tutorial uses Robotomail's HTTP API to send from a mailbox that can also receive replies. See the email API for agents for the full workflow.
Keep the send operation on the server
A mailto: link asks the visitor's email client to compose a message. It does not send mail from your application or guarantee that a form submission reaches you.
Putting an API key into client-side JavaScript exposes it to every visitor. Keep the key in server-side secret storage, authorize the caller, constrain the sender and recipients, and apply rate limits to your endpoint. A contact form must not become an open mail relay.
For a practical form-to-conversation pattern, see contact forms and lead qualification.
Send with Node.js fetch
Use a Node runtime that supplies fetch and AbortSignal.timeout. Set ROBOTOMAIL_API_KEY, ROBOTOMAIL_MAILBOX_ID and TEST_RECIPIENT in the server environment. Complete account verification before sending.
On Free, set TEST_RECIPIENT to your verified signup email address. Free includes one mailbox, 10 sends and 10 receives per calendar month with that address only. Upgrade to contact other recipients or use a custom domain.
const key = process.env.ROBOTOMAIL_API_KEY;
const mailboxId = process.env.ROBOTOMAIL_MAILBOX_ID;
const recipient = process.env.TEST_RECIPIENT;
if (!key || !mailboxId || !recipient) throw new Error('Missing email configuration');
async function sendTest() {
const response = await fetch(
`https://api.robotomail.com/v1/mailboxes/${encodeURIComponent(mailboxId)}/messages`,
{
method: 'POST',
headers: {
Authorization: `Bearer ${key}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
to: [recipient],
subject: 'Hello from JavaScript',
bodyText: 'This is a controlled test. Reply here with any questions.',
}),
signal: AbortSignal.timeout(30000),
},
);
if (!response.ok) throw new Error(`Send rejected: HTTP ${response.status}`);
const { message } = await response.json();
console.log('Accepted message ID:', message.id);
}
sendTest().catch(() => {
console.error('Send did not complete normally. Reconcile before retrying.');
process.exitCode = 1;
});
List mailboxes through GET /v1/mailboxes to obtain the correct ID. Keep the key out of logs, and test with an address you control. A timeout can leave a send's outcome uncertain, so a retry needs more care than simply calling the function again.
HTML and files
The send body requires bodyText. Add bodyHtml for an HTML alternative and keep the text version complete. Escape user-supplied values before adding them to HTML; do not use an agent's generated markup as trusted application UI.
Upload attachments first, then include the returned IDs in the attachments array. Upload authorization and file-size limits are separate from mailbox access. The attachment guide includes a Node upload-and-send example.
Receive the reply
Register an inbound webhook, open an SSE stream or poll the mailbox. For a webhook, verify the signature using the exact raw body before parsing. Queue slow work and deduplicate processing so repeated delivery cannot create repeated replies.
Fetch the incoming message and relevant thread, then apply your application's rules. If the agent should answer, check the recipient and content before sending. Set inReplyTo to the incoming email's RFC Message-ID, not its database UUID.
Store task state outside the model. A process restart should not erase the fact that a message already produced a reply or a CRM update. The receive-and-reply guide covers the transport and payload details.
SMTP libraries and HTTP APIs
A library such as Nodemailer can build MIME messages and submit them through a configured SMTP provider. That is useful when an application already has an SMTP integration and the provider settings it needs.
An HTTP mailbox API gives an application explicit operations for mailbox identity, sending, receiving and thread retrieval. Choose based on the whole workflow rather than the size of the first send snippet. Robotomail's bearer key is an HTTP API credential, not an SMTP password.
Production checks that matter
Validate all recipient addresses according to your application's rules, enforce access to the relevant mailbox and avoid sending arbitrary data requested by an incoming email. Define which actions need approval.
Track accepted sends, delivery events, bounces and complaints separately. Respect suppression and quota responses. A delivered event confirms recipient-server acceptance, not a read or successful activation.
Use email delivery troubleshooting and agent email security before expanding an unattended workflow. Prefer the TypeScript SDK if its typed interface fits your application better than direct fetch calls.
Give your AI agent a real email address
Create a mailbox, connect your agent and test a conversation. Send, receive and retrieve the thread through one API.
Related posts

10 Email Automation Best Practices for 2026
Master our top 10 email automation best practices for AI agents. Learn about DKIM, webhooks, threading, and more for secure, reliable agent-native email.
Read post
Inbound Package Meaning: From Warehouse Box to API Payload
Confused by the 'inbound package meaning'? Learn the critical difference between the logistics term and the API payload concept AI developers must know.
Read post
Send Email from PHP with the Robotomail API
A PHP cURL sending example with private credentials, error handling, attachment guidance and a path for incoming replies.
Read post