ESP: Resend7 min read

Your React Email template renders locally. Does it land in inbox?

Resend + React Email gives you typed, componentised email. The preview server shows how it looks. Seeds show where Gmail, Outlook and Yahoo file it. One array entry covers both.

Resend is the modern, developer-focused email API: TypeScript SDK, clean REST endpoints, straightforward webhooks. Paired with React Email it lets you write email templates as React components and preview them in a local dev server. That workflow is a massive quality-of-life upgrade over editing HTML strings in .hbs files — but the preview server only answers one question: does this look right? It does not answer the more important one: will Gmail put this in Primary or Promotions?

TL;DR

Add seed addresses as a bcc array on the Resend emails.send() call. Your React Email template renders identically for real recipients and seeds. The seed results fill the gap the local preview cannot cover — real folder placement per provider.

Why the Resend workflow needs a seed layer

React Email's local preview renders your template with dummy data, inline-styles everything, and gives you a visual diff. What it cannot render is:

  • Gmail's classifier. The Promotions vs Primary call is made by Google on receipt, using headers, link density, image-to-text ratio, and sender reputation. No local preview can simulate this.
  • Outlook's junk filter. Outlook looks at authentication alignment, sender-domain reputation and content signals. Again, impossible locally.
  • Mobile-client rendering quirks. The preview shows desktop Chrome. Gmail iOS, Outlook Android, Apple Mail on a Watch — all render differently. Real seed screenshots catch issues the preview would never surface.

The one-array-entry change

Resend's emails.send() accepts bcc as a string or string array. Your existing React Email send looks like this:

import { Resend } from 'resend';
import { WelcomeEmail } from '@/emails/welcome';

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

export async function sendWelcome(user: { email: string; name: string }) {
  const { data, error } = await resend.emails.send({
    from: 'Acme <hello@acme.io>',
    to: user.email,
    subject: `Welcome to Acme, ${user.name}`,
    react: <WelcomeEmail name={user.name} />,
  });

  if (error) throw error;
  return data;
}

The seeded version adds a single field:

export async function sendWelcome(user: { email: string; name: string }) {
  const seeds = process.env.SEED_ADDRESSES?.split(',') ?? [];

  const { data, error } = await resend.emails.send({
    from: 'Acme <hello@acme.io>',
    to: user.email,
    bcc: seeds,                               // <- seed recipients
    subject: `Welcome to Acme, ${user.name}`,
    react: <WelcomeEmail name={user.name} />,
    headers: { 'X-Entity-Ref-ID': 'welcome-v3' },  // optional tag
  });

  if (error) throw error;
  return data;
}

Resend fans out the bcc server-side. The React Email component renders once; the resulting HTML goes to both the real recipient and every seed address. Your template props, inlining pipeline and CSS stay identical — the seed just receives the exact same bytes the user does.

Centralise in one helper

Do not sprinkle bcc: seeds through 20 call sites. Wrap every Resend call in a helper that decides per-template whether to seed:

type Template = 'welcome' | 'reset' | 'invoice' | 'digest';

const SEED_TEMPLATES: Record<Template, 'always' | 'sample' | 'never'> = {
  welcome: 'always',
  reset: 'always',
  invoice: 'always',
  digest: 'sample',
};

function seedsFor(template: Template): string[] {
  const policy = SEED_TEMPLATES[template];
  const all = process.env.SEED_ADDRESSES?.split(',') ?? [];
  if (policy === 'always') return all;
  if (policy === 'sample') return Math.random() < 0.05 ? all : [];
  return [];
}

export async function sendTemplate<T extends Template>(
  template: T,
  to: string,
  react: React.ReactElement,
  subject: string,
) {
  return resend.emails.send({
    from: 'Acme <hello@acme.io>',
    to,
    bcc: seedsFor(template),
    subject,
    react,
    tags: [{ name: 'template', value: template }],
  });
}

React Email preview vs seed test: they answer different questions

Both tools have their place. Keep them honest:

  1. Preview server answers: Does the component render without exploding, with the right copy, in the right layout? Use this in dev loop, storybook, PR reviews.
  2. Seed test answers: When Resend actually sends this through its MTA, which folder does Gmail/Outlook/Yahoo file it in, and what does it look like in iOS Gmail? Use this in staging and in production.
  3. Resend test mode (onboarding@resend.dev) answers: Does the API call succeed with my API key? It does not answer placement, because the test addresses route through Resend internals, not real providers.
Get 20+ seed addresses free

The free Inbox Check tool generates 20+ fresh seed addresses per test across Gmail, Outlook, Yahoo, Mail.ru, Yandex, ProtonMail and more. No signup, no credit card.

→ Run a free test now

Domain warm-up on Resend with seeds

Resend gives you a fresh sending domain the moment you verify DNS. That domain has zero reputation. Shipping 10,000 welcome emails on day one from a fresh domain is a reliable way to land in Gmail Spam for a month. Seeds let you warm up intelligently:

  • Day 1–3. Send only to seeds plus a handful of real internal users. Read placement; verify SPF/DKIM/DMARC align on the headers. Fix anything yellow.
  • Day 4–10. Scale to real traffic at 100–500 sends/day. Continue seeding 100% of sends. Watch for drift (Primary rate should stay above 85% at Gmail).
  • Day 11+. Ramp 2×/day until target volume. Keep seeds on — drop to sampling only after you have a week of clean placement above target volume.

Common mistakes with Resend seeding

  • Using Resend's sandbox address as a seed. It does not measure placement. It only confirms the API call works.
  • Seeding from an unverified domain. Resend will reject the send at the API. Verify the domain and wait for SPF/DKIM propagation first.
  • Forgetting to gate seeds behind env. A developer cloning your repo does not need to trigger seeds on every local test. Default SEED_ADDRESSES to empty in dev; set it only in staging/prod.
  • Treating React Email preview as deliverability proof. The preview confirms rendering, not placement. They are complementary, not a substitute.

Frequently asked questions

Does Resend charge per bcc recipient?

Yes. Resend bills per email sent, and each bcc recipient is one email. At 20 seeds on a 10K send/month app that is 200K extra emails. Sample on high-volume templates (digests, notifications) to control cost.

Will seeded React Email templates render identically for seed and real recipient?

Yes. The component renders once on the server, the resulting HTML is what Resend sends to both. Props are evaluated with your real user data; seeds receive the same rendered output.

Can I use Resend's audience feature instead of bcc for seeds?

You can, but it complicates reporting. Audiences are meant for marketing broadcast lists. For seed-testing transactional and per-user sends, bcc on the single send call is cleaner.

How do I stop seeds inflating my open-rate metrics?

Tag seeded sends with a tags: [{ name: 'has_seed', value: 'true' }] entry and filter it out in your analytics layer. Resend returns tags on every webhook event.
Related reading

Check your deliverability across 20+ providers

Gmail, Outlook, Yahoo, Mail.ru, Yandex, GMX, ProtonMail and more. Real inbox screenshots, SPF/DKIM/DMARC, spam engine verdicts. Free, no signup.

Run Free Test →

Unlimited tests · 20+ seed mailboxes · Live results · No account required