Send Email from an AI Agent (Python + Node)

Updated 4 min read

Send email from your AI agent in under five minutes. Code examples in Python and Node.js for basic sends, HTML email, threading, and a complete agent loop.

John Joubert

John Joubert

Founder, Robotomail

Send Email from an AI Agent (Python + Node)
Table of contents

Setup and API examples reviewed 23 September 2026. Original publication date preserved.

This tutorial shows how to send email from an AI agent using Robotomail's REST API. Code examples in both Python and Node.js. You'll go from zero to sending in under five minutes.

Retrieve the original before replying

The webhook's data.message_id is a database ID used to retrieve or deduplicate a message. Fetch it with the GET message endpoint, then use the response's message.messageId (the RFC Message-ID) as inReplyTo. Keep data.thread_id for your application's conversation state. Do not use a database ID or thread ID as a reply header. Stop and investigate if the fetched message has no Message-ID.

The Python tool below accepts a database ID and uses this lookup before sending. Include this helper in the same module:

import os
import json
import urllib.request
from urllib.parse import quote

def get_reply_message_id(mailbox_id: str, message_id: str) -> str:
    url = (
        "https://api.robotomail.com/v1/mailboxes/"
        + quote(mailbox_id, safe="") + "/messages/" + quote(message_id, safe="")
    )
    request = urllib.request.Request(url, headers={
        "Authorization": "Bearer " + os.environ["ROBOTOMAIL_API_KEY"]
    })
    # HTTP errors propagate; do not send a reply if retrieval fails.
    with urllib.request.urlopen(request, timeout=20) as response:
        original = json.load(response)["message"]
    if not original.get("messageId"):
        raise ValueError("Original email has no Message-ID")
    return original["messageId"]

Prerequisites

You need a Robotomail account and API key. If you don't have one, your agent can create both in a single request:

curl -X POST https://api.robotomail.com/v1/signup \
  -H "Content-Type: application/json" \
  -d '{
    "email": "you@example.com",
    "password": "a-strong-password",
    "slug": "myagent"
  }'

The response includes your API key and a default mailbox at myagent@robotomail.co. Save the API key and mailbox ID.

Send a basic email (Python)

import requests

API_KEY = "rm_..."
MAILBOX_ID = "mbx_..."
BASE_URL = "https://api.robotomail.com/v1"

response = requests.post(
    f"{BASE_URL}/mailboxes/{MAILBOX_ID}/messages",
    headers={
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
    },
    json={
        "to": ["recipient@example.com"],
        "subject": "Hello from my AI agent",
        "bodyText": "This email was sent by an autonomous agent.",
    },
)

message = response.json()
print(f"Sent: {message['id']}")

Send a basic email (Node.js)

const API_KEY = "rm_...";
const MAILBOX_ID = "mbx_...";
const BASE_URL = "https://api.robotomail.com/v1";

const response = await fetch(
  `${BASE_URL}/mailboxes/${MAILBOX_ID}/messages`,
  {
    method: "POST",
    headers: {
      Authorization: `Bearer ${API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      to: ["recipient@example.com"],
      subject: "Hello from my AI agent",
      bodyText: "This email was sent by an autonomous agent.",
    }),
  }
);

const message = await response.json();
console.log(`Sent: ${message.id}`);

Send HTML email

Add a bodyHtml field alongside the required bodyText. Providing both lets email clients fall back to plain text when HTML rendering isn't available.

response = requests.post(
    f"{BASE_URL}/mailboxes/{MAILBOX_ID}/messages",
    headers=headers,
    json={
        "to": ["recipient@example.com"],
        "subject": "Weekly report",
        "bodyText": "Your weekly metrics are attached.",
        "bodyHtml": "<h1>Weekly Report</h1><p>Your metrics are attached.</p>",
    },
)

Reply to a thread

To reply to an existing conversation, include the inReplyTo field with the message ID you're responding to. Robotomail sets the correct In-Reply-To and References headers automatically, so the reply threads correctly in the recipient's email client.

# When your agent receives an inbound message via webhook,
# retrieve the original message to read its RFC Message-ID:
inbound_message_id = get_reply_message_id(mailbox_id, webhook["data"]["message_id"])

response = requests.post(
    f"{BASE_URL}/mailboxes/{MAILBOX_ID}/messages",
    headers=headers,
    json={
        "to": ["recipient@example.com"],
        "subject": "Re: Hello from my AI agent",
        "bodyText": "Thanks for your reply! Here's what I found...",
        "inReplyTo": inbound_message_id,
    },
)

Complete agent loop

Here's a minimal Python agent that sends an email and handles replies via webhook. This pattern works with any LLM (Claude, GPT, Llama) for generating responses.

from flask import Flask, request
import requests

app = Flask(__name__)

@app.route("/webhooks/email", methods=["POST"])
def handle_inbound():
    payload = request.json
    message = payload["data"]

    # Extract the inbound message details
    from_addr = message["from"]
    body = message["body_text"]
    message_id = message["message_id"]  # Database ID for retrieval and deduplication

    # Generate a reply (plug in your LLM here)
    reply_text = generate_reply(body)

    # Send the reply, threaded to the original message
    requests.post(
        f"{BASE_URL}/mailboxes/{MAILBOX_ID}/messages",
        headers=headers,
        json={
            "to": [from_addr],
            "subject": f"Re: {message['subject']}",
            "bodyText": reply_text,
            "inReplyTo": get_reply_message_id(message["mailbox_id"], message_id),
        },
    )

    return "", 200

For the full inbound setup (registering webhooks, verifying signatures), see how to receive inbound email via webhook.

Next steps

You now have the building blocks for an email-capable AI agent. From here:

Start building, free

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