LaunchverseLaunchverse
ProductPricingMarketplaceDocsCareersTemplates
Log inStart free
Start free
All guides
Tutorial/ 9 min read/8 May 2026

Send Transactional Emails from a Launchverse App: SMTP, Resend, and Postmark

How to wire transactional emails (signups, receipts, password resets) into a Launchverse application — covers SMTP, Resend, Postmark, and the deliverability mistakes that send your mail to spam.

The first feature most apps need after signup-and-login is "send the user an email when X happens." It's also the feature where new applications most commonly stub their toe — emails go to spam, deliverability is invisible, and the bounce rate quietly tanks before anyone notices.

This guide covers the practical setup for sending transactional email from a Launchverse application: which provider to choose, how to wire it, and the DNS records you must set so your mail actually arrives.

Why you can't sendmail directly

In theory, your container can SMTP straight to the recipient's mail server (gmail-smtp-in.l.google.com for @gmail.com). In practice, every major mail provider:

  • Blocks unsolicited connections from cloud IPs (your container has one).
  • Demands authenticated, signed mail (DKIM + SPF + DMARC).
  • Rate-limits unknown senders aggressively.

Run-your-own-SMTP works for ops mail to your own domain inside one corporate network. For real customer mail, you go through a provider whose IPs are known-good and whose mail is signed correctly. The good ones charge cents per thousand messages.

Choosing a provider

ProviderSweet spotFree tierNotes
ResendModern API, great DX3,000 / monthBuilt for the JS ecosystem, has React Email support
PostmarkPremium deliverability100 / month, then $$Premium reputation, great for high-stakes mail
MailgunVolume + EU regionsPay-as-you-goSolid all-rounder, dashboard is dated
SendGridEstablished, large volume100 / dayStrong volume tooling, occasionally flaky support
AWS SESCheapest at scaleFirst 62,000 / month free if from EC2Cheapest dollar-per-thousand; UI is bare
Plain SMTP via Brevo / SendGridLegacy systems / WordPressVariesIf your stack only speaks SMTP

The 80/20 recommendation in 2026: Resend for new projects, Postmark for projects where deliverability matters more than the bill. Both have enough free volume to validate without committing.

DNS records you absolutely must set

Three records make your mail "real" in the eyes of receiving servers:

1. SPF — who is allowed to send mail as your domain?

A TXT record on your sending domain (e.g. example.com):

TXT @  "v=spf1 include:_spf.<provider>.com -all"

Replace <provider> with the provider's published include (Resend: _spf.resend.com; SendGrid: sendgrid.net; etc.).

2. DKIM — cryptographically sign each message

The provider gives you a CNAME or TXT record per signing key (typically two). They look like:

CNAME resend._domainkey  resend._domainkey.resend.com
CNAME resend2._domainkey resend2._domainkey.resend.com

Add them exactly as the provider says. Once these resolve, the provider can sign messages on your behalf and Gmail / Outlook will display them as "from you, signed by Resend."

3. DMARC — policy when SPF/DKIM fail

A TXT record on _dmarc.example.com:

TXT _dmarc "v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com"

Start with p=quarantine. After a few weeks of clean reports, escalate to p=reject. The rua address gets aggregate reports from receiving servers — useful when you're wondering why a customer says "I never get your emails."

Without these three records, your mail goes to spam. It's not optional.

Wiring it into a Launchverse app (Node + Resend)

// app/api/auth/welcome/route.ts
import { Resend } from "resend";

const resend = new Resend(process.env.RESEND_API_KEY);

export async function POST(req: Request) {
  const { to, name } = await req.json();
  const { data, error } = await resend.emails.send({
    from: "Launchverse <hello@example.com>",
    to: [to],
    subject: `Welcome, ${name}!`,
    html: `<p>Thanks for signing up.</p>`,
  });
  if (error) return Response.json({ error: error.message }, { status: 500 });
  return Response.json({ id: data?.id });
}

Set RESEND_API_KEY in Launchverse → Settings → Environment Variables. Restart the project. Test with a real recipient (not a @example.com address — providers blackhole those).

Wiring it via plain SMTP (Python + any provider)

If your stack is more SMTP-shaped:

import os, smtplib, ssl
from email.message import EmailMessage

msg = EmailMessage()
msg["From"] = "hello@example.com"
msg["To"] = recipient
msg["Subject"] = subject
msg.set_content(body_text)

with smtplib.SMTP(os.environ["SMTP_HOST"], 587) as s:
    s.starttls(context=ssl.create_default_context())
    s.login(os.environ["SMTP_USER"], os.environ["SMTP_PASS"])
    s.send_message(msg)

Set the four env vars in Launchverse: SMTP_HOST, SMTP_USER, SMTP_PASS, plus the From address.

Don't send from a free domain

Don't use gmail.com / outlook.com / yahoo.com as your From address. Even with SPF / DKIM / DMARC perfectly set up on your domain, a From: someone@gmail.com is a different domain that you don't control, and DMARC will fail.

Use a domain you own. If you don't have one, buy a .com for $10 — it pays for itself the first month.

Test deliverability

After setup:

  1. Send a test email to mail-tester.com (their UI shows you a free score out of 10).
  2. Send to a Gmail account, an Outlook account, and a Proton account. Check that all three arrive in inbox (not spam, not Promotions).
  3. Mark a few as "Important" / "Not spam" — early reputation matters.
  4. Set up basic monitoring: a once-a-day cron that sends a known message to a known mailbox and alerts if it bounces.

Bounces, complaints, and unsubscribes

Three signals you need to track:

  • Hard bounces (mailbox doesn't exist). Stop sending immediately; over ~5% bounce rate gets you blacklisted.
  • Complaints (recipient marked you as spam). Stop sending to that recipient forever; even legitimate transactional mail to them is now contributing to your spam reputation.
  • Soft bounces (mailbox full, temporary). Retry with backoff (your provider does this for you).

Most providers expose webhooks for these events. Wire them to your user database — when complaint fires for user@example.com, set email_unsubscribed = true and never send to them again.

Deliverability checklist

CheckStatus
Custom domain (not gmail.com)✓
SPF record✓
DKIM signing✓
DMARC at quarantine or reject✓
From matches signing domain✓
Plain-text alternative in multipart messages✓
Unsubscribe link on marketing mail✓
Bounce handling✓
Complaint handling✓
Production sending tested with mail-tester.com✓

If you can tick all 10, you're a deliverability outlier in a good way.

Further reading

  • Environment variables and secrets on a modern PaaS
  • Web App Firewall, HTTPS, and egress allowlists
  • Set up a custom domain on Launchverse

Ready to deploy?

Start free in Naira — no card required, no FX surprises.

Start deploying free See pricingFAQ

Have feedback or a topic to suggest? Talk to us.

The launchpad for your next product. Self-serve infrastructure, custom domains, instant rollbacks.

Launchverse - Faster deployment, honest pricing | Product Hunt

Company

  • About Us
  • Careers
  • Contact

Resources

  • Documentation
  • API Reference
  • Support
  • Use Cases
  • Templates
  • Marketplace
  • Quick Start
  • Guides
  • FAQ
  • Changelog
  • Status

Legal

  • 01 Terms of Service
  • 02 Privacy Policy
  • 03 Security

© 2026 Launchverse. Engineered with precision.

System Status:
Operational