Guides
Send transactional email from defineApi handlers. Default Robodev SMTP or per-project custom SMTP.
Every defineApi handler receives an injected email client. Call email.send to deliver a transactional message through the project's active provider. New and existing projects start on Robodev (default) platform SMTP. Organization members can switch a project to custom SMTP from the dashboard Email page.
v1 is outbound only. There is no inbound mail, attachments, CC/BCC, or campaign builder. Edit Auth and custom templates on the project Email page — changes apply immediately, without Code save or deploy. Project-host register welcome, magic-link, and forgot-password mail use the Auth templates. Dashboard forgot-password uses platform SMTP and is not logged on the project Email page. Unlike Storage's serve-only GET /storage/objects/{key}, there is no reserved project-host /email route — api/email.ts is a normal handler. Hosted templates live on the Email page. Offline `robodev dev` can render optional `robodev/emails/{slug}.html` files; those files are not a deploy class.
email.send
Use it from defineApi only. to is required. Subject is required unless you pass template. At least one of html or text is required after template resolve. Max 50 recipients per send. If from is omitted, the active provider From is used.
- Success resolves { id, status: "sent" }. id is the dashboard log row.
- Failure writes a failed log, then throws. The handler 500s unless you catch, same as a db error.
- html and text bodies are never stored in logs.
- email.send({ template, to, vars }) loads a project template by slug, renders {{vars}}, then applies any explicit subject/html/text overrides.
- Missing slug throws template_not_found. A disabled template throws template_disabled and writes a failed log. Auth HTTP still succeeds when an Auth template is off; the mail is skipped and not logged.
Templates
- Auth templates are pre-registered: auth.welcome, auth.magic-link, auth.forgot-password. They cannot be deleted. They can be turned off.
- Custom slugs match ^[a-z][a-z0-9-]{0,62}$ and must not start with auth.
- When a template is off, it is not sent. There is no plaintext fallback.
- The Email page editor can generate HTML with Cursor. Generate does not publish the project.
Default vs custom
- Robodev (default) — platform SMTP from Starbase env. Missing settings row means Robodev.
- Custom SMTP — per-project host, port, username, password, from, and TLS. Stored in metadata, not the tenant database.
- Switching back to Robodev clears custom fields, including the password.
Dashboard
Open /projects/:id/email. Templates are the first section: edit Auth and custom HTML, preview without sending, disable a template, or generate with Cursor. Test the Robodev connection, or validate and save custom SMTP (validate does not persist; save persists only after verify succeeds). Sent attempts appear in a durable log: to, from, subject, status, provider, time, and error. Last 200 rows, newest first.
Operator env
Platform send and Robodev validate need SMTP_HOST and SMTP_FROM. Optional: SMTP_PORT (587), SMTP_USER, SMTP_PASS, SMTP_SECURE (true or 1 for implicit TLS, typically port 465). If those keys are unset, the dashboard still shows Robodev as the default; email.send and Robodev validate fail with a clear error, and custom SMTP still works.