はじめに
メールのHTMLテンプレート開発、やったことある人なら分かると思うんですが、正直かなりしんどいんですよね。
テーブルレイアウトを駆使して、GmailとOutlookの両方で崩れないように調整して、インラインスタイルをひたすら書いて...。2025年になってもこの状況かと思うと、ちょっとげんなりします。
そんな中で登場したのがReact Emailです。名前の通り、Reactでメールテンプレートを書けるライブラリなんですが、これが意外と実用的で、個人的にはもうこれ一択だと思っています。
GitHubのスター数は17,500を超えていて、Resend社が開発しているという点でも信頼感があります。
とはいえ、読むより触った方が早いと思います。React EmailのHtmlやButtonといったコンポーネントを実際にブラウザ上で動かして、見た目がどう変わるか確認できるサンプルを用意しました。先に触ってみたい方はこちらからどうぞ。
React Emailの特徴
Reactコンポーネントでメールが書ける
一番の特徴はこれですね。普段Reactを書いている人なら、学習コストほぼゼロでメールテンプレートが作れます。
import { Button, Html, Head, Body, Container, Text } from "@react-email/components";
const WelcomeEmail = () => {
return (
<Html>
<Head />
<Body style={{ fontFamily: "sans-serif" }}>
<Container>
<Text>ご登録ありがとうございます。</Text>
<Button
href="https://example.com/dashboard"
style={{
backgroundColor: "#000",
color: "#fff",
padding: "12px 20px"
}}
>
ダッシュボードへ
</Button>
</Container>
</Body>
</Html>
);
};
export default WelcomeEmail;
これ、普通のReactコンポーネントとほぼ同じ書き方なんですよ。TypeScriptも使えるし、propsで動的に内容を変えることもできます。
メールクライアント間の差異を吸収
Gmail、Outlook、Apple Mail、Yahoo!メール...それぞれレンダリングが微妙に違うんですが、React Emailのコンポーネントはこの差異を内部で吸収してくれます。
個人的にはこれが一番ありがたいポイントですね。Outlookだけ表示が崩れる問題に何度悩まされたことか。
Tailwind CSSにも対応
スタイリングにTailwind CSSを使うこともできます。
import { Tailwind, Button } from "@react-email/components";
const StyledEmail = () => {
return (
<Tailwind>
<Button className="bg-blue-500 text-white px-4 py-2 rounded">
クリック
</Button>
</Tailwind>
);
};
普段Tailwindを使っている人にとっては、これでさらに開発速度が上がると思います。
便利な組み込みコンポーネント
17種類以上のコンポーネントが用意されています。
- Html, Head, Body - 基本構造
- Container, Section, Row, Column - レイアウト
- Button, Link - インタラクション
- Img - 画像
- Heading, Text - テキスト
- Hr - 区切り線
- Preview - プレビューテキスト
これらを組み合わせるだけで、大抵のメールテンプレートは作れます。
インストール方法
セットアップは簡単です。
新規プロジェクトの場合
npx create-email@latest
これで必要なファイル構成が自動で生成されます。
既存プロジェクトに追加する場合
npm install @react-email/components -E
-Eオプションは正確なバージョンでインストールするためのものです。メールテンプレートは安定性が重要なので、バージョンを固定しておくのがおすすめですね。
React Emailのサンプルを動かす
React Emailは@react-email/componentsが提供するHtml・Body・Container・Text・Buttonといったコンポーネントを組み合わせるだけで、メールの見た目を組み立てられます。実際にコンポーネントとしてブラウザ上でレンダリングして確認できるサンプルを用意しました。下の入力欄で宛名と本文を書き換えると、その場でプレビューが変わります。
要点だけを抜き出すと、こんな形になります。
import { Html, Body, Container, Text, Button } from "@react-email/components";
function WelcomeEmail({ userName, message }: { userName: string; message: string }) {
return (
<Html>
<Body style={{ fontFamily: "sans-serif", backgroundColor: "#f6f9fc" }}>
<Container style={{ padding: "24px", backgroundColor: "#fff" }}>
<Text style={{ fontWeight: "bold" }}>{userName} 様</Text>
<Text>{message}</Text>
<Button
href="https://example.com"
style={{ backgroundColor: "#000", color: "#fff", padding: "12px 20px" }}
>
詳細を見る
</Button>
</Container>
</Body>
</Html>
);
}
実際に動かせるものが下です。「宛名」と「本文」の入力欄を書き換えると、Textコンポーネントの中身とプレビューがリアルタイムで変わります。宛名を空にしてみると、敬称部分がそのまま空欄になる様子も確認できます。
このように、HtmlやBody、ContainerといったReact Emailのコンポーネントは、実体としては見た目を整えるためのReactコンポーネントなので、userNameやmessageをpropsで渡すだけで表示を差し替えられます。実際の配信では、このWelcomeEmailをそのままrender()に渡してHTML化するか、Resendのreactオプションにそのまま渡すだけです。
基本的な使い方
1. テンプレートを作成
emailsディレクトリを作って、そこにコンポーネントを配置するのが一般的です。
// emails/notification.tsx
import {
Html,
Head,
Body,
Container,
Section,
Text,
Link,
Hr,
} from "@react-email/components";
interface NotificationEmailProps {
userName: string;
message: string;
}
const NotificationEmail = ({ userName, message }: NotificationEmailProps) => {
return (
<Html>
<Head />
<Body style={main}>
<Container style={container}>
<Section>
<Text style={heading}>{userName}さんへ</Text>
<Text style={paragraph}>{message}</Text>
<Hr style={hr} />
<Link href="https://example.com" style={link}>
詳細を確認する
</Link>
</Section>
</Container>
</Body>
</Html>
);
};
const main = {
backgroundColor: "#f6f9fc",
fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
};
const container = {
backgroundColor: "#ffffff",
margin: "0 auto",
padding: "20px",
maxWidth: "600px",
};
const heading = {
fontSize: "20px",
fontWeight: "bold",
marginBottom: "16px",
};
const paragraph = {
fontSize: "16px",
lineHeight: "1.6",
};
const hr = {
borderColor: "#e6ebf1",
margin: "20px 0",
};
const link = {
color: "#5469d4",
textDecoration: "underline",
};
export default NotificationEmail;
2. プレビューで確認
開発サーバーを起動してブラウザでプレビューできます。
npx react-email dev
これでリアルタイムにメールの見た目を確認しながら開発できます。ホットリロードにも対応しているので、変更が即座に反映されます。
3. HTMLに変換
作成したテンプレートはHTMLに変換して送信します。
import { render } from "@react-email/render";
import NotificationEmail from "./emails/notification";
const html = await render(
<NotificationEmail
userName="田中"
message="新しいコメントがあります"
/>
);
// このhtmlを任意のメール送信サービスで使用
実践的なユースケース
React EmailのButtonとLinkを装飾する
Buttonコンポーネントはstyleプロパティで色やサイズを自由に変えられるので、用途別にバリエーションを作っておくと便利です。ここでは「プライマリ」「デンジャー」「アウトライン」の3種類のボタンを、クリックで切り替えられるようにしています。
const variants = {
primary: { backgroundColor: "#000", color: "#fff" },
danger: { backgroundColor: "#dc2626", color: "#fff" },
outline: { backgroundColor: "#fff", color: "#000", border: "1px solid #000" },
};
<Button
href="https://example.com"
style={{ padding: "12px 20px", borderRadius: 4, ...variants[variant] }}
>
{variant === "danger" ? "アカウントを削除" : "詳細を見る"}
</Button>
実際に動かせるものが下です。上部のボタンでvariantを切り替えると、Buttonコンポーネントのstyleとラベル文言が同時に変わります。
ボタンを押すたびにvariantのstateが変わり、ButtonのstyleとLinkの周りのテキストがまとめて切り替わるのが分かると思います。variantsオブジェクトに新しいキーを追加すれば、そのまま新しいボタンパターンとして使えます。
React Emailで動的な注文明細メールを組み立てる
React Emailはpropsで受け取った値をそのまま表示できるので、配列データをmapしながら明細を組み立てるような動的な本文も作れます。ここでは注文アイテムのリストと合計金額を、Section・Row・Columnを使って一覧表示しています。
function OrderEmail({ items }) {
const total = items.reduce((sum, i) => sum + i.price * i.qty, 0);
return (
<Section>
{items.map((item) => (
<Row key={item.name}>
<Column>{item.name} × {item.qty}</Column>
<Column align="right">¥{item.price * item.qty}</Column>
</Row>
))}
<Hr />
<Text>合計: ¥{total}</Text>
</Section>
);
}
実際に動かせるものが下です。「商品を追加」ボタンを押すとitems配列が増え、reduceで計算した合計金額もその場で再計算されます。
「商品を追加」を押すたびにitemsが1件ずつ増え、RowとColumnで組んだ明細と、reduceで計算した合計金額の両方がその場で更新されます。実際の注文確認メールを作るときも、itemsをAPIから取得した配列に差し替えるだけで、同じ構造がそのまま使えます。
React EmailでTailwindスタイリングを使う
React EmailはTailwindコンポーネントで全体をラップすると、classNameでTailwind CSSのユーティリティクラスを使ってスタイリングできます。インラインスタイルを1つずつ書くより、配色やレイアウトのバリエーションを素早く試せるのが利点です。
import { Tailwind, Button, Text } from "@react-email/components";
<Tailwind>
<Text className="text-gray-700 text-base">お知らせがあります。</Text>
<Button className="bg-indigo-600 text-white px-5 py-3 rounded-md">
確認する
</Button>
</Tailwind>
実際に動かせるものが下です。テーマ切り替えボタンを押すと、classNameに渡す色クラス(bg-indigo-600やbg-emerald-600など)が変わり、Tailwindの配色ユーティリティだけでボタンの印象が変わる様子を確認できます。
テーマボタンを押すとthemeのstateが変わり、Buttonに渡すclassNameがbg-indigo-600からbg-emerald-600のように切り替わります。Tailwindのクラス名を差し替えるだけで配色を統一できるので、ブランドカラーに合わせたメールテンプレートを量産したいときに向いています。
Resendと組み合わせる
React Emailを作っているResend社のメール送信サービスとの組み合わせが最もスムーズです。
import { Resend } from "resend";
import WelcomeEmail from "./emails/welcome";
const resend = new Resend("re_xxxxx");
await resend.emails.send({
from: "noreply@example.com",
to: "user@example.com",
subject: "ようこそ",
react: <WelcomeEmail userName="田中" />,
});
HTMLへの変換すら不要で、Reactコンポーネントをそのまま渡せます。
SendGrid、AWS SESとの連携
他のメール送信サービスを使う場合は、HTMLに変換してから送信します。
import { render } from "@react-email/render";
import sgMail from "@sendgrid/mail";
const html = await render(<WelcomeEmail userName="田中" />);
await sgMail.send({
to: "user@example.com",
from: "noreply@example.com",
subject: "ようこそ",
html: html,
});
スパムチェック機能
React Emailには送信前にメールのスパム判定をチェックする機能もあります。これ、意外と重要で、せっかく作ったメールが迷惑メールフォルダに入ってしまったら意味がないですからね。
まとめ
React Emailは、メールテンプレート開発の苦痛をかなり軽減してくれるライブラリです。
おすすめポイント
- Reactを使っているなら学習コストほぼゼロ
- メールクライアント間の差異を自動で吸収
- TypeScriptによる型安全性
- Tailwind CSSも使える
- プレビュー機能で開発効率アップ
向いているケース
- Next.jsやReactベースのプロジェクトでメール送信機能を実装したい
- トランザクションメール(会員登録、パスワードリセットなど)を作りたい
- チームでメールテンプレートを管理したい
正直なところ、2025年にメールテンプレートを新規で作るなら、React Email一択だと思います。テーブルレイアウトと格闘する時代は終わりました。
参考リンク