📫

React Email x Resend で次世代メールサービスを体験

2023/06/20に公開

1. はじめに

Resendは Email を API 経由で送信するサービスです。

6 月 12 日に Resend のサービスがアップデートされ、無料プランで1ヶ月最大3000通メール、1日100通を送れる用になりました[1]。この時点では、利用者が限定されていましたが、Resend が 6 月 13 日に全てのユーザーが利用できるようにGAされました[2]

この記事では、次世代メールサービスの ResendReact Emai と組み合わせて、メールを送信する方法を紹介します。 [3]

https://resend.com/

https://react.email/

作業したソースはここにあります。

https://github.com/hayato94087/nextjs-reactemail-resend-sample

2. Resendとは

あらためて、Resendとは Email を API 経由で送信するサービスです。

React Emailとの関係

ResendReact Email で混合してしまうかもしれませんが、React Email と Resend は同じ創業者が立ち上げた別のサービスです。(正確にはReact Emailはパッケージ)

Resendが解決する課題

開発者の開発体験を重視し、開発者が使いやすい、React を使い、メールのテンプレートを作成できる React Email を立ち上げました。これにより、メールのテンプレートを React コンポーネントを使い作成できるようになりました。一方で、同時に最大の課題はメールテンプレートではなく、メール送信であることに気づきました。この課題を解決するために、創業者が Resend を立ち上げました[4]。創業者は Zeno RochaBu Kinoshita の 2 名です。

https://twitter.com/zenorocha

https://twitter.com/bukinoshita

React Email と Resend によるシナジー

React Email は React コンポーネントでメールテンプレートを作るライブラリーで、Resend はメールを送信するインフラです。React Email と Resend を組み合わせることで、より効率的な開発が可能となります。

競合他社との比較

Resend の競合相手となるメール配信プラットフォームは 2009/2010 年の創業された企業です。創業者いわく、10 年以上、開発者の開発体験を向上させるような革新的な進歩がおこなわれていないと言っています。Resend は、メール送信のプラットフォームを最新の技術で作り直し、開発者がメール送信をより効率的に行えるようになっているnext-generation Sendgridだと謳っています[5]

料金について

Sendgridの料金表Resendの料金表を比較しました。無償利用枠はSengridのほうが安いですが、有償利用枠に入ってくるとResendのほうが安いです。

開発体験はおいておき、無償利用枠についてはSendgridのほうがたくさん送信できます。Sendgridは12000通/月まで無償で、Reendは3000通/月まで無償です。

有料枠を利用し始めると、Resendのほうが料金プランが安くなります。

以下は1ヶ月の合計メール送信料にあわせた利用料金です。

1ヶ月のメール送信数 Sendgrid Resend
3000 0円 0ドル
12000 0円 20ドル
50000 3750円[6] 20ドル
100000 4600円 35ドル
200000 25000円[7] 80ドル
400000 40000円[8] 200ドル
800000 68000円[9] 400ドル
1600000 110500円[10] 700ドル
5000000 303500円[11] 1200ドル

https://sendgrid.kke.co.jp/plan/

https://resend.com/pricing

コミュニティサポート

困ったときにコミュニティからサポートを受けたいですが、Discordはないようなので、コミュニティからサポートを受けられる場所が分からなかったです。

3. React Email とは

あらためて、React Email とは、メールテンプレートを React コンポーネントで記述できるパッケージです。

React Emailが解決する課題

Web の HTML と比較日、メールの HTML は、CSS のサポートが悪く、レイアウトが崩れやすいです。また、メールの HTML は、メールクライアントによって、表示が異なる事もあります。メールの HTML を記述するのは、開発者にとって、大変な作業です。React Email は現在ベータバージョンですが、React Email を利用することで、様々なメールクライアントに対応したメールを簡単に作成できます。

対応メールクライアント

以下が対応しているメールクライアントです。

メールテンプレートの記述方法

React Email では、以下のようにコンポーネントを使いメールを記述できるようになります[12]。ウェブ開発で利用している<div>は使わず、以下のコンポーネントを使います。

  • Html
  • Head
  • Heading
  • Button
  • Link
  • Image
  • Divider
  • Paragraph
  • Container
  • Preview
  • Body
  • Column
  • Section
  • Font

メールの記載例が以下のサイトのまとめられています。

https://demo.react.email/preview/vercel-invite-user?view=desktop

Vercel のユーザーを招待するメールの例です。

以下のように React Email の独自コンポーネントを利用し記述できます。

import {
  Body,
  Button,
  Container,
  Column,
  Head,
  Heading,
  Hr,
  Html,
  Img,
  Link,
  Preview,
  Row,
  Section,
  Tailwind,
  Text,
} from '@react-email/components';
import * as React from 'react';

interface VercelInviteUserEmailProps {
  username?: string;
  userImage?: string;
  invitedByUsername?: string;
  invitedByEmail?: string;
  teamName?: string;
  teamImage?: string;
  inviteLink?: string;
  inviteFromIp?: string;
  inviteFromLocation?: string;
}

const baseUrl = process.env.VERCEL_URL
  ? `https://${process.env.VERCEL_URL}`
  : '';

export const VercelInviteUserEmail = ({
  username = 'zenorocha',
  userImage = `${baseUrl}/static/vercel-user.png`,
  invitedByUsername = 'bukinoshita',
  invitedByEmail = 'bukinoshita@example.com',
  teamName = 'My Project',
  teamImage = `${baseUrl}/static/vercel-team.png`,
  inviteLink = 'https://vercel.com/teams/invite/foo',
  inviteFromIp = '204.13.186.218',
  inviteFromLocation = 'São Paulo, Brazil',
}: VercelInviteUserEmailProps) => {
  const previewText = `Join ${invitedByUsername} on Vercel`;

  return (
    <Html>
      <Head />
      <Preview>{previewText}</Preview>
      <Tailwind>
        <Body className="bg-white my-auto mx-auto font-sans">
          <Container className="border border-solid border-[#eaeaea] rounded my-[40px] mx-auto p-[20px] w-[465px]">
            <Section className="mt-[32px]">
              <Img
                src={`${baseUrl}/static/vercel-logo.png`}
                width="40"
                height="37"
                alt="Vercel"
                className="my-0 mx-auto"
              />
            </Section>
            <Heading className="text-black text-[24px] font-normal text-center p-0 my-[30px] mx-0">
              Join <strong>{teamName}</strong> on <strong>Vercel</strong>
            </Heading>
            <Text className="text-black text-[14px] leading-[24px]">
              Hello {username},
            </Text>
            <Text className="text-black text-[14px] leading-[24px]">
              <strong>bukinoshita</strong> (
              <Link
                href={`mailto:${invitedByEmail}`}
                className="text-blue-600 no-underline"
              >
                {invitedByEmail}
              </Link>
              ) has invited you to the <strong>{teamName}</strong> team on{' '}
              <strong>Vercel</strong>.
            </Text>
            <Section>
              <Row>
                <Column align="right">
                  <Img className="rounded-full" src={userImage} width="64" height="64" />
                </Column>
                <Column align="center">
                  <Img
                    src={`${baseUrl}/static/vercel-arrow.png`}
                    width="12"
                    height="9"
                    alt="invited you to"
                  />
                </Column>
                <Column align="left">
                  <Img className="rounded-full" src={teamImage} width="64" height="64" />
                </Column>
              </Row>
            </Section>
            <Section className="text-center mt-[32px] mb-[32px]">
              <Button
                pX={20}
                pY={12}
                className="bg-[#000000] rounded text-white text-[12px] font-semibold no-underline text-center"
                href={inviteLink}
              >
                Join the team
              </Button>
            </Section>
            <Text className="text-black text-[14px] leading-[24px]">
              or copy and paste this URL into your browser:{' '}
              <Link
                href={inviteLink}
                className="text-blue-600 no-underline"
              >
                {inviteLink}
              </Link>
            </Text>
            <Hr className="border border-solid border-[#eaeaea] my-[26px] mx-0 w-full" />
            <Text className="text-[#666666] text-[12px] leading-[24px]">
              This invitation was intended for{' '}
              <span className="text-black">{username} </span>.This invite was sent from{' '}
              <span className="text-black">{inviteFromIp}</span> located in{' '}
              <span className="text-black">{inviteFromLocation}</span>. If you were not
              expecting this invitation, you can ignore this email. If you are
              concerned about your account's safety, please reply to this email to
              get in touch with us.
            </Text>
          </Container>
        </Body>
      </Tailwind>
    </Html>
  );
};

export default VercelInviteUserEmail;

メール配信サービスとの連携

以下のメール配信サービスとの連携ができます[13]

  • Resend
  • Nodemailer
  • SendGrid
  • Postmark
  • AWS SES

それでは、今回は、React Email を利用しメールテンプレートを作成し、Resend を利用しメールを送信してみましょう。

コミュニティサポート

Discordで困ったときにコミュニティからサポートを受けられます。

https://react.email/discord

4. 初期環境の構築

初期の環境構築として以下を実施しておきます。

  • Next.js App Router でプロジェクトを構築
  • GitHub にリポジトリを作成
  • Vercel にデプロイ

実施方法は以下の記事を参考にしてください。

https://zenn.dev/hayato94087/articles/b30efe589baa0e

今回は、以下のプロジェクト名称の前提で進めます。

項目
Next.jsのプロジェクト名 nextjs-reactemail-resend-sample
GitHubのリポジトリ名 nextjs-reactemail-resend-sample
Vercelのプロジェクト名 nextjs-reactemail-resend-sample

5 React Email を使ってみる

それでは、実際に React Email の環境を構築していきます。以下を参考にしながらマニュアルで設定していきます。

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

5.1. React Email のインストール

React Email のパッケージをついあ k します。

$ pnpm add react-email @react-email/button @react-email/html -E

5.2. .gitignoreについか

.gitignore に .react-email を追加します。

.gitignore
+# react email
+.react-email

5.2. スクリプトの追加

email dev で React Email の GUI を起動させることができます。

email dev --help でヘルプを確認できます。

$ pnpm email:dev --help                                                                         1 err  at 18:14:30 

> nextjs-reactemail-resend-sample@0.1.0 email:dev /Users/hayato94087/Private/nextjs-reactemail-resend-sample
> email dev "--help"

Usage: react-email dev [options]

Starts the application in development mode

Options:
  -d, --dir <path>  Directory with your email templates (default: "./emails")
  -p --port <port>  Port to run dev server on (default: "3000")
  -h, --help        display help for command

package.json に以下のスクリプトを追加します。-d オプションでメールテンプレートのディレクトリを指定します。-p で起動するポートを指定します。

{
  "scripts": {
    "email:dev": "email dev -d ./src/emails -p 3001"
  }
}

5.3. メールテンプレートを作成

メールテンプレートを作成します。

$ mkdir -p src/emails
$ touch src/emails/index.tsx
src/emails/index.tsx
import { Button } from '@react-email/button';
import { Html } from '@react-email/html';
import * as React from 'react';

export default function Email() {
  return (
    <Html>
      <Button
        pX={20}
        pY={12}
        href="https://example.com"
        style={{ background: '#000', color: '#fff' }}
      >
        Click me
      </Button>
    </Html>
  );
}

5.4. メールテンプレートをローカルで確認

先程作成したスクリプトを実行し、React Email の GUI を起動させます。

$ pnpm email:dev

React Email の GUI が起動します。

作成したメールのプレビューが確認できます。

Source を確認すると、記載したコードを確認できます。

Resend を使ってテストメールを送ることができます。

無事メールが届いていました。

6. Resend を使ってみる

ここでは、さらに、Resend を使って、React Email で作ったメールテンプレートを利用しメールを送信します。

6.1. Resend の アカウント作成

ここでは、アカウント作成する手順を詳細に記載しています。

サイトにアクセスし、「Get Started」をクリックします。

自前の GitHub アカウントでサインアップします。

GitHub アカウントでサインアップした後に、チーム名の記載をもとめられます。入力したら次へ進めます。

フリープランでの登録完了しました。

6.2. Resend SDK インストール

Resend Node.js SDK をインストールします。

pnpm add resend

6.3. ドメインの登録

Resend にドメインを登録します。

「Add domain」をクリックします。

ドメインを追加します。

  1. 事前に取得しているドメインを入力します。
  2. Region は、表示された選択肢の中から選択しておきます。
  3. Add をクリックします。

ドメインの DNS レコードに追加すべき情報が赤枠に表示されます。

DNS レコードを登録します。今回は Google ドメインで取得したので Google ドメインの画面です。

Verify DNS Records をクリックし、DNS レコードを検証を開始します。

DNS レコードの検証は Google ドメインの場合は 5 分〜10 分ほどかかりました。

検証が完了しました。

ドメイン一番に登録されたドメインが表示されます。

6.4. APIKEYの取得

「API Keys」の画面に遷移し、「Create API Key」をクリックして、API キーを追加します。

APIKEY に必要な項目を入力 k します。

  1. API Key の名前を入力します。(今回は、「sending api key」としました)
  2. Permission のところに権限を設定します。「Full access」か「Sending access」のいずれかを選択できます。(今回は「Sending access」を選択しました。)
  3. ドメインを選択できます。(今回は、先程登録したドメインを選択しましいた)

API キーが表示されますので、コピーして保存しておきます。

作成した APIKEY は一覧で確認できます。ここでは 1 件しか表示されていませんが、複数個作成できます。

6.5. APIKEYを設定

.env.local の<your_apikey>に API キーを設定します。

$ touch .env.local
.env.local
RESEND_API_KEY=<your_apikey>

6.6. EmailをReactから送信

Route Handler を利用しているため、React からメールを送信するために、route.ts を作成します。route.ts では EmailTemplate を読み込み、React コンポーネントで作成されたメールテンプレートを利用しメールを作成し、送信します。

$ mkdir -p src/app/api/send
$ touch src/app/api/send/route.ts
app/api/send/route.ts
import Email from "@/emails";
import { NextResponse } from "next/server";
import { Resend } from "resend";

const resend = new Resend(process.env.RESEND_API_KEY);

export async function POST() {
  try {
    const data = await resend.emails.send({
      from: "onboarding@vercelstudyx2af.com",
      to: process.env.YOUR_EMAIL as string,
      subject: "Hello world",
      react: Email(),
    });

    return NextResponse.json(data);
  } catch (error) {
    return NextResponse.json({ error });
  }
}

6.7. 環境変数の自身のメールアドレスを記載

.env.local
RESEND_API_KEY=<your_apikey>
+YOUR_EMAIL=<your_email>

6.8. メールを送信

ローカルサーバを起動させてメールが送信できるか確かめます。

$ pnpm dev

/api/send に POST リクエストを送信します。メールの送信 ID が返却されるので、この ID を使って、メールの送信ステータスが確認できます。データベースなり保存しておくと良いです。

$ curl -X POST http://localhost:3000/api/send

{"id":"f12394bd-XXXX-XXXX-XXXX-XXXXXXXXXXXX"}

メールは無事届いていました。ドメインは登録したドメインから無事メールが送信されています。

7. Resendのダッシュボード

実装部分は一旦ここまでで、ここでは、Resend のダッシュボードを確認していきます。

7.1. Overview

ログイン毎に表示される最初の画面では、メールの送信数やなどの情報が確認できるようです。

7.2. 送信済みメール一覧

Resend のダッシュボードで送信されたメールを確認できます。

以下のように、送信されたメール一覧を確認できます。クリックするとメールの内容を確認できます。

送信されたメールの詳細を確認できます。プレビュー画面では送信済みのメールも確認できます。

7.3. ドメイン管理

ドメインを登録、確認できます。すでに説明済みなので割愛します。

7.4. 送信ログ監視

Resend のダッシュボードで、処理 ID ごとのログを確認できます。

クリックすると詳細が確認できます。

7.5. APIKey管理

API キー新規作成、発行済 API キーの確認、削除できます。

設定ボタンをクリックし、「Remove APIKEY」で APIKEY を削除できます。

7.6. Wehookの設定

Webhook を登録すると、メールに関するイベントを受け取る事ができます。

受け取れるイベント一覧を確認できます。

7.7. 設定

各種設定が可能です。

送信数の確認

自身がこれまで送信したメールの数の確認ができます。

プランの確認・変更

利用しているプランの確認、変更できます。

IPの追加

IP を追加できます。

まとめ

この記事では、ResendReact Emai と組み合わせて、メールを送信する方法を紹介しました。料金的にもSendgridと遜色なく、開発体験も優れていることから、Resendの利用を考えたいと思います。

脚注
  1. https://resend.com/blog/new-free-tier ↩︎

  2. https://twitter.com/resendlabs/status/1668622792919773187?s=20 ↩︎

  3. React Email,Resend、ともにnext-generationと謳っています ↩︎

  4. https://resend.com/blog/introducing-resend ↩︎

  5. https://resend.com/blog/introducing-resend ↩︎

  6. 2300+10000*0.145=3750円 ↩︎

  7. 12000+100000*0.130=25000円 ↩︎

  8. 30000+100000*0.100=40000円 ↩︎

  9. 59000+100000*0.090=68000円 ↩︎

  10. 104000+100000*0.065=110500円 ↩︎

  11. 141000+2500000*0.065=303500円円 ↩︎

  12. https://github.com/resendlabs/react-email#components ↩︎

  13. https://github.com/resendlabs/react-email#integrations ↩︎

  14. https://resend.com/docs/dashboard/domains/google-domains ↩︎

Discussion