AI app builder
Updated
Add email to your Bolt app with Lumail
Bolt can scaffold anything from a Vite single-page app to a full-stack framework. Email needs a server, so the prompt has to say where the send runs, and the key has to stay out of anything prefixed `VITE_`.
TL;DR
LUMAIL_API_KEY from .env, sends a contact-form message to your own inbox with reply_to set to the visitor, and uses an idempotency key.1. Prompt Bolt
The example is a contact form, because it is the first email most Bolt apps need and it only ever emails you. Swap the first task at the end of the prompt for a welcome email once you have auth.
2. Put the API key in the right place
Create a lum_ token in Lumail under API tokens and add it to the project's .env. Anything starting with VITE_ is bundled into the browser code, so the Lumail key must never use that prefix.
When you deploy, set LUMAIL_API_KEY, LUMAIL_FROM and CONTACT_TO in your host's environment variables too. A deployed app does not read your local .env.
3. The code Bolt should generate
Here is the route for a project with a Node server (Express shown). In a framework, the same body goes in its server route or action; on a static host, in its function format. The shape stays the same: validate, send with reply_to, check error.
4. Lumail MCP server and agent plugins
Bolt builds and hosts your app in the cloud, so your app talks to Lumail through the API with a token, not through MCP. The Lumail MCP server is for agents that run where you work: Claude Code, Codex, ChatGPT, Cursor or the Lumail CLI.
That split is useful once the app is live. Ask Claude Code or ChatGPT to check your domain's DNS status, look up a subscriber who did not get their email, or draft the next newsletter, while the app keeps sending through the API.
- Lumail for AI agents - Every way an agent can work with Lumail.
- In-app integration - One prompt that wires Lumail into a codebase.
- Claude Code plugin - MCP server and skill for Claude Code.
- Codex plugin - MCP server and skill for OpenAI Codex.
- ChatGPT app - Drive Lumail from a ChatGPT conversation.
- Lumail CLI - Terminal access for scripts and agents.
5. Verify your sending domain
Lumail only sends from a domain you have verified. Add the domain in your organization's Domains settings, then publish the SPF, DKIM and DMARC records it shows at your DNS provider. Until the domain verifies, every send fails with an error saying the domain is not authorized or verified.
Use a subdomain such as mail.yourdomain.com if your root domain already sends from another provider. Start DMARC at p=none, then tighten it once reports look clean.
- Email domains - Add a domain and the SPF, DKIM and DMARC records.
- Add a DMARC record - Publish a policy, then tighten it safely.
- Mail tester - Send a real email and check authentication and spam signals.
Common pitfalls
- `VITE_LUMAIL_API_KEY`. If the AI adds the prefix to make the key "work" in a component, the key is now public. Rotate it and move the call to a server route.
- Works in preview, fails in production. The deployed app needs its own environment variables. Set them on the host and redeploy.
- Unescaped HTML. Form input dropped straight into
htmllets visitors inject markup into your inbox. Strip or escape it, or sendtextonly. - Client-side sends. If the AI imports
lumailin a React component or usesfetchto the Lumail API from the browser, the key ships to every visitor. Move it to a server route or function and rotate the token. - Unverified `from` domain. Sends from a domain that is not verified in the same organization are rejected with a 400 that names the domain. Verify it first, or use the exact address Lumail shows you.
- Treating `{ error }` as an exception. The SDK never throws on HTTP errors. Code that only wraps the call in
try/catchsilently drops failures. - Duplicate emails on retry. Without an idempotency key, a retried request or double-clicked button can send twice.
Frequently asked questions
Can a Bolt app send email from the front end?
No. A key in front-end code, including any VITE_ variable, is readable by every visitor. Send from a server route or a serverless function.
My Bolt project has no server. What should I do?
Ask Bolt to add a serverless function for the host you deploy to, or a Supabase Edge Function if the project uses Supabase. The function reads LUMAIL_API_KEY and calls the Lumail SDK or REST API.
Why send contact form messages to myself instead of the visitor?
Because a public endpoint that emails any address it is given can be abused to send spam from your domain. Sending to your own CONTACT_TO address with reply_to set to the visitor is safe and lets you answer from your inbox.
How much does it cost to send these emails?
The Free plan includes 3,000 emails a month. Premium is $20 a month for 40,000 emails, then $0.60 per 1,000. Subscribers are unlimited on every plan.
Can I use the Lumail MCP server with Bolt?
Bolt runs in the cloud, so connect the MCP server to a local agent such as Claude Code, Codex, ChatGPT or Cursor instead. The Bolt app keeps sending through the API.
Keep building
- AI app builderAdd email to your Lovable appA Supabase Edge Function that sends with Lumail, with the API key stored as a function secret.
- AI app builderAdd email to your v0 appA Next.js server action that sends with Lumail, with the key in project env vars, never NEXT_PUBLIC_.
- AI app builderAdd email to your Replit appReplit Agent prompt for Node or Python, with the API key in Secrets and checked on the deployment.
- GuideSend emails from Node.jsScripts, Express and batch sends.
- DocsCreate an API tokenMint a lum_ token scoped to one organization.
- DocsTest-mode recipientsFixture addresses that never send real email.
- DocsVerify a sending domainDNS records and verification steps.
- Free toolMail testerCheck SPF, DKIM, DMARC and spam signals on a real send.
Ship email from your Bolt app today.
3,000 emails a month free. Transactional and marketing email on one verified domain, with unlimited subscribers on every plan.