React Email adapter for VeilMail — render React Email components to HTML and send them via the VeilMail SDK.
Drop-in replacement for
@react-email/renderwhen paired with Veil Mail. If you're migrating from Resend or another provider that uses React Email, your existing components work unmodified — just swap the render call and point at the VeilMail client. Includesrender(),renderDual()(HTML + plain text in one call), andcreateEmail()helpers.import { VeilMail } from '@resonia/veilmail-sdk' import { render } from '@resonia/react-email' import { WelcomeEmail } from './emails/welcome' const client = new VeilMail('veil_live_xxxxx') const html = await render(WelcomeEmail({ name: 'Alice' })) await client.emails.send({ from, to, subject: 'Welcome', html })Related: Veil Mail Node.js SDK · React Email docs · Migrating from Resend
# npm
npm install @resonia/react-email @react-email/render react react-dom
# pnpm
pnpm add @resonia/react-email @react-email/render react react-dom
# yarn
yarn add @resonia/react-email @react-email/render react react-dom
# bun
bun add @resonia/react-email @react-email/render react react-domOptionally install @react-email/components for pre-built email components:
npm install @react-email/componentsDefine a React Email component, render it, and send it through the VeilMail SDK:
// emails/welcome.tsx
import { Html, Head, Body, Container, Text, Button } from '@react-email/components';
interface WelcomeEmailProps {
name: string;
loginUrl: string;
}
export function WelcomeEmail({ name, loginUrl }: WelcomeEmailProps) {
return (
<Html>
<Head />
<Body style={{ fontFamily: 'Arial, sans-serif', backgroundColor: '#f4f4f5' }}>
<Container style={{ padding: '40px 20px', maxWidth: '560px', margin: '0 auto' }}>
<Text style={{ fontSize: '24px', fontWeight: 'bold' }}>
Welcome, {name}!
</Text>
<Text style={{ fontSize: '16px', color: '#3f3f46' }}>
Thanks for signing up. Click the button below to get started.
</Text>
<Button
href={loginUrl}
style={{
backgroundColor: '#18181b',
color: '#ffffff',
padding: '12px 24px',
borderRadius: '6px',
fontSize: '14px',
textDecoration: 'none',
}}
>
Get Started
</Button>
</Container>
</Body>
</Html>
);
}// send.ts
import { VeilMail } from '@resonia/veilmail-sdk';
import { createEmail } from '@resonia/react-email';
import { WelcomeEmail } from './emails/welcome';
const client = new VeilMail({ apiKey: 'veil_live_xxx' });
const payload = await createEmail(
<WelcomeEmail name="John" loginUrl="https://app.example.com/login" />,
{
from: 'Acme <hello@acme.com>',
to: 'john@example.com',
subject: 'Welcome to Acme!',
}
);
const email = await client.emails.send(payload);
console.log('Sent:', email.id);Render a React Email component to an HTML string (or plain text).
import { render } from '@resonia/react-email';
// HTML output
const html = await render(<WelcomeEmail name="John" />);
// Plain text output
const text = await render(<WelcomeEmail name="John" />, { plainText: true });Parameters:
| Parameter | Type | Description |
|---|---|---|
component |
ReactElement |
A React Email component to render |
options.plainText |
boolean |
Render as plain text instead of HTML. Default: false |
Returns: Promise<string>
Render a React Email component and return both HTML and plain text versions in a single call.
import { renderDual } from '@resonia/react-email';
const { html, text } = await renderDual(<WelcomeEmail name="John" />);Parameters:
| Parameter | Type | Description |
|---|---|---|
component |
ReactElement |
A React Email component to render |
Returns: Promise<{ html: string; text: string }>
Render a React Email component and combine the result with VeilMail send parameters into a payload that can be passed directly to client.emails.send().
import { VeilMail } from '@resonia/veilmail-sdk';
import { createEmail } from '@resonia/react-email';
const client = new VeilMail({ apiKey: 'veil_live_xxx' });
const payload = await createEmail(
<WelcomeEmail name="John" />,
{
from: 'hello@acme.com',
to: 'john@example.com',
subject: 'Welcome!',
tags: ['onboarding'],
metadata: { userId: 'usr_123' },
}
);
await client.emails.send(payload);Parameters:
| Parameter | Type | Description |
|---|---|---|
component |
ReactElement |
A React Email component to render |
params |
VeilMailEmailProps |
Email send parameters (see below) |
Returns: Promise<VeilMailEmailProps & { html: string; text: string }>
The send parameters accepted by createEmail. These mirror the VeilMail SDK's SendEmailParams (excluding html and text, which are generated from the component).
| Property | Type | Required | Description |
|---|---|---|---|
from |
string |
Yes | Sender address ("Name <email>" or just email) |
to |
string | string[] |
Yes | Recipient address(es) |
subject |
string |
Yes | Email subject line |
cc |
string | string[] |
No | CC recipients |
bcc |
string | string[] |
No | BCC recipients |
replyTo |
string |
No | Reply-to address |
headers |
Record<string, string> |
No | Custom email headers |
tags |
string[] |
No | Tags for categorization |
scheduledFor |
string |
No | Scheduled send time (ISO 8601) |
metadata |
Record<string, unknown> |
No | Custom metadata |
idempotencyKey |
string |
No | Idempotency key to prevent duplicate sends |
If you only need the rendering utilities without the VeilMail SDK:
import { render, renderDual } from '@resonia/react-email';
const html = await render(<MyEmail />);
// or
const { html, text } = await renderDual(<MyEmail />);import { VeilMail } from '@resonia/veilmail-sdk';
import { renderDual } from '@resonia/react-email';
import { InviteEmail } from './emails/invite';
const client = new VeilMail({ apiKey: 'veil_live_xxx' });
const users = [
{ email: 'alice@example.com', name: 'Alice' },
{ email: 'bob@example.com', name: 'Bob' },
];
const emails = await Promise.all(
users.map(async (user) => {
const { html, text } = await renderDual(<InviteEmail name={user.name} />);
return {
from: 'team@acme.com',
to: user.email,
subject: `You're invited, ${user.name}!`,
html,
text,
};
})
);
await client.emails.sendBatch(emails);import { createEmail } from '@resonia/react-email';
const payload = await createEmail(
<ReminderEmail name="John" eventName="Webinar" />,
{
from: 'events@acme.com',
to: 'john@example.com',
subject: 'Reminder: Webinar Tomorrow',
scheduledFor: '2026-02-01T09:00:00Z',
}
);
await client.emails.send(payload);| Package | Version | Required |
|---|---|---|
@react-email/render |
>=0.0.12 |
Yes |
react |
>=18.0.0 |
Yes |
react-dom |
>=18.0.0 |
Yes |
@react-email/components |
>=0.0.15 |
No (optional) |
MIT