Resend is the developer-first email API — small SDK, generous free tier, real HTML templates. Setup takes ten minutes once you accept that the slow part is configuring DNS for your domain, not writing code.
Sending email from a web app is one of those things that's easy until you actually need to do it. You write a small function that POSTs to an email provider's API. Your test message goes out. It lands in your Gmail inbox. Done. Then production traffic kicks in and the mail starts landing in spam. Or worse, getting rejected by recipient servers entirely. The code is identical; the problem isn't the code.
Email deliverability is mostly a function of three DNS records — SPF, DKIM, and DMARC — that tell receiving servers "yes, this provider is authorized to send mail on behalf of this domain, here's how to verify it." Without them set, modern receivers (Gmail, Apple Mail, Outlook) at best put your mail in spam and at worst reject it. Setting them up is annoying because they have to live on the domain you're sending from, which means changing DNS at your registrar, which means waiting for propagation.
Resend's value proposition is "the email API where this whole dance is the easiest." The dashboard tells you exactly which DNS records to add and verifies them automatically. The SDK is small. The free tier (3,000 emails/month, 100/day) is enough for almost any indie project. Their HTML template story uses React components, which is unusual in this space and notably nicer than dragging a WYSIWYG editor around. This tutorial covers the setup; the principles apply to any modern email provider (Postmark, SendGrid, Loops, etc.) — the specifics are Resend-shaped.
You should send mail from a domain you own — [email protected], not [email protected]. There are two reasons:
If you don't have a domain yet, see the registrar tutorials. You can also use a subdomain dedicated to transactional mail — mail.yourapp.com or notifications.yourapp.com — which is good practice because it isolates your sending reputation from anything else on the root domain.
Sign up. The free tier gives you 3,000 emails per month and 100 per day, sent from the shared [email protected] domain. That's enough to test the SDK; it's not enough to ship to real users (because mail from resend.dev won't look like it's from you, and recipients may suspect it).
To send from your own domain you need to add and verify it. That's the next step.
Click Add Domain, type the domain (or subdomain) you'll send from, click Add. Resend shows you a list of DNS records to add. Typically 3–5 records: one for SPF, two or three for DKIM (depending on configuration), optionally one for DMARC, and an MX record if you want to also receive bounce notifications back through Resend.
The records look intimidating but you don't need to understand the cryptography — just copy each one verbatim into your DNS provider.
For each record Resend shows, go to your DNS provider (see the DNS tutorial if needed) and add:
resend; others want resend.yourdomain.com. Either format is fine if used consistently.After adding all records, click Verify DNS Records in Resend. Propagation can take minutes to hours. Resend re-checks automatically; you'll get a "verified" status when all records resolve correctly.
_dmarc) tells receivers what to do when SPF or DKIM fail — quarantine, reject, or just report. Together they're the modern "yes, this mail is legitimate" handshake.
Click Create API Key, name it (e.g., "production"), choose permissions (typically Sending access — restricted scope is better than full access). Copy the key (re_…); you only see it once.
Put it in your backend's env file: RESEND_API_KEY=re_…. As always, never commit to git.
Install the SDK in your project:
npm install resend
# or: pip install resend, or: gem install resend
Send a test email:
import { Resend } from 'resend';
const resend = new Resend(process.env.RESEND_API_KEY);
await resend.emails.send({
from: 'You <[email protected]>',
to: ['[email protected]'],
subject: 'Hello from Resend',
html: '<p>This is the body of the email.</p>',
});
Check your recipient inbox. If it arrives, you're done. If it doesn't, check the Resend dashboard's Emails log — it shows every send attempt with its status (delivered, bounced, spam-folder, etc.) and the receiver's response.
For one-off emails, raw HTML strings work fine. For anything you'll send repeatedly (welcome emails, receipts, password resets), use templates. Resend's official option is React Email — write your email as a React component, render it to HTML at send time.
import { Resend } from 'resend';
import { ReceiptEmail } from './emails/Receipt';
await resend.emails.send({
from: 'Receipts <[email protected]>',
to: customer.email,
subject: `Receipt for $${amount}`,
react: ReceiptEmail({ customerName: customer.name, amount, items }),
});
React Email components have email-safe primitives (<Container>, <Text>, <Button>) that render to the table-based HTML email clients require. You write modern JSX; the library handles the legacy markup.
Mail in spam usually means one of these is true:
From domain doesn't match your DKIM domain. If you set up DKIM for mail.yourdomain.com but send from [email protected], the DKIM signature doesn't authorize the From. Either send from [email protected] or set up DKIM for the root.mail-tester.com — it'll give you a score and explain why.