react-emailでHTMLメールを作ってみた

## この記事の概要

HTMLメールを手動で作成したことはありますか？
WYSISYGなエディタで作るならともかく、1からHTMLを書いて作るのは大変ですよね。
考えた通りのスタイリングを施そうと思うと結局外部サービスでは上手くいかず手書きした経験が何度かありますが、結構本当にしんどいです。

そんな中、react-emailというReactでHTMLメールを作れるライブラリを見つけたので試しに触ってみました。

https://github.com/zenorocha/react-email

## 使い方

セットアップをします。
マニュアルとオートがありますが、今回はオートを選びます。

https://react.email/docs/getting-started/automatic-setup

私は普段Yarnを使っているのでYarnで実行します。
npxでもセットアップできます（その場合は`npx create-email@latest`）。

```shell
yarn create email
```

```shell
success Installed "create-email@0.0.4" with binaries:
      - create-email
⠋ Preparing files...
qiita-react-email
├── emails
│   ├── notion-magic-link.tsx
│   ├── plaid-verify-identity.tsx
│   ├── stripe-welcome.tsx
│   └── vercel-invite-user.tsx
├── package.json
✔ React Email Starter files ready
✨  Done in 4.38s.
```

依存関係をインストール。

```shell
yarn
```

立ち上げ。

```shell
yarn dev
```

`localhost:3000`で確認できるようになりました。

```shell
$ email dev
✔ React Email files ready
✔ React email is up-to-date
✔ Emails preview generated
✔ Dependencies installed
$ next dev
ready - started server on 0.0.0.0:3000, url: http://localhost:3000
```

表示される通り、`emails`フォルダの中にメールを作成します。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/b6e8e925-9a4a-85cb-e22a-875a9c199a10.png)

サンプルファイルを真似てコードを書いてみました。

```typescript:my-first-email.tsx
import * as React from "react";
import { Button } from "@react-email/button";
import { Container } from "@react-email/container";
import { Head } from "@react-email/head";
import { Hr } from '@react-email/hr';
import { Html } from "@react-email/html";
import { Img } from "@react-email/img";
import { Link } from "@react-email/link";
import { Preview } from "@react-email/preview";
import { Section } from "@react-email/section";
import { Text } from "@react-email/text";

export default function Email() {
  return (
    <Html>
      <Head />
      <Preview>My first email</Preview>
      <Section style={section}>
        <Container style={container}>
          <Img
            src="https://picsum.photos/id/0/300/200"
            alt=""
            width="300"
            height="200"
            style={image}
          />
          <Text style={heading}>This is my first email</Text>
          <Text style={paragraph}>
            <Link href="https://example.com">Lorem ipsum</Link> dolor sit amet,
            consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
            labore et dolore magna aliqua.
          </Text>
          <Hr />
          <Text>
            Ut enim ad minim veniam, quis nostrud
            exercitation ullamco laboris nisi ut aliquip ex ea commodo
            consequat. Duis aute irure dolor in reprehenderit in voluptate velit
            esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat
            cupidatat non proident, sunt in culpa qui officia deserunt mollit
            anim id est laborum.
          </Text>
          <Section style={buttonWrapper}>
            <Button style={button}>Check it out!</Button>
          </Section>
        </Container>
      </Section>
    </Html>
  );
}

// スタイルの定義は省略
```

出力結果は次のようになりました。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/fd42b209-1bf2-fdf6-026d-0f7afa3c61d7.png)

たかがこれだけですが、HTMLメールを手で書いたことのある身としてはあまりにも簡単で涙が出るかと思いました。

## ドキュメントに載っていないけど存在するコンポーネント

基本的には[docs/component](https://react.email/docs/components/html)に呼び出し方やPropsが載っているのですが、[Column](https://github.com/zenorocha/react-email/tree/main/packages/column)、[Heading](https://github.com/zenorocha/react-email/tree/main/packages/heading)、[Hr](https://github.com/zenorocha/react-email/tree/main/packages/hr)、[Section](https://github.com/zenorocha/react-email/tree/main/packages/section)は載っていなかったので列挙だけしておきます。

使い方は他のコンポーネントとなんら変わりません。

## 最後に

私がデザイナーなのもあり、普段HTMLメールを作成する際は実際の送信まで行っていません。
そのため今回も一旦メールの見た目を作成するまでの記事です。

しかし、送信までして初めてHTMLメールなので（？）どこかで触ってみたいと思います。

---

最後まで読んでくださってありがとうございます！
Twitterでも情報を発信しているので、良かったらフォローお願いします！

https://twitter.com/xrxoxcxox

Devトークでのお話してくださる方も募集中です！

https://jobs.qiita.com/employers/qiita-inc/dev_talks/489