📨

React Email で HTML メールを作成・送信する

に公開

React Email とは

https://react.email/

React Email は、React コンポーネントを使用してメールテンプレートを構築するためのフレームワークです。
HTML メールの複雑さを抽象化し、開発者が使い慣れた React でメールを作成できるようにするものです。

主な特徴は以下です。

  • React ベース: 使い慣れた React コンポーネントでメールを設計
  • レスポンシブ対応: 様々なデバイスでの表示に最適化
  • 再利用可能なコンポーネント: 一貫したデザインを実現
  • 型安全: TypeScript によるサポート
  • プレビュー機能: 開発中にリアルタイムでメールをプレビュー

HTML メールの作成は難しい!?

HTML メールの作成は、通常の Web ページ開発とは異なる多くの複雑さと制約を持っています。

Gmail や Outlook など、メールクライアントは様々なレンダリングエンジンを使用しており、それぞれが異なる HTML/CSS のサポートレベルを持っています。

React Email がこれらの複雑さを効果的に抽象化し、開発者体験を向上させてくれます。

React と TypeScript でメールを作成・送信する

React Email でメールを作成して、送信してみましょう!

セットアップ

今回は pnpm を使用し、Manual Setup を参考にセットアップしていきます。

mkdir react-email-app
cd react-email-app
npm init

必要な React Email パッケージをインストールしていきます。

pnpm add react-email -D -E
pnpm add @react-email/components react react-dom -E

package.json にデバッグ用のコマンドを追記します。

package.json
{
  "scripts": {
    "dev": "email dev"
  }
}

ディレクトリ構成

デフォルトの設定で開発する場合、emails フォルダにメールテンプレートを格納し、static フォルダには画像などの静的ファイルを格納します。

emails フォルダはメールテンプレートを格納する場所なので、.tsx ファイルがメールと判定されてしまいます。それを _ プレフィックスをつけることで回避することができます。

root
└── emails
    ├── _components
    │   ├── header.tsx
    │   └── footer.tsx
    ├── static
    │   └── mountain.png
    └── my-email.tsx

メール本文を実装する

Tailwind コンポーネントを使い、メールを装飾してみました。

my-email.tsx
import { 
  Body,
  Button,
  Container,
  Head,
  Html,
  Preview,
  Section,
  Tailwind,
  Text
} from "@react-email/components";
import Header from "./_components/header";
import Footer from "./_components/footer";

interface MyEmailProps {
  title?: string;
  userId?: string;
  userName?: string;
}

const STATIC_URL = process.env.BASE_URL ? `https://${process.env.BASE_URL}` : "";

export default function MyEmail({ title, userId, userName }: MyEmailProps) {
  const titleText = title || "これはテストメールです";

  return (
    <Html>
      <Tailwind>
        <Body className="bg-white my-auto mx-auto font-sans px-2">
          <Container>
            <Head>
              <title>{titleText}</title>
            </Head>
            <Preview>{titleText}</Preview>
            <Header logoUrl={`${STATIC_URL}/static/logo.png`} text={`Hi, ${userName}(@${userId})!`} />
            <Section>
              <Text className="text-center font-bold">これはテストメールの本文です。</Text>
              <Button
                href={`https://zenn.dev/${userId}`} 
                className="mx-auto block w-full w-[320px] rounded-full bg-blue-400 px-2 py-3 text-center font-bold text-neutral-50"
              >
                  {userName}さんの記事一覧 - Zenn
              </Button>
            </Section>
            <Footer />
          </Container>
        </Body>
      </Tailwind>
    </Html>
  );
}

MyEmail.PreviewProps = {
  title: "これはテストメールです",
  userId: "codemountains",
  userName: "山とコード",
};
header.tsx
import { Column, Heading, Img, Row, Section } from "@react-email/components";

interface HeaderProps {
  logoUrl: string;
  text: string;
}

export default function Header({ logoUrl, text }: HeaderProps) {
  return (
    <Section>
      <Img src={logoUrl} alt="logo" className="mx-auto"/>
      <Row>
        <Column>
          <Heading className="text-center">{text}</Heading>
        </Column>
      </Row>
    </Section>
  );
};
footer.tsx
import { Section, Text } from "@react-email/components";

export default function Footer() {
  return (
    <Section className="mt-8">
      <Text className="text-center">※このメールは送信専用です。</Text>
    </Section>
  );
};

デバッグとテスト送信

pnpm dev で開発用サーバを起動して、メールのデザインを確認することができます。

プレビュー時の Props は PreviewProps で、以下のように指定しています。

MyEmail.PreviewProps = {
  title: "これはテストメールです",
  userId: "codemountains",
  userName: "山とコード",
};

また、メールのテスト送信機能も備わっています。

画面右上の [Send] から、Resend 経由でメールを送信できます。

Gmail での表示結果です。

Resend で送信処理を実装する

メールを送信する処理を自前でも実装してみます。

Resend のパッケージをインストールします。

また、React コンポーネントを扱う都合上 .tsx ファイル単体を実行したいので、tsx コマンドを使用します。

pnpm add resend
pnpm add -D tsx  

Send email using Resend を参考に、sender/send-my-email.tsx を作成しました。

sender/send-my-email.tsx
import { Resend } from "resend";
import MyEmail from "../emails/my-email";

const Send = async () => {
  console.log("Sending email...");

  // Resend の API キーを埋め込む
  const resend = new Resend("re_123456789");

  try {
    await resend.emails.send({
      from: "Sending Test <onboarding@resend.dev>",
      to: "to_email_address", // 送信先を指定
      subject: "My email sending test",
      react: <MyEmail title="Test with Resend" userId="codemountains" userName="山とコード" />
    });

    console.log("Email sent completed!");
  } catch (error) {
    console.error(error);
  }
};

Send();

以下のコマンドで実行します。

npx tsx sender/send-my-email.tsx

HTML ファイルをエクスポートする

メール送信処理は Node.js でなく、他の言語で実装したいケースもあると思います。

そのようなユースケースの場合は、作成したメールテンプレートを HTML でエクスポートすることができます。
出力先は ./out です。

package.json
{
  "scripts": {
    "export": "email export"
  }
}

HTML ファイルをエクスポートする際の注意点は Props です。
当然、上記 my-email.tsx ではエクスポート時に MyEmailProps を指定できないので、値が undefined となります。

Hi, undefined(@undefined)!

まとめ

HTML を直接記述することなく、E メールを作成できました🤝🤝🤝

普段から React を使用している場合、非常に便利な選択肢になるのかなと思います!

参考

株式会社microCMS

Discussion