Email clone

Resend, SendGrid v3, and SMTP capture — send, inbox, bounce simulation.

Email clone

Capture outbound email across Resend, SendGrid v3, and SMTP in one clone — inspect inboxes, simulate bounces and spam traps, and advance the virtual clock for domain verification and delivery.

Clone ID: email · Binary: clones-email · SDK: email · Registry alias: sendgrid · Dashboard: Email explorer

Start here

QuestionAnswer
Best forWelcome emails, password reset, receipts, SendGrid dynamic templates, and bounce paths
Connect withResend/SendGrid SDK pointed at clone URL, route mode for api.sendgrid.com / api.resend.com, SMTP to port 1025, or MCP inbox tools
Known limitsNo delivery to the real internet — all messages stay in the clone
SeedsEmpty by default; seed domains via JSON or create them over REST

Quick start

import { email } from "@molar/clones";

const clone = await email.start({ seed: "welcome-flow", runId: "run-email-01" });

await clone.send({
  from: "hello@example.com",
  to: ["user@example.com"],
  subject: "Welcome to Pro",
  html: "<p>Thanks!</p>",
});

await clone.advanceClock("5s");
const messages = await clone.inbox("user@example.com");

MCP tools

ToolDescription
molar_clone_spawnSpawn Email clone (kind: "email", optional seed)
email_inboxRead captured messages for a recipient (adminUrl, runId, recipient)
email_mark_bounceMark recipient as hard-bounced for deliverability tests

REST API coverage

Provider shapeEndpoints
ResendPOST /emails, POST /emails/batch, GET /emails, GET /emails/:id
Resend domainsPOST /domains, list/get/delete; status moves to verified on clock advance
Resend audiencesPOST /audiences, POST /audiences/:id/contacts
SendGrid v3POST /v3/mail/send with dynamic_template_data rendering
SMTPMailpit-compatible capture on 127.0.0.1:1025 (raw messages land in the same inbox)
Mailpit-compatGET /api/v1/messages, POST /api/v1/chaos
AdminInbox list, bounce/spam-trap flags

Set RESEND_API_KEY or SendGrid key to the derived test key from the SDK spawn response.

Seeds and initial state

There is no bundled welcome seed. Typical patterns:

// Seed a verified domain via admin JSON
await clone.adminPost(`/_clone/seed?runId=${clone.runId}`, {
  domains: [{ name: "example.com" }],
});

// Or create via REST
await clone.request("/domains", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({ name: "example.com" }),
});
await clone.advanceClock("1m");

Dashboard preset Checkout Stripe + Receipt pairs stripe + email for payment confirmation mail.

Limits

LimitDetail
AttachmentsIn-memory per message
Multi-recipientSupported; inbox keyed by to address
Delivery timingAdvance clock after send to reach delivered
Cross-cloneCheckout receipt (stripe + email), password reset (auth + email) — Scenarios

Inbox & bounce

await clone.markBounce("bad@example.com");
await clone.markSpamTrap("trap@spam.org");
const inbox = await clone.inbox("user@example.com");

Environment variables

MOLAR_CLONE_EMAIL_URL, MOLAR_CLONE_EMAIL_ADMIN_URL, RESEND_API_KEY (derived test key)