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
安装
New Project
新项目
Scaffold a new React Email project:
sh
npx create-email@latest
cd react-email-starter
npm install
npm run devThis creates a folder with sample templates. Also works with yarn, pnpm, or bun.
react-email-starter快速搭建新的React Email项目:
sh
npx create-email@latest
cd react-email-starter
npm install
npm run dev此命令会创建一个包含示例模板的文件夹,同时支持yarn、pnpm或bun包管理器。
react-email-starterExisting Project
现有项目
Add React Email to an existing codebase:
- Install dependencies:
sh
npm install @react-email/components
npm install react-email @react-email/preview-server -D- Create an emails directory:
sh
mkdir emails- Add a preview script to package.json:
json
{
"scripts": {
"email:dev": "email dev"
}
}- Start the preview server:
sh
npm run email:devThe flag specifies where email templates are stored. Adjust the path to match your project structure (e.g., , ).
--dirsrc/emailsapp/emails在现有代码库中添加React Email:
- 安装依赖:
sh
npm install @react-email/components
npm install react-email @react-email/preview-server -D- 创建邮件目录:
sh
mkdir emails- 在package.json中添加预览脚本:
json
{
"scripts": {
"email:dev": "email dev"
}
}- 启动预览服务器:
sh
npm run email:dev--dirsrc/emailsapp/emailsBrand Setup (Required First Step)
品牌配置(第一步必填)
Before creating any email template, gather brand information from the user. This ensures visual consistency across all emails.
在创建任何邮件模板之前,请先收集用户的品牌信息,确保所有邮件的视觉风格一致。
Required Brand Information
必填品牌信息
Ask the user for:
-
Brand colors
- Primary color (main brand color for buttons, links, accents)
- Secondary color (supporting color for backgrounds, borders)
- Text color (default: for light mode)
#1a1a1a - Background color (default: for light mode)
#f4f4f5
-
Logo
- Logo image URL (must be absolute URL, PNG or JPEG)
- Logo dimensions or aspect ratio preference
- Logo placement preference (centered, left-aligned)
- Ask user for file and path of the local file if the logo is not a publicly accessible URL.
-
Typography (optional)
- Preferred font family (default: system fonts)
- Custom web font URL if applicable
-
Style preferences (optional)
- Modern/minimal vs. classic/traditional
- Rounded corners vs. sharp edges
- Spacing density (compact vs. spacious)
- Never add emojis unless the user explicitly requests them.
请向用户收集以下信息:
-
品牌配色
- 主色调(用于按钮、链接、强调元素的品牌主色)
- 辅助色(用于背景、边框的支持色)
- 文本颜色(浅色模式默认值:)
#1a1a1a - 背景颜色(浅色模式默认值:)
#f4f4f5
-
品牌Logo
- Logo图片URL(必须为绝对URL,格式为PNG或JPEG)
- Logo尺寸或宽高比偏好
- Logo位置偏好(居中、左对齐)
- 如果Logo没有公开可访问的URL,请询问用户本地文件的路径。
-
排版设置(可选)
- 首选字体族(默认:系统字体)
- 自定义网页字体URL(如有)
-
风格偏好(可选)
- 现代极简风 vs 经典传统风
- 圆角 vs 直角
- 间距密度(紧凑 vs 宽松)
- 除非用户明确要求,否则请勿添加表情符号。
Brand Configuration Pattern
品牌配置示例
Once gathered, define a reusable Tailwind configuration. Using provides intellisense support for all configuration options:
satisfies TailwindConfigtsx
// emails/tailwind.config.ts
import { pixelBasedPreset, type TailwindConfig } from '@react-email/components';
export default {
presets: [pixelBasedPreset],
theme: {
extend: {
colors: {
brand: {
primary: '#007bff', // User's primary brand color
secondary: '#6c757d', // User's secondary color
},
},
},
},
} satisfies TailwindConfig;
// For non-Tailwind brand assets (optional)
export const brandAssets = {
logo: {
src: 'https://example.com/logo.png', // User's logo URL
alt: 'Company Name',
width: 120,
},
};收集信息后,定义可复用的Tailwind配置。使用可获得所有配置选项的智能提示:
satisfies TailwindConfigtsx
// emails/tailwind.config.ts
import { pixelBasedPreset, type TailwindConfig } from '@react-email/components';
export default {
presets: [pixelBasedPreset],
theme: {
extend: {
colors: {
brand: {
primary: '#007bff', // 用户提供的品牌主色
secondary: '#6c757d', // 用户提供的辅助色
},
},
},
},
} satisfies TailwindConfig;
// 非Tailwind品牌资源配置(可选)
export const brandAssets = {
logo: {
src: 'https://example.com/logo.png', // 用户提供的Logo URL
alt: 'Company Name',
width: 120,
},
};Using Tailwind Config in Templates
在模板中使用Tailwind配置
tsx
import * as React from "react";
import tailwindConfig, { brandAssets } from './tailwind.config';
import { Tailwind, Img } from '@react-email/components';
<Tailwind config={tailwindConfig}>
<Body className="bg-gray-100 font-sans">
<Container className="max-w-xl mx-auto bg-white p-6">
<Img
src={brandAssets.logo.src}
alt={brandAssets.logo.alt}
width={brandAssets.logo.width}
className="mx-auto mb-6"
/>
<Button className="bg-brand-primary text-white rounded px-5 py-3">
Call to Action
</Button>
</Container>
</Body>
</Tailwind>tsx
import * as React from "react";
import tailwindConfig, { brandAssets } from './tailwind.config';
import { Tailwind, Img } from '@react-email/components';
<Tailwind config={tailwindConfig}>
<Body className="bg-gray-100 font-sans">
<Container className="max-w-xl mx-auto bg-white p-6">
<Img
src={brandAssets.logo.src}
alt={brandAssets.logo.alt}
width={brandAssets.logo.width}
className="mx-auto mb-6"
/>
<Button className="bg-brand-primary text-white rounded px-5 py-3">
行动按钮
</Button>
</Container>
</Body>
</Tailwind>Asset Locations
资源存放位置
Direct users to place brand assets in appropriate locations:
- Logo and images: Host on a CDN or public URL. For local development, place in .
emails/static/ - Custom fonts: Use the component with a web font URL (Google Fonts, Adobe Fonts, or self-hosted).
Font
Example prompt for gathering brand info:
"Before I create your email template, I need some brand information to ensure consistency. Could you provide:
- Your primary brand color (hex code, e.g., #007bff)
- Your logo URL (must be a publicly accessible PNG or JPEG)
- Any secondary colors you'd like to use
- Style preference (modern/minimal or classic/traditional)"
引导用户将品牌资源存放在合适的位置:
- Logo和图片:托管在CDN或提供公开URL。本地开发时,可放在目录下。
emails/static/ - 自定义字体:使用组件搭配网页字体URL(Google Fonts、Adobe Fonts或自托管字体)。
Font
收集品牌信息的示例话术:
"在创建邮件模板之前,我需要一些品牌相关信息以确保风格统一。能否提供以下内容:
- 品牌主色调(十六进制代码,例如#007bff)
- Logo的公开URL(必须为PNG或JPEG格式)
- 如需使用辅助色,请提供对应的颜色值
- 风格偏好(现代极简风或经典传统风)"
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 * as React from "react";
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 * as React from "react";
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>欢迎您 - 请验证您的邮箱</Preview>
<Body className="bg-gray-100 font-sans">
<Container className="max-w-xl mx-auto p-5">
<Heading className="text-2xl text-gray-800">
欢迎加入!
</Heading>
<Text className="text-base text-gray-800">
您好{name},感谢您的注册!
</Text>
<Button
href={verificationUrl}
className="bg-brand text-white px-5 py-3 rounded block text-center no-underline"
>
验证邮箱
</Button>
</Container>
</Body>
</Tailwind>
</Html>
);
}
// 用于开发测试的预览属性
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 (use absolute URLs) (use the dev server for the BASE_URL of the image in dev mode; for production, ask the user for the BASE_URL of the site; dynamically generate the URL of the image based on environment.)
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 - - 图片组件(需使用绝对URL;开发模式下使用开发服务器的BASE_URL;生产环境下请询问用户站点的BASE_URL,根据环境动态生成图片URL)
Img - - 水平分隔线
Hr
特殊组件:
- - 语法高亮代码块
CodeBlock - - 行内代码
CodeInline - - Markdown渲染组件
Markdown - - 自定义网页字体组件
Font
Behavioral Guidelines
行为准则
Brand-First Workflow
品牌优先工作流
- Always gather brand information before creating the first email template. Do not skip this step.
- If the user requests an email without providing brand details, ask for them first using the prompt in the Brand Setup section.
- If a file exists in the emails directory, use it for all new templates.
tailwind.config.ts - When creating multiple emails, ensure all templates import and use the same brand configuration.
- If the user provides new brand assets or colors mid-project, update and offer to update existing templates.
tailwind.config.ts
- 创建首个邮件模板前,必须先收集品牌信息,不可跳过此步骤。
- 如果用户未提供品牌信息就要求创建邮件,请先使用品牌配置部分的话术收集信息。
- 如果邮件目录中已存在文件,所有新模板都需使用该配置。
tailwind.config.ts - 创建多份邮件时,确保所有模板都导入并使用同一品牌配置。
- 如果用户在项目中途提供新的品牌资源或颜色,需更新并主动提出更新现有模板。
tailwind.config.ts
General 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
样式设置
Use the component with for styling (email clients don't support rem units). If not using Tailwind, use inline styles.
TailwindpixelBasedPresetCritical limitations (email clients don't support these):
- No SVG/WEBP images - use PNG/JPEG only
- No flexbox/grid - use /
Rowcomponents or tablesColumn - No media queries (,
sm:, etc.) or theme selectors (md:,dark:)light: - Always specify border style (, etc.)
border-solid
Structure rules:
- Place inside
<Head />when using Tailwind<Tailwind> - Only include props in that the component uses
PreviewProps
See references/STYLING.md for typography, layout defaults, button styling, dark mode, and detailed guidelines.
使用带的组件进行样式设置(邮件客户端不支持rem单位)。如果不使用Tailwind,请使用内联样式。
pixelBasedPresetTailwind关键限制(邮件客户端不支持以下特性):
- 不支持SVG/WEBP图片,仅可使用PNG/JPEG格式
- 不支持flexbox/grid布局,需使用/
Row组件或表格Column - 不支持媒体查询(如、
sm:)或主题选择器(如md:、dark:)light: - 必须指定边框样式(如)
border-solid
结构规则:
- 使用Tailwind时,需将放在
<Head />内部<Tailwind> - 中仅包含组件实际使用的属性
PreviewProps
关于排版、布局默认值、按钮样式、深色模式及详细规范,请参考references/STYLING.md。
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 * as React from "react";
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 * as React from "react";
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: '欢迎加入Acme',
react: <WelcomeEmail name="John" verificationUrl="https://example.com/verify" />
});
if (error) {
console.error('发送失败:', 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 * as React from "react";
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 * as React from "react";
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 includetext.
alt -
Provide plain text version - Required for accessibility and some email clients. The render function will generate this if you pass theoption.
plainText -
Keep file size under 102KB - Gmail clips larger emails.
-
Add proper TypeScript types - Define interfaces for all email props.
-
Include preview props - Addto components for development testing.
.PreviewProps -
Handle errors - Always check for errors when sending emails.
-
跨客户端测试 - 在Gmail、Outlook、Apple Mail、Yahoo Mail中测试。如需高精度测试,可使用Litmus或Email on Acid等服务,也可使用React Email的工具栏检查特定功能的支持情况。
-
确保响应式 - 最大宽度设置为600px左右,并在移动设备上测试。
-
使用绝对图片URL - 托管在可靠的CDN上,务必添加文本。
alt -
提供纯文本版本 - 为了可访问性和兼容部分邮件客户端,这是必需的。如果在render函数中传入参数,会自动生成纯文本版本。
plainText -
文件大小控制在102KB以内 - Gmail会截断更大的邮件。
-
添加TypeScript类型 - 为所有邮件属性定义接口。
-
包含预览属性 - 为组件添加以便开发测试。
.PreviewProps -
错误处理 - 发送邮件时务必检查错误。
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
- Styling Guide: references/STYLING.md
- Internationalization Guide: references/I18N.md
- Common Patterns: references/PATTERNS.md
- React Email 官方文档
- React Email GitHub仓库
- Resend 官方文档
- 邮件客户端CSS支持情况
- 组件参考:references/COMPONENTS.md
- 样式指南:references/STYLING.md
- 国际化指南:references/I18N.md
- 常见模式:references/PATTERNS.md