react-email

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

React 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

安装

sh
npm i react-email
Or scaffold a new project:
sh
npx create-email@latest
cd react-email-starter
npm install
npm run dev
This works with any package manager (npm, yarn, pnpm, bun) — substitute accordingly.
The dev server runs at localhost:3000 with a preview interface for templates in the
emails
folder.
sh
npm i react-email
或者搭建新项目:
sh
npx create-email@latest
cd react-email-starter
npm install
npm run dev
这适用于任何包管理器(npm、yarn、pnpm、bun)——请相应替换命令。
开发服务器运行在 localhost:3000,并为
emails
文件夹中的模板提供预览界面。

Adding to an Existing Project

添加到现有项目

Install the packages and add a script to your
package.json
:
json
{
  "scripts": {
    "email": "email dev --dir emails --port 3000"
  }
}
Make sure the path to the emails folder is relative to the base project directory. Ensure
tsconfig.json
includes proper support for JSX.
安装这些包,并向
package.json
添加脚本:
json
{
  "scripts": {
    "email": "email dev --dir emails --port 3000"
  }
}
确保
emails
文件夹的路径相对于项目根目录。确保
tsconfig.json
正确支持 JSX。

Basic 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';

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 />
        <Body className="bg-gray-100 font-sans">
          <Preview>Welcome - Verify your email</Preview>
          <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 box-border"
            >
              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';

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 />
        <Body className="bg-gray-100 font-sans">
          <Preview>Welcome - Verify your email</Preview>
          <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 box-border"
            >
              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 };

Behavioral Guidelines

行为准则

  • When iterating over the code, only update what the user asked for. Keep the rest intact.
  • If the user asks to use media queries, inform them that most email clients don't support them and suggest a different approach.
  • Never use template variables (like
    {{name}}
    ) directly in TypeScript code. Instead, reference the underlying properties directly. If the user explicitly asks for
    {{variableName}}
    , place the mustache string only in PreviewProps, never in the component JSX:
typescript
const EmailTemplate = (props) => {
  return (
    <h1>Hello, {props.variableName}!</h1>
  );
}

EmailTemplate.PreviewProps = {
  variableName: "{{variableName}}",
};

export default EmailTemplate;
  • Never write the
    {{variableName}}
    pattern directly in the component structure. If the user insists, explain that this would make the template invalid.
  • 修改代码时,仅更新用户要求的内容,其余部分保持不变。
  • 如果用户要求使用 media queries,请告知大多数邮件客户端不支持它们,并建议采用其他方案。
  • 绝不要在 TypeScript 代码中直接使用模板变量(如
    {{name}}
    ),而应直接引用底层属性。如果用户明确要求使用
    {{variableName}}
    ,则仅将 mustache 字符串放在
    PreviewProps
    中,绝不要放在组件 JSX 中:
typescript
const EmailTemplate = (props) => {
  return (
    <h1>Hello, {props.variableName}!</h1>
  );
}

EmailTemplate.PreviewProps = {
  variableName: "{{variableName}}",
};

export default EmailTemplate;
  • 绝不要直接在组件结构中编写
    {{variableName}}
    模式。如果用户坚持这样做,请解释这会导致模板无效。

Essential Components

核心组件

See references/COMPONENTS.md for complete component documentation.
Core Structure:
  • Html
    - Root wrapper with
    lang
    attribute
  • Head
    - Meta elements, styles, fonts
  • Body
    - Main content wrapper
  • Container
    - Outermost centering wrapper (has built-in
    max-width: 37.5em
    ). Use only once per email.
  • Section
    - Interior content blocks (no built-in max-width). Use for grouping content inside
    Container
    .
  • Row
    &
    Column
    - Multi-column layouts
  • Tailwind
    - Enables Tailwind CSS utility classes
Content:
  • Preview
    - Inbox preview text, always first inside
    <Body>
  • Heading
    - h1-h6 headings
  • Text
    - Paragraphs
  • Button
    - Styled link buttons (always include
    box-border
    )
  • Link
    - Hyperlinks
  • Img
    - Images (see Static Files section below)
  • Hr
    - Horizontal dividers
Specialized:
  • CodeBlock
    - Syntax-highlighted code
  • CodeInline
    - Inline code
  • Markdown
    - Render markdown
  • Font
    - Custom web fonts
有关完整的组件文档,请参阅 references/COMPONENTS.md。
核心结构:
  • Html
    - 带
    lang
    属性的根包装器
  • Head
    - 元元素、样式和字体
  • Body
    - 主要内容包装器
  • Container
    - 最外层居中包装器(内置
    max-width: 37.5em
    )。每封邮件仅使用一次。
  • Section
    - 内部内容区块(没有内置 max-width)。用于在
    Container
    内组织内容。
  • Row
    与
    Column
    - 多列布局
  • Tailwind
    - 启用 Tailwind CSS 工具类
内容:
  • Preview
    - 收件箱预览文本,始终位于
    <Body>
    内的第一个位置
  • Heading
    - h1-h6 标题
  • Text
    - 段落
  • Button
    - 带样式的链接按钮(始终包含
    box-border
    )
  • Link
    - 超链接
  • Img
    - 图片(参见下方的静态文件部分)
  • Hr
    - 水平分隔线
专用组件:
  • CodeBlock
    - 带语法高亮的代码块
  • CodeInline
    - 行内代码
  • Markdown
    - 渲染 Markdown
  • Font
    - 自定义 Web 字体

Before Writing Code

编写代码前

When a user requests an email template, ask clarifying questions FIRST if they haven't provided:
  1. Brand colors - Ask for primary brand color (hex code like #007bff)
  2. Logo - Ask if they have a logo file and its format (PNG/JPG only - warn if SVG/WEBP)
  3. Style preference - Professional, casual, or minimal tone
  4. Production URL - Where will static assets be hosted in production?
当用户请求邮件模板,但尚未提供以下信息时,请先提出澄清问题:
  1. 品牌颜色 - 询问主要品牌颜色(十六进制代码,如 #007bff)
  2. Logo - 询问用户是否有 Logo 文件及其格式(仅限 PNG/JPG——如果使用 SVG/WEBP,则提醒用户)
  3. 风格偏好 - 专业、休闲或极简风格
  4. 生产环境 URL - 生产环境中的静态资源将托管在哪里?

Static Files and Images

静态文件与图片

Directory Structure

目录结构

Local images must be placed in the
static
folder inside your emails directory:
project/
├── emails/
│   ├── welcome.tsx
│   └── static/           <-- Images go here
│       └── logo.png
本地图片必须放在
emails
目录内的
static
文件夹中:
project/
├── emails/
│   ├── welcome.tsx
│   └── static/           <-- Images go here
│       └── logo.png

Dev 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:
    baseURL
    is empty, so URL is
    /static/logo.png
    - served by React Email's dev server
  • Production:
    baseURL
    is the CDN domain, so URL is
    https://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"  // User's production CDN
  : "";

export default function Email() {
  return (
    <Img
      src={`${baseURL}/static/logo.png`}
      alt="Logo"
      width="150"
      height="50"
    />
  );
}
工作方式:
  • 开发环境:
    baseURL
    为空,因此 URL 为
    /static/logo.png
    ——由 React Email 的开发服务器提供
  • 生产环境:
    baseURL
    为 CDN 域名,因此 URL 为
    https://cdn.example.com/static/logo.png
重要提示: 始终向用户询问其生产环境托管 URL。不要硬编码
localhost:3000
。

Styling

样式

See references/STYLING.md for comprehensive styling documentation including typography, layout patterns, dark mode, and brand consistency.
有关排版、布局模式、深色模式和品牌一致性等全面样式文档,请参阅 references/STYLING.md。

Key Rules

关键规则

  • Use
    Tailwind
    with
    pixelBasedPreset
    (email clients don't support
    rem
    ). Import
    pixelBasedPreset
    from
    react-email
    .
  • Never use flexbox or grid — use
    Row
    /
    Column
    components or tables for layouts.
  • Avoid CSS/Tailwind media queries (
    sm:
    ,
    md:
    ,
    lg:
    ,
    xl:
    ) — limited email client support.
  • Never use theme selectors (
    dark:
    ,
    light:
    ) — not supported.
  • Never use SVG or WEBP images — warn users about rendering issues.
  • Always specify border type (
    border-solid
    ,
    border-dashed
    , etc.) — email clients don't inherit it.
  • For single-side borders, reset others first (
    border-none border-l border-solid
    ).
  • 使用
    Tailwind
    和
    pixelBasedPreset
    (邮件客户端不支持
    rem
    )。从
    react-email
    导入
    pixelBasedPreset
    。
  • 绝不要使用 flexbox 或 grid——使用
    Row
    /
    Column
    组件或表格进行布局。
  • 避免使用 CSS/Tailwind media queries(
    sm:
    、
    md:
    、
    lg:
    、
    xl:
    )——邮件客户端对其支持有限。
  • 绝不要使用主题选择器(
    dark:
    、
    light:
    )——不受支持。
  • 绝不要使用 SVG 或 WEBP 图片——提醒用户可能存在渲染问题。
  • 始终指定边框类型(
    border-solid
    、
    border-dashed
    等)——邮件客户端不会继承边框类型。
  • 对于单侧边框,先重置其他边框(
    border-none border-l border-solid
    )。

Required Classes

必需类名

ComponentRequired ClassWhy
Button
box-border
Prevents padding from overflowing the button width
Hr
/ any border
border-solid
(or
border-dashed
, etc.)
Email clients don't inherit border type
Single-side borders
border-none
+ the side
Resets default borders on other sides
组件必需类名原因
Button
box-border
防止内边距溢出按钮宽度
Hr
/ 任意边框
border-solid
(或
border-dashed
等)
邮件客户端不会继承边框类型
单侧边框
border-none
+ 对应侧
重置其他侧默认边框

Structure Notes

结构说明

  • Always define
    <Head />
    inside
    <Tailwind>
    when using Tailwind CSS
  • <Preview>
    should always be the first element inside
    <Body>
  • Only include props in
    PreviewProps
    that the component actually uses
  • Use fixed width/height for known-size elements (logos, icons); responsive sizing (
    w-full
    ,
    h-auto
    ) for content images
  • 使用 Tailwind CSS 时,始终在
    <Tailwind>
    内定义
    <Head />
  • <Preview>
    应始终是
    <Body>
    内的第一个元素
  • PreviewProps
    中只包含组件实际使用的属性
  • 对尺寸已知的元素(Logo、图标)使用固定宽高;对内容图片使用响应式尺寸(
    w-full
    、
    h-auto
    )

Rendering

渲染

Convert to HTML

转换为 HTML

tsx
import { render } from 'react-email';
import { WelcomeEmail } from './emails/welcome';

const html = await render(
  <WelcomeEmail name="John" verificationUrl="https://example.com/verify" />
);
tsx
import { render } from 'react-email';
import { WelcomeEmail } from './emails/welcome';

const html = await render(
  <WelcomeEmail name="John" verificationUrl="https://example.com/verify" />
);

Convert to Plain Text

转换为纯文本

tsx
const text = await render(<WelcomeEmail name="John" verificationUrl="https://example.com/verify" />, { plainText: true });
tsx
const text = await render(<WelcomeEmail name="John" verificationUrl="https://example.com/verify" />, { plainText: true });

Sending

发送

React Email supports sending with any email service provider. See references/SENDING.md for complete sending documentation including Resend, Nodemailer, and SendGrid examples.
Quick example using the Resend 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" />
});
The Resend Node SDK automatically handles both HTML and plain-text rendering.
React Email 支持通过任意邮件服务提供商发送邮件。有关完整的发送文档,包括 Resend、Nodemailer 和 SendGrid 示例,请参阅 references/SENDING.md。
使用 Resend 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" />
});
Resend Node SDK 会自动处理 HTML 和纯文本渲染。

CLI Commands

CLI 命令

The
react-email
package provides a CLI accessible via the
email
command:
CommandDescription
email dev --dir <path> --port <port>
Start the preview development server (default:
./emails
, port 3000)
email build --dir <path>
Build the preview app for production deployment
email start
Run the built preview app
email export --outDir <path> --pretty --plainText --dir <path>
Export templates to static HTML files
email resend setup
Connect the CLI to your Resend account via API key
email resend reset
Remove the stored Resend API key
react-email
包提供可通过
email
命令访问的 CLI:
命令说明
email dev --dir <path> --port <port>
启动预览开发服务器(默认目录为
./emails
,端口为 3000)
email build --dir <path>
构建用于生产部署的预览应用
email start
运行已构建的预览应用
email export --outDir <path> --pretty --plainText --dir <path>
将模板导出为静态 HTML 文件
email resend setup
通过 API 密钥将 CLI 连接到你的 Resend 账户
email resend reset
删除已存储的 Resend API 密钥

Internationalization

国际化

See references/I18N.md for complete i18n documentation. React Email supports three libraries: next-intl, react-i18next, and react-intl.
有关完整的 i18n 文档,请参阅 references/I18N.md。React Email 支持三个库:next-intl、react-i18next 和 react-intl。

Email Editor

邮件编辑器

React Email includes a visual editor (
@react-email/editor
) that can be embedded in your app. It's built on TipTap/ProseMirror and produces email-ready HTML.
See references/EDITOR.md for complete documentation including:
  • EmailEditor
    — batteries-included component with bubble menus, slash commands, and theming
  • StarterKit
    — 35+ email-aware extensions (headings, lists, tables, columns, buttons, etc.)
  • Inspector
    — contextual sidebar for editing styles
  • EmailTheming
    — built-in themes (
    basic
    ,
    minimal
    ) with customizable CSS properties
  • composeReactEmail
    — export editor content to email-ready HTML and plain text
  • Custom extensions via
    EmailNode
    and
    EmailMark
Quick example:
tsx
import { EmailEditor, type EmailEditorRef } from '@react-email/editor';
import '@react-email/editor/themes/default.css';
import { useRef } from 'react';

export function MyEditor() {
  const ref = useRef<EmailEditorRef>(null);

  return (
    <EmailEditor
      ref={ref}
      content="<p>Start typing...</p>"
      theme="basic"
    />
  );
}
React Email 包含一个可嵌入应用的可视化编辑器(
@react-email/editor
)。它基于 TipTap/ProseMirror 构建,可生成适合邮件使用的 HTML。
有关完整文档,请参阅 references/EDITOR.md,其中包括:
  • EmailEditor
    — 开箱即用的组件,带气泡菜单、斜杠命令和主题功能
  • StarterKit
    — 35+ 个面向邮件场景的扩展(标题、列表、表格、分栏、按钮等)
  • Inspector
    - 用于编辑样式的上下文侧边栏
  • EmailTheming
    - 内置主题(
    basic
    、
    minimal
    ),可自定义 CSS 属性
  • composeReactEmail
    - 将编辑器内容导出为适合邮件使用的 HTML 和纯文本
  • 通过
    EmailNode
    和
    EmailMark
    使用自定义扩展
快速示例:
tsx
import { EmailEditor, type EmailEditorRef } from '@react-email/editor';
import '@react-email/editor/themes/default.css';
import { useRef } from 'react';

export function MyEditor() {
  const ref = useRef<EmailEditorRef>(null);

  return (
    <EmailEditor
      ref={ref}
      content="<p>Start typing...</p>"
      theme="basic"
    />
  );
}

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
  • Team invitation emails
有关完整示例,请参阅 references/PATTERNS.md,其中包括:
  • 密码重置邮件
  • 带商品列表的订单确认邮件
  • 包含代码块的通知邮件
  • 多列布局
  • 团队邀请邮件

Email Best Practices

邮件最佳实践

  1. Test across email clients - Gmail, Outlook, Apple Mail, Yahoo Mail
  2. Keep it responsive - Max-width around 600px, test on mobile
  3. Use absolute image URLs - Host on reliable CDN
  4. Write meaningful alt text - Describe purpose and details for content images; use
    alt=""
    for decorative images (spacers, dividers, background flourishes). React Email's
    <Img>
    defaults to
    alt=""
    .
  5. Provide plain text version - Required for accessibility
  6. Keep file size under 102KB - Gmail clips larger emails
  7. Add proper TypeScript types - Define interfaces for all email props
  8. Include preview props - Add
    .PreviewProps
    for development testing
  9. Use verified domains - For production
    from
    addresses
  1. 在多个邮件客户端中测试 - Gmail、Outlook、Apple Mail、Yahoo Mail
  2. 保持响应式设计 - 最大宽度约为 600px,并在移动端测试
  3. 使用绝对图片 URL - 托管在可靠的 CDN 上
  4. 编写有意义的替代文本 - 描述内容图片的用途和细节;装饰性图片(间隔块、分隔线、背景装饰)使用
    alt=""
    。React Email 的
    <Img>
    默认使用
    alt=""
    。
  5. 提供纯文本版本 - 无障碍访问所必需
  6. 将文件大小控制在 102KB 以下 - Gmail 会截断更大的邮件
  7. 添加正确的 TypeScript 类型 - 为所有邮件属性定义接口
  8. 包含预览属性 - 添加
    .PreviewProps
    以便在开发环境中测试
  9. 使用已验证的域名 - 用于生产环境的发件人地址

Accessibility

无障碍访问

React Email handles the structural defaults; the rest is content.
What React Email gives you for free:
  • <Html>
    sets
    lang
    and
    dir
    (defaults:
    lang="en" dir="ltr"
    — override per locale)
  • <Img>
    defaults to
    alt=""
    so decorative images are skipped by screen readers
  • <Markdown>
    renders layout tables with
    role="presentation"
  • <Preview>
    also emits a
    <title>
    tag
Upgrade with
npm install react-email@latest
to get these defaults.
What you still have to do (content choices):
  • Open with a single
    <Heading as="h1">
    , nest subheadings in order, never skip levels (very short SMS-style emails may skip the heading entirely)
  • Set descriptive
    alt
    on meaningful images; pass an explicit
    alt=""
    on decorative images — never omit the attribute
  • Linked images are never decorative. When an
    <Img>
    is inside a
    <Link>
    or
    <Button>
    , the
    alt
    must describe where the link goes —
    alt=""
    on a linked image leaves the link with no accessible name
  • Write link text that describes the destination (
    <Button>Read the report</Button>
    , not
    click here
    )
  • Hit 4.5:1 text contrast (WCAG AA); preview in dark mode
  • For layout tables you build by hand (outside
    <Markdown>
    ), add
    role="presentation"
  • For non-English emails, pass the locale:
    <Html lang={locale} dir={isRTL ? 'rtl' : 'ltr'}>
    (see I18N.md)
For the full rule set, severity ranking, and authoring checklist, see the accessibility reference in the
email-best-practices
skill.
React Email 会处理结构性默认值,其余部分取决于内容。
React Email 默认提供:
  • <Html>
    设置
    lang
    和
    dir
    (默认值为
    lang="en" dir="ltr"
    ——可按语言环境覆盖)
  • <Img>
    默认使用
    alt=""
    ,因此屏幕阅读器会跳过装饰性图片
  • <Markdown>
    使用
    role="presentation"
    渲染布局表格
  • <Preview>
    还会输出
    <title>
    标签
通过
npm install react-email@latest
升级即可获得这些默认行为。
仍需由你完成的部分(内容选择):
  • 以单个
    <Heading as="h1">
    开头,按顺序嵌套子标题,不要跳级(非常简短的 SMS 风格邮件可以完全省略标题)
  • 为有意义的图片设置描述性
    alt
    ;装饰性图片显式传入
    alt=""
    ——绝不要省略该属性
  • 带链接的图片绝不能视为装饰性图片。 当
    <Img>
    位于
    <Link>
    或
    <Button>
    内时,
    alt
    必须描述链接目标——链接图片使用
    alt=""
    会导致链接没有无障碍名称
  • 编写能够描述目标的链接文本(使用
    <Button>Read the report</Button>
    ,不要使用
    click here
    )
  • 达到 4.5:1 的文本对比度(WCAG AA);在深色模式下预览
  • 对于手动构建的布局表格(在
    <Markdown>
    之外),添加
    role="presentation"
  • 对于非英语邮件,传入语言环境:
    <Html lang={locale} dir={isRTL ? 'rtl' : 'ltr'}>
    (参见 I18N.md)
有关完整的规则集、严重程度排名和编写检查清单,请参阅
email-best-practices
skill 中的无障碍访问参考。

Additional Resources

其他资源