react-email
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseReact Email
React Email
Build and send HTML emails using React components - a modern, component-based approach to email development that works across all major email clients.
使用React组件构建并发送HTML邮件——这是一种现代化的、基于组件的邮件开发方式,可在所有主流邮件客户端中正常显示。
Installation
安装
You need to scaffold a new React Email project using the create-email CLI. This will create a folder called with sample email templates.
react-email-starterUsing npm:
sh
npx create-email@latestUsing yarn:
sh
yarn create emailUsing pnpm:
sh
pnpm create emailUsing bun:
sh
bun create email你需要使用create-email CLI搭建一个新的React Email项目。这将创建一个名为的文件夹,其中包含示例邮件模板。
react-email-starter使用npm:
sh
npx create-email@latest使用yarn:
sh
yarn create email使用pnpm:
sh
pnpm create email使用bun:
sh
bun create emailNavigate to Project Directory
进入项目目录
You must change into the newly created project folder:
sh
cd react-email-starter你必须切换到新创建的项目文件夹中:
sh
cd react-email-starterInstall Dependencies
安装依赖
You need to install all project dependencies before running the development server.
Using npm:
sh
npm installUsing yarn:
sh
yarnUsing pnpm:
sh
pnpm installUsing bun:
sh
bun install在运行开发服务器之前,你需要安装所有项目依赖。
使用npm:
sh
npm install使用yarn:
sh
yarn使用pnpm:
sh
pnpm install使用bun:
sh
bun installStart the Development Server
启动开发服务器
Your task is to start the local preview server to view and edit email templates.
Using npm:
sh
npm run devUsing yarn:
sh
yarn devUsing pnpm:
sh
pnpm devUsing bun:
sh
bun dev你的任务是启动本地预览服务器,以查看和编辑邮件模板。
使用npm:
sh
npm run dev使用yarn:
sh
yarn dev使用pnpm:
sh
pnpm dev使用bun:
sh
bun devVerify Installation
验证安装
Confirm the development server is running by checking that localhost:3000 is accessible. The server will display a preview interface where you can view email templates from the folder.
emails通过检查localhost:3000是否可访问,确认开发服务器正在运行。服务器将显示一个预览界面,你可以在其中查看文件夹中的邮件模板。
emailsNotes on installation
安装注意事项
Assuming React Email is installed in an existing project, update the top-level package.json file with a script to run the React Email preview server.
json
{
"scripts": {
"email": "email dev --dir emails --port 3000"
}
}Make sure the path to the emails folder is relative to the base project directory.
如果是在现有项目中安装React Email,请在顶层package.json文件中添加一个脚本,用于运行React Email预览服务器。
json
{
"scripts": {
"email": "email dev --dir emails --port 3000"
}
}确保emails文件夹的路径相对于基础项目目录。
tsconfig.json updating or creation
更新或创建tsconfig.json
Ensure the tsconfig.json includes proper support for jsx.
确保tsconfig.json包含对jsx的适当支持。
Basic Email Template
基础邮件模板
Replace the sample email templates. Here is how to create a new email template:
Create an email component with proper structure using the Tailwind component for styling:
tsx
import {
Html,
Head,
Preview,
Body,
Container,
Heading,
Text,
Button,
Tailwind,
pixelBasedPreset
} from '@react-email/components';
interface WelcomeEmailProps {
name: string;
verificationUrl: string;
}
export default function WelcomeEmail({ name, verificationUrl }: WelcomeEmailProps) {
return (
<Html lang="en">
<Tailwind
config={{
presets: [pixelBasedPreset],
theme: {
extend: {
colors: {
brand: '#007bff',
},
},
},
}}
>
<Head />
<Preview>Welcome - Verify your email</Preview>
<Body className="bg-gray-100 font-sans">
<Container className="max-w-xl mx-auto p-5">
<Heading className="text-2xl text-gray-800">
Welcome!
</Heading>
<Text className="text-base text-gray-800">
Hi {name}, thanks for signing up!
</Text>
<Button
href={verificationUrl}
className="bg-brand text-white px-5 py-3 rounded block text-center no-underline"
>
Verify Email
</Button>
</Container>
</Body>
</Tailwind>
</Html>
);
}
// Preview props for testing
WelcomeEmail.PreviewProps = {
name: 'John Doe',
verificationUrl: 'https://example.com/verify/abc123'
} satisfies WelcomeEmailProps;
export { WelcomeEmail };替换示例邮件模板。以下是创建新邮件模板的方法:
使用Tailwind组件创建具有适当结构的邮件组件以进行样式设置:
tsx
import {
Html,
Head,
Preview,
Body,
Container,
Heading,
Text,
Button,
Tailwind,
pixelBasedPreset
} from '@react-email/components';
interface WelcomeEmailProps {
name: string;
verificationUrl: string;
}
export default function WelcomeEmail({ name, verificationUrl }: WelcomeEmailProps) {
return (
<Html lang="en">
<Tailwind
config={{
presets: [pixelBasedPreset],
theme: {
extend: {
colors: {
brand: '#007bff',
},
},
},
}}
>
<Head />
<Preview>Welcome - Verify your email</Preview>
<Body className="bg-gray-100 font-sans">
<Container className="max-w-xl mx-auto p-5">
<Heading className="text-2xl text-gray-800">
Welcome!
</Heading>
<Text className="text-base text-gray-800">
Hi {name}, thanks for signing up!
</Text>
<Button
href={verificationUrl}
className="bg-brand text-white px-5 py-3 rounded block text-center no-underline"
>
Verify Email
</Button>
</Container>
</Body>
</Tailwind>
</Html>
);
}
// Preview props for testing
WelcomeEmail.PreviewProps = {
name: 'John Doe',
verificationUrl: 'https://example.com/verify/abc123'
} satisfies WelcomeEmailProps;
export { WelcomeEmail };Essential Components
核心组件
See references/COMPONENTS.md for complete component documentation.
Core Structure:
- - Root wrapper with
Htmlattributelang - - Meta elements, styles, fonts
Head - - Main content wrapper
Body - - Centers content (max-width layout)
Container - - Layout sections
Section - &
Row- Multi-column layoutsColumn - - Enables Tailwind CSS utility classes
Tailwind
Content:
- - Inbox preview text, always first in
PreviewBody - - h1-h6 headings
Heading - - Paragraphs
Text - - Styled link buttons
Button - - Hyperlinks
Link - - Images (see Static Files section below)
Img - - Horizontal dividers
Hr
Specialized:
- - Syntax-highlighted code
CodeBlock - - Inline code
CodeInline - - Render markdown
Markdown - - Custom web fonts
Font
完整的组件文档请参见references/COMPONENTS.md。
核心结构:
- - 带有
Html属性的根包装器lang - - 元元素、样式、字体
Head - - 主内容包装器
Body - - 居中内容(最大宽度布局)
Container - - 布局区块
Section - &
Row- 多列布局Column - - 启用Tailwind CSS工具类
Tailwind
内容组件:
- - 收件箱预览文本,必须放在
Preview的最前面Body - - h1-h6标题
Heading - - 段落
Text - - 样式化链接按钮
Button - - 超链接
Link - - 图片(请参见下方的静态文件部分)
Img - - 水平分隔线
Hr
特殊组件:
- - 语法高亮代码块
CodeBlock - - 行内代码
CodeInline - - 渲染Markdown内容
Markdown - - 自定义网络字体
Font
Before Writing Code
编码前准备
When a user requests an email template, ask clarifying questions FIRST if they haven't provided:
- Brand colors - Ask for primary brand color (hex code like #007bff)
- Logo - Ask if they have a logo file and its format (PNG/JPG only - warn if SVG/WEBP)
- Style preference - Professional, casual, or minimal tone
- Production URL - Where will static assets be hosted in production?
Example response to vague request:
Before I create your email template, I have a few questions:
- What is your primary brand color? (hex code)
- Do you have a logo file? (PNG or JPG - note: SVG and WEBP don't work reliably in email clients)
- What tone do you prefer - professional, casual, or minimal?
- Where will you host static assets in production? (e.g., https://cdn.example.com)
当用户请求邮件模板时,如果他们未提供以下信息,请先询问澄清问题:
- 品牌颜色 - 询问主品牌颜色(如#007bff这样的十六进制代码)
- Logo - 询问是否有Logo文件及其格式(仅支持PNG/JPG - 若为SVG/WEBP需提醒用户)
- 风格偏好 - 专业风、休闲风还是极简风
- 生产环境URL - 静态资源将在生产环境中托管在哪里?
对模糊请求的示例回复:
在为你创建邮件模板之前,我有几个问题:
- 你的主品牌颜色是什么?(十六进制代码)
- 你有Logo文件吗?(仅支持PNG或JPG - 注意:SVG和WEBP在邮件客户端中无法可靠显示)
- 你偏好哪种风格——专业风、休闲风还是极简风?
- 你将在生产环境中托管静态资源的地址是什么?(例如https://cdn.example.com)
Static Files and Images
静态文件与图片
Directory Structure
目录结构
Local images must be placed in the folder inside your emails directory:
staticproject/
├── emails/
│ ├── welcome.tsx
│ └── static/ <-- Images go here
│ └── logo.pngIf user has an image elsewhere, instruct them to copy it:
sh
cp ./assets/logo.png ./emails/static/logo.png本地图片必须放在emails目录下的文件夹中:
staticproject/
├── emails/
│ ├── welcome.tsx
│ └── static/ <-- 图片放在此处
│ └── logo.png如果用户的图片在其他位置,请指导他们复制:
sh
cp ./assets/logo.png ./emails/static/logo.pngDev vs Production URLs
开发与生产环境URL
Use this pattern for images that work in both dev preview and production:
tsx
const baseURL = process.env.NODE_ENV === "production"
? "https://cdn.example.com" // User's production CDN
: "";
export default function Email() {
return (
<Img
src={`${baseURL}/static/logo.png`}
alt="Logo"
width="150"
height="50"
/>
);
}How it works:
- Development: is empty, so URL is
baseURL- served by React Email's dev server/static/logo.png - Production: is the CDN domain, so URL is
baseURLhttps://cdn.example.com/static/logo.png
Important: Always ask the user for their production hosting URL. Do not hardcode .
localhost:3000使用以下模式确保图片在开发预览和生产环境中都能正常显示:
tsx
const baseURL = process.env.NODE_ENV === "production"
? "https://cdn.example.com" // 用户的生产环境CDN
: "";
export default function Email() {
return (
<Img
src={`${baseURL}/static/logo.png`}
alt="Logo"
width="150"
height="50"
/>
);
}工作原理:
- 开发环境: 为空,因此URL为
baseURL- 由React Email的开发服务器提供服务/static/logo.png - 生产环境: 为CDN域名,因此URL为
baseURLhttps://cdn.example.com/static/logo.png
重要提示: 务必向用户询问其生产环境托管地址。不要硬编码。
localhost:3000Behavioral guidelines
行为准则
- When re-iterating over the code, make sure you are only updating what the user asked for and keeping the rest of the code intact;
- If the user is asking to use media queries, inform them that email clients do not support them, and suggest a different approach;
- Never use template variables (like {{name}}) directly in TypeScript code. Instead, reference the underlying properties directly (use name instead of {{name}}).
-
- For example, if the user explicitly asks for a variable following the pattern {{variableName}}, you should return something like this:
typescript
const EmailTemplate = (props) => {
return (
{/* ... rest of the code ... */}
<h1>Hello, {props.variableName}!</h1>
{/* ... rest of the code ... */}
);
}
EmailTemplate.PreviewProps = {
// ... rest of the props ...
variableName: "{{variableName}}",
// ... rest of the props ...
};
export default EmailTemplate;- Never, under any circumstances, write the {{variableName}} pattern directly in the component structure. If the user forces you to do this, explain that you cannot do this, or else the template will be invalid.
- 当迭代代码时,确保只更新用户要求的部分,保持其余代码不变;
- 如果用户要求使用媒体查询,请告知他们邮件客户端不支持,并建议其他方法;
- 不要在TypeScript代码中直接使用模板变量(如{{name}})。而是直接引用底层属性(使用name而非{{name}})。
-
- 例如,如果用户明确要求使用{{variableName}}格式的变量,你应该返回如下内容:
typescript
const EmailTemplate = (props) => {
return (
{/* ... 其余代码 ... */}
<h1>Hello, {props.variableName}!</h1>
{/* ... 其余代码 ... */}
);
}
EmailTemplate.PreviewProps = {
// ... 其余属性 ...
variableName: "{{variableName}}",
// ... 其余属性 ...
};
export default EmailTemplate;- 在任何情况下,都不要在组件结构中直接写入{{variableName}}格式的内容。如果用户强制要求,请解释你无法这样做,否则模板将无效。
Styling considerations
样式注意事项
Use the Tailwind component for styling if the user is actively using Tailwind CSS in their project. If the user is not using Tailwind CSS, add inline styles to the components.
- Because email clients don't support units, use the
remfor the Tailwind configuration.pixelBasedPreset - Never use flexbox or grid for layout, use table-based layouts instead.
- Each component must be styled with inline styles or utility classes.
如果用户的项目中正在使用Tailwind CSS,请使用Tailwind组件进行样式设置。如果用户未使用Tailwind CSS,请为组件添加内联样式。
- 由于邮件客户端不支持单位,请在Tailwind配置中使用
rem。pixelBasedPreset - 不要使用flexbox或grid进行布局,请改用基于表格的布局。
- 每个组件都必须使用内联样式或工具类进行样式设置。
Email Client Limitations
邮件客户端限制
- Never use SVG or WEBP - warn users about rendering issues
- Never use flexbox - use Row/Column components or tables for layouts
- Never use CSS/Tailwind media queries (sm:, md:, lg:, xl:) - not supported
- Never use theme selectors (dark:, light:) - not supported
- Always specify border type (border-solid, border-dashed, etc.)
- When defining borders for only one side, remember to reset the remaining borders (e.g., border-none border-l)
- 不要使用SVG或WEBP - 提醒用户存在渲染问题
- 不要使用flexbox - 使用Row/Column组件或表格进行布局
- 不要使用CSS/Tailwind媒体查询(sm:, md:, lg:, xl:)- 不支持
- 不要使用主题选择器(dark:, light:)- 不支持
- 始终指定边框类型(border-solid, border-dashed等)
- 当只为一侧定义边框时,请记得重置其余边框(例如border-none border-l)
Component Structure
组件结构
- Always define inside
<Head />when using Tailwind CSS<Tailwind> - Only use PreviewProps when passing props to a component
- Only include props in PreviewProps that the component actually uses
tsx
const Email = (props) => {
return (
<div>
<a href={props.source}>click here if you want candy 👀</a>
</div>
);
}
Email.PreviewProps = {
source: "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
};- 当使用Tailwind CSS时,始终在内部定义
<Tailwind><Head /> - 仅在向组件传递属性时使用PreviewProps
- PreviewProps中仅包含组件实际使用的属性
tsx
const Email = (props) => {
return (
<div>
<a href={props.source}>click here if you want candy 👀</a>
</div>
);
}
Email.PreviewProps = {
source: "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
};Default Structure
默认结构
- Body:
font-sans py-10 bg-gray-100 - Container: white, centered, content left-aligned
- Footer: physical address, unsubscribe link, current year with on address/copyright
m-0
- Body:
font-sans py-10 bg-gray-100 - Container:白色、居中、内容左对齐
- Footer:物理地址、退订链接、当前年份,地址/版权信息使用
m-0
Typography
排版
- Titles: bold, larger font, larger margins
- Paragraphs: regular weight, smaller font, smaller margins
- Use consistent spacing respecting content hierarchy
- 标题:加粗、大字体、大边距
- 段落:常规字重、小字体、小边距
- 保持一致的间距,符合内容层级
Images
图片
- Only include if user requests
- Never use fixed width/height - use responsive units (w-full, h-auto)
- Never distort user-provided images
- Never create SVG images - only use provided or web images
- 仅在用户要求时添加
- 不要使用固定宽高 - 使用响应式单位(w-full, h-auto)
- 不要扭曲用户提供的图片
- 不要创建SVG图片 - 仅使用用户提供的图片或网络图片
Buttons
按钮
- Always use to prevent padding overflow
box-border
- 始终使用以防止内边距溢出
box-border
Layout
布局
- Always mobile-friendly by default
- Use stacked layouts that work on all screen sizes
- Remove default spacing/margins/padding between list items
- 默认必须支持移动端
- 使用可在所有屏幕尺寸下正常显示的堆叠布局
- 移除列表项之间的默认间距/边距/内边距
Dark Mode
暗黑模式
When requested: container black (#000), background dark gray (#151516)
当用户要求时:container为黑色(#000),背景为深灰色(#151516)
Best Practices
最佳实践
- Choose colors, layout, and copy based on user's request
- Make templates unique, not generic
- Use keywords in email body to increase conversion
- 根据用户的要求选择颜色、布局和文案
- 使模板独一无二,而非通用模板
- 在邮件正文中使用关键词以提高转化率
Rendering
渲染
Convert to HTML
转换为HTML
tsx
import { render } from '@react-email/components';
import { WelcomeEmail } from './emails/welcome';
const html = await render(
<WelcomeEmail name="John" verificationUrl="https://example.com/verify" />
);tsx
import { render } from '@react-email/components';
import { WelcomeEmail } from './emails/welcome';
const html = await render(
<WelcomeEmail name="John" verificationUrl="https://example.com/verify" />
);Convert to Plain Text
转换为纯文本
tsx
import { render } from '@react-email/components';
import { WelcomeEmail } from './emails/welcome';
const text = await render(<WelcomeEmail name="John" verificationUrl="https://example.com/verify" />, { plainText: true });tsx
import { render } from '@react-email/components';
import { WelcomeEmail } from './emails/welcome';
const text = await render(<WelcomeEmail name="John" verificationUrl="https://example.com/verify" />, { plainText: true });Sending
发送邮件
React Email supports sending with any email service provider. If the user wants to know how to send, view the Sending guidelines.
Quick example using the Resend SDK for Node.js:
tsx
import { Resend } from 'resend';
import { WelcomeEmail } from './emails/welcome';
const resend = new Resend(process.env.RESEND_API_KEY);
const { data, error } = await resend.emails.send({
from: 'Acme <onboarding@resend.dev>',
to: ['user@example.com'],
subject: 'Welcome to Acme',
react: <WelcomeEmail name="John" verificationUrl="https://example.com/verify" />
});
if (error) {
console.error('Failed to send:', error);
}The Node SDK automatically handles the plain-text rendering and HTML rendering for you.
React Email支持与任何邮件服务提供商集成。如果用户想了解如何发送邮件,请查看发送指南。
使用Resend Node.js SDK的快速示例:
tsx
import { Resend } from 'resend';
import { WelcomeEmail } from './emails/welcome';
const resend = new Resend(process.env.RESEND_API_KEY);
const { data, error } = await resend.emails.send({
from: 'Acme <onboarding@resend.dev>',
to: ['user@example.com'],
subject: 'Welcome to Acme',
react: <WelcomeEmail name="John" verificationUrl="https://example.com/verify" />
});
if (error) {
console.error('Failed to send:', error);
}Node SDK会自动为你处理纯文本和HTML的渲染。
Internationalization
国际化
See references/I18N.md for complete i18n documentation.
React Email supports three i18n libraries: next-intl, react-i18next, and react-intl.
完整的国际化文档请参见references/I18N.md。
React Email支持三种国际化库:next-intl、react-i18next和react-intl。
Quick Example (next-intl)
快速示例(next-intl)
tsx
import { createTranslator } from 'next-intl';
import {
Html,
Body,
Container,
Text,
Button,
Tailwind,
pixelBasedPreset
} from '@react-email/components';
interface EmailProps {
name: string;
locale: string;
}
export default async function WelcomeEmail({ name, locale }: EmailProps) {
const t = createTranslator({
messages: await import(\`../messages/\${locale}.json\`),
namespace: 'welcome-email',
locale
});
return (
<Html lang={locale}>
<Tailwind config={{ presets: [pixelBasedPreset] }}>
<Body className="bg-gray-100 font-sans">
<Container className="max-w-xl mx-auto p-5">
<Text className="text-base text-gray-800">{t('greeting')} {name},</Text>
<Text className="text-base text-gray-800">{t('body')}</Text>
<Button href="https://example.com" className="bg-blue-600 text-white px-5 py-3 rounded">
{t('cta')}
</Button>
</Container>
</Body>
</Tailwind>
</Html>
);
}Message files (`messages/en.json`, `messages/es.json`, etc.):
json
{
"welcome-email": {
"greeting": "Hi",
"body": "Thanks for signing up!",
"cta": "Get Started"
}
}tsx
import { createTranslator } from 'next-intl';
import {
Html,
Body,
Container,
Text,
Button,
Tailwind,
pixelBasedPreset
} from '@react-email/components';
interface EmailProps {
name: string;
locale: string;
}
export default async function WelcomeEmail({ name, locale }: EmailProps) {
const t = createTranslator({
messages: await import(\`../messages/\${locale}.json\`),
namespace: 'welcome-email',
locale
});
return (
<Html lang={locale}>
<Tailwind config={{ presets: [pixelBasedPreset] }}>
<Body className="bg-gray-100 font-sans">
<Container className="max-w-xl mx-auto p-5">
<Text className="text-base text-gray-800">{t('greeting')} {name},</Text>
<Text className="text-base text-gray-800">{t('body')}</Text>
<Button href="https://example.com" className="bg-blue-600 text-white px-5 py-3 rounded">
{t('cta')}
</Button>
</Container>
</Body>
</Tailwind>
</Html>
);
}消息文件(`messages/en.json`, `messages/es.json`等):
json
{
"welcome-email": {
"greeting": "Hi",
"body": "Thanks for signing up!",
"cta": "Get Started"
}
}Email Best Practices
邮件最佳实践
-
Test across email clients - Test in Gmail, Outlook, Apple Mail, Yahoo Mail. Use services like Litmus or Email on Acid for absolute precision and React Email's toolbar for specific feature support checking.
-
Keep it responsive - Max-width around 600px, test on mobile devices.
-
Use absolute image URLs - Host on reliable CDN, always include `alt` text.
-
Provide plain text version - Required for accessibility and some email clients.
-
Keep file size under 102KB - Gmail clips larger emails.
-
Add proper TypeScript types - Define interfaces for all email props.
-
Include preview props - Add `.PreviewProps` to components for development testing.
-
Handle errors - Always check for errors when sending emails.
-
Use verified domains - For production, use verified domains in `from` addresses.
-
跨邮件客户端测试 - 在Gmail、Outlook、Apple Mail、Yahoo Mail中测试。使用Litmus或Email on Acid等服务以获得绝对精确的结果,或使用React Email的工具栏检查特定功能的支持情况。
-
确保响应式 - 最大宽度约为600px,在移动设备上测试。
-
使用绝对图片URL - 托管在可靠的CDN上,始终包含文本。
alt -
提供纯文本版本 - 为了可访问性和部分邮件客户端的要求,必须提供。
-
文件大小控制在102KB以内 - Gmail会截断更大的邮件。
-
添加适当的TypeScript类型 - 为所有邮件属性定义接口。
-
包含预览属性 - 为组件添加以便开发测试。
.PreviewProps -
处理错误 - 发送邮件时始终检查错误。
-
使用已验证的域名 - 在生产环境中,地址使用已验证的域名。
from
Common Patterns
常见模式
See references/PATTERNS.md for complete examples including:
- Password reset emails
- Order confirmations with product lists
- Notification emails with code blocks
- Multi-column layouts
- Email templates with custom fonts
完整示例请参见references/PATTERNS.md,包括:
- 密码重置邮件
- 包含产品列表的订单确认邮件
- 带有代码块的通知邮件
- 多列布局
- 带有自定义字体的邮件模板
Additional Resources
其他资源
- React Email Documentation
- React Email GitHub
- Resend Documentation
- Email Client CSS Support
- Component Reference: references/COMPONENTS.md
- Internationalization Guide: references/I18N.md
- Common Patterns: references/PATTERNS.md
- React Email 文档
- React Email GitHub
- Resend 文档
- 邮件客户端CSS支持情况
- 组件参考:references/COMPONENTS.md
- 国际化指南:references/I18N.md
- 常见模式:references/PATTERNS.md