AI Builder Guides

OpenClaw

Give your OpenClaw AI agent an inbox with MailBlastr — send reports, parse newsletters and receipts, and receive replies via signed webhooks, with a leveled security model.

This guide shows how to give an OpenClaw AI agent its own email inbox backed by MailBlastr — so it can send and receive mail with a dedicated address instead of borrowing your credentials.

Why give your agent an inbox?

An inbox lets your agent:

  • Sign up for its own accounts on GitHub, hosting platforms, and more, so you never share your personal credentials.
  • Process attachments such as receipts and invoices, and act on them.
  • Receive newsletters, parse them, and forward the important parts to you.
  • Send daily reports and digests.
  • Send and receive email as a first-class capability.

Step 1: Get an API key

Create a MailBlastr API key for the agent. Scope it to a dedicated project if you want to sandbox the agent away from your production sending.

Do not paste the key into the chat. SSH into the agent’s machine and store it in an .env file, or put it in a password manager (e.g. a 1Password service account) the agent can read from its own vault.

Step 2: Verify a domain

Your agent needs an address to send from and receive at. We strongly recommend a subdomain (agent.example.com) rather than the root domain, especially if you want to receive mail, so the agent’s sending reputation stays isolated from your primary domain.

  1. 1
    Add the domain

    Create the subdomain via POST /domains or the dashboard, choosing the region closest to your agent.

  2. 2
    Add the DNS records

    MailBlastr returns SPF, DKIM, and (for receiving) MX records. Add them at your DNS provider. See Managing domains.

  3. 3
    Enable receiving

    If the agent should receive mail, enable inbound on the domain and add the MX record MailBlastr provides — not just sending records.

  4. 4
    Wait for verification

    Verification usually completes within minutes (up to 72 hours for DNS to propagate). Poll GET /domains/:id until status is verified.

Once verified, store the address in the agent’s memory and have it send you a test email to confirm sending works.

Step 3: Receive email via webhooks

At this point the agent can send but not receive. To receive, register a webhook for the email.received event pointing at a public URL. During development, expose a local server with a tunnel such as Tailscale Funnel:

tailscale funnel 3000
# gives a stable public URL like https://hostname.tailnet-name.ts.net
curl -X POST 'https://api.mailblastr.com/webhooks' \
  -H "Authorization: Bearer $MAILBLASTR_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
    "endpoint_url": "https://hostname.tailnet-name.ts.net/api/webhook",
    "events": ["email.received"]
  }'
When MailBlastr returns the webhook signing secret, store it securely (the same way you stored the API key) — never paste it into the chat.

A minimal handler verifies the signature, applies a sender allowlist, fetches the full inbound email, then notifies you:

import crypto from 'node:crypto';
import { MailBlastr } from 'mailblastr';

const API_KEY = process.env.MAILBLASTR_API_KEY;
const WEBHOOK_SECRET = process.env.MAILBLASTR_WEBHOOK_SECRET; // 'whsec_...'
const mb = new MailBlastr(API_KEY);

// Security: strict allowlist
const ALLOWED_SENDERS = ['your@email.com'];

// Verify the Svix-style signature over `${id}.${timestamp}.${payload}`.
function verify(payload, h) {
  const signed = `${h.id}.${h.timestamp}.${payload}`;
  const secret = Buffer.from(WEBHOOK_SECRET.split('_')[1], 'base64');
  const expected = crypto.createHmac('sha256', secret).update(signed).digest('base64');
  // header looks like "v1,<sig> v1,<sig2>" — accept if any matches
  return h.signature.split(' ').some((s) => s.split(',')[1] === expected);
}

async function handler(req) {
  const payload = await req.text();
  const h = {
    id: req.headers.get('svix-id'),
    timestamp: req.headers.get('svix-timestamp'),
    signature: req.headers.get('svix-signature'),
  };
  if (!h.id || !h.timestamp || !h.signature || !verify(payload, h)) {
    return new Response('Invalid signature', { status: 400 });
  }

  const event = JSON.parse(payload);
  if (event.type === 'email.received') {
    if (!ALLOWED_SENDERS.includes(event.data.from.toLowerCase())) {
      return new Response('OK', { status: 200 }); // ignore, but ack
    }
    // Fetch the full inbound email with the SDK.
    const { data: email } = await mb.emails.receiving.get(event.data.email_id);
    await notifyUser(email);
  }

  return new Response('OK', { status: 200 });
}
For production, deploy the handler behind a stable URL and register it via POST /webhooks. See Receiving email for full inbound payloads, bodies, and attachments.

Step 4: Instant notifications via OpenClaw

Rather than polling its inbox on a cron, your agent can use OpenClaw’s Gateway API to be notified the instant MailBlastr delivers an email.received webhook — turning each inbound message into a real-time prompt. Wire your webhook handler to call the Gateway API, then send a test email to confirm the agent reacts immediately.

Security considerations

An agent inbox is powerful, and inbound email is an untrusted input — prompt injection via email is a real risk. MailBlastr signs every webhook so you can reject forged payloads, but you also need a policy for what the agent does with verified mail. Choose a security level and start strict:

  1. 1
    Strict allowlist

    Only act on email from specific known senders. Recommended for most use cases.

  2. 2
    Domain allowlist

    Act on email from any sender at a trusted domain (e.g. anyone at example.com).

  3. 3
    Content filtering with sanitization

    Accept email from anyone, but sanitize the body to strip likely injection attempts before the agent reads it.

  4. 4
    Sandboxed processing

    Process all email, but in a restricted context where the agent has limited capabilities and tools.

  5. 5
    Human-in-the-loop

    Process all email but require human approval before the agent takes any action.

Begin with the strict allowlist and only loosen it if a use case demands it. Always verify the webhook signature before trusting a payload — see Verify webhooks.