The Dark Reality of Email HTML: Why Modern CSS Fails
Web browsers have standardized modern CSS Flexbox, Grid, CSS Variables, and responsive media queries. Email clients, however, remain trapped in legacy rendering engines. Microsoft Outlook on Windows still utilizes the Microsoft Word 2007 HTML rendering engine, which completely ignores flex containers, padding on divs, and web font declarations.
Historically, email developers were forced to manually handcraft complex nested <table> layouts with inline style attributes and VML (Vector Markup Language) conditional comments. React Email changes this by allowing engineers to write standard, componentized React with Tailwind CSS, which then compiles down into bulletproof, client-compatible email HTML.
1. Building a Responsive Invoice Template (InvoiceEmail.tsx)
Using @react-email/components and the <Tailwind> provider, you can design clean, modern transactional templates.
import { Html, Head, Body, Container, Section, Text, Button, Tailwind, Hr } from '@react-email/components';
import * as React from 'react';
interface InvoiceProps {
invoiceId: string;
customerName: string;
amount: string;
date: string;
downloadUrl: string;
}
export function InvoiceEmail({ invoiceId, customerName, amount, date, downloadUrl }: InvoiceProps) {
return (
<Html>
<Head />
<Tailwind>
<Body className="bg-zinc-950 font-sans text-zinc-100 p-8">
<Container className="max-w-[560px] mx-auto border border-zinc-800 p-6 rounded bg-zinc-900">
<Section className="border-b border-zinc-800 pb-4 mb-4">
<Text className="text-emerald-400 font-mono text-xs uppercase font-bold tracking-wider">
SadaSend Automated Receipt
</Text>
<Text className="text-2xl font-bold mt-1 text-white">Invoice #{invoiceId}</Text>
<Text className="text-zinc-400 text-sm mt-1">Billed to: {customerName}</Text>
</Section>
<Section className="py-2">
<Text className="text-zinc-300 text-sm">
Amount Paid: <strong className="text-emerald-400 text-base">{amount}</strong>
</Text>
<Text className="text-zinc-300 text-sm">
Date: <strong className="text-white">{date}</strong>
</Text>
</Section>
<Hr className="border-zinc-800 my-4" />
<Section className="pt-2">
<Button
href={downloadUrl}
className="bg-emerald-500 text-black px-6 py-3 rounded text-sm font-semibold text-center block"
>
Download PDF Receipt →
</Button>
</Section>
</Container>
</Body>
</Tailwind>
</Html>
);
}2. Rendering to HTML and Dispatching with SadaSend
Use @react-email/render inside your server action or backend microservice to compile the React tree into an HTML string for the API payload.
import { render } from '@react-email/render';
import { InvoiceEmail } from './InvoiceEmail';
export async function sendInvoice(email: string, invoice: any) {
const html = await render(InvoiceEmail({
invoiceId: invoice.id,
customerName: invoice.customerName,
amount: '$49.00',
date: 'October 9, 2026',
downloadUrl: `https://app.sadasend.com/invoices/${invoice.id}`,
}));
const res = await fetch('https://api.sadasend.com/emails', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.SADASEND_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
to: email,
subject: `Invoice #${invoice.id} from SadaSend`,
html,
text: `Your invoice #${invoice.id} for $49.00 is ready.`,
}),
});
return await res.json();
}Building AI agents that send email?
Scoped API keys, per-key recipient allowlists, approval mode and a hosted MCP server with ten tools — on the free plan, without a card.