現代のソフトウェアアプリケーションは、ユーザーとのコミュニケーションにメールを利用することがよくあります。例えば、サインインの試行時に認証コードを送信したり、マーケティングメールやニュースレターを送信したりします。つまり、メール通知は通常、ユーザーとのコミュニケーションの最も一般的な手段となっています。

このチュートリアルでは、React Emailを使用して魅力的なメールテンプレートをデザインし、シンプルで強力なメールAPIプラットフォームであるResendを使用してそれらを送信する方法を学びます。

前提条件

このチュートリアルを最大限に活用するために、ReactまたはNext.jsの基本的な理解が必要です。

また、以下のツールも使用します:

  • React Email: Reactコンポーネントを使用して美しくデザインされたメールテンプレートを作成するためのライブラリ。

  • Resend: アプリケーションからメールを送信するためのシンプルで強力なAPIプラットフォーム。

Next.jsを使用してアプリケーションを構築する方法

このセクションでは、シンプルなカスタマーサポートアプリケーションを作成します。このアプリには、ユーザーが問い合わせを送信するためのフォームが含まれ、サポートチケットが作成されたことを確認するメール通知がトリガーされます。

最初に、ユーザーインターフェースとAPIエンドポイントを設定します。

次のコマンドを実行して新しいNext.js TypeScriptプロジェクトを作成します:

npx create-next-app react-email-resend

app/page.tsxファイルを更新して、顧客の詳細(フルネーム、メールアドレス、チケットの件名、問題を説明する詳細メッセージ)を収集するフォームをレンダリングします。フォームが送信されると、入力データはhandleSubmit関数を使用してコンソールにログ出力されます。

"use client";
import support from "@/app/images/support.jpg";
import { useState } from "react";
import Image from "next/image";

export default function Page() {
    //👇🏻 入力状態
    const [name, setName] = useState<string>("");
    const [email, setEmail] = useState<string>("");
    const [subject, setSubject] = useState<string>("");
    const [content, setContent] = useState<string>("");

    const handleSubmit = async (e: React.FormEvent) => {
        e.preventDefault();
        //👇🏻 ユーザーの入力をログ出力
        console.log({ name, email, subject, content });
    };
return ({/** -- UI要素 -- */})
}

ユーザーのフルネーム、メールアドレス、チケット件名、および問題を説明する詳細メッセージを受け入れるフォームUI要素を返します。

    return (
        <main className='w-full min-h-screen flex items-center justify-between'>
                <form className='w-full' onSubmit={handleSubmit}>
                    <label htmlFor='name' className='opacity-60'>
                        Full Name
                    </label>
                    <input
                        type='text'
                        className='w-full px-4 py-3 border-[1px] mb-3 border-gray-300 rounded-sm'
                        id='name'
                        required
                        value={name}
                        onChange={(e) => setName(e.target.value)}
                    />

                    <label htmlFor='email' className='opacity-60'>
                        Email Address
                    </label>
                    <input
                        type='email'
                        className='w-full px-4 py-3 border-[1px] mb-3 border-gray-300 rounded-sm'
                        id='email'
                        value={email}
                        onChange={(e) => setEmail(e.target.value)}
                        required
                    />

                    <label htmlFor='subject' className='opacity-60'>
                        Subject
                    </label>
                    <input
                        type='text'
                        className='w-full px-4 py-3 border-[1px] mb-3 border-gray-300 rounded-sm'
                        id='subject'
                        value={subject}
                        onChange={(e) => setSubject(e.target.value)}
                        required
                    />

                    <label htmlFor='message' className='opacity-60'>
                        Message
                    </label>
                    <textarea
                        rows={7}
                        className='w-full px-4 py-3 border-[1px] mb-3 border-gray-300 rounded-sm'
                        id='message'
                        required
                        value={content}
                        onChange={(e) => setContent(e.target.value)}
                    />

                    <button className='w-full bg-blue-500 py-4 px-3 rounded-md font-bold text-blue-50'>
                        SEND MESSAGE
                    </button>
                </form>
            </div>
        </main>
    );

以下は、コンポーネントからの結果ページです:

次に、顧客の入力を受け入れるAPIエンドポイント(/api/route.ts)を作成します。

cd app
mkdir api && cd api
touch route.ts

api/route.tsファイルに以下のコードをコピーします。このAPIエンドポイントは、顧客の入力を受け取るとコンソールにログ出力します。

import { NextRequest, NextResponse } from "next/server";

export async function POST(req: NextRequest) {
    const { name, email, subject, content } = await req.json();
    //👇🏻 コンテンツをログ出力
    console.log({ name, email, subject, content });
    return NextResponse.json({
        message: "Email sent successfully",
        data,
 });
}

handleSubmit関数を更新して、顧客のデータをAPIエンドポイントに送信し、JSONレスポンスを返します:

const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();

    try {
        const response = await fetch("/api", {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
            },
            body: JSON.stringify({ name, email, subject, content }),
        });
        const data = await response.json();
        alert(data.message);
    } catch (error) {
        console.error(error);
        alert("An error occurred, please try again later");
    }
    setName("");
    setEmail("");
    setSubject("");
    setContent("");
};

おめでとうございます!データ収集と送信が設定されました。次のセクションでは、React EmailとResendを使用してメールテンプレートの作成と送信方法について説明します。

React Emailを使用したメールテンプレートの作成方法

React Emailを使用して、ReactとTypeScriptを使ってメールコンポーネントを構築して送信することができます。これは、Gmail、Yahoo Mail、Outlook、Apple Mailなど、複数のメールクライアントをサポートしています。

React Emailには、React JSX/TSXコンポーネントを使用して、メールテンプレートをカスタマイズするための複数のUIコンポーネントも用意されています。

以下のコードスニペットを実行して、React Emailパッケージとそのコンポーネントをインストールしてください:

npm install react-email -D -E
npm install @react-email/components -E

package.jsonファイルにこのスクリプトを含めてください。これにより、React Emailがプロジェクト内のメールテンプレートの場所を把握します。

  "scripts": {
    "email": "email dev --dir src/emails"
  },

React Emailの機能の1つとして、開発中にメールテンプレートをブラウザでプレビューして、受信者のメールでどのように表示されるかを確認できる点が挙げられます。

次に、Next.jsのsrcフォルダ内にTicketCreated.tsxファイルを含むemailsフォルダを作成し、次のコードスニペットをファイルにコピーしてください:

import * as React from "react";
import {
    Body,
    Container,
    Head,
    Heading,
    Hr,
    Html,
    Link,
    Preview,
    Text,
    Tailwind,
} from "@react-email/components";

interface TicketCreatedProps {
    username: string;
    ticketID: string;
}

const baseUrl = process.env.VERCEL_URL || "http://localhost:3000";

上記のコードスニペットでは、メールテンプレートを構築するために必要なコンポーネントをインポートしました。

次に、React Emailコンポーネントを使用してメールテンプレートをレンダリングするために、TicketCreatedコンポーネントをファイルに追加してください。

export const TicketCreated = ({ username, ticketID }: TicketCreatedProps) => {
    return (
        <Html>
            <Head />
            <Preview>Support Ticket Confirmation Email 🎉</Preview>
            <Tailwind>
                <Body className='bg-white my-auto mx-auto font-sans px-2'>
                    <Container className='border border-solid border-[#eaeaea] rounded my-[40px] mx-auto p-[20px] max-w-[465px]'>
                        <Heading className='text-black text-[24px] font-normal text-center p-0 my-[30px] mx-0'>
                            Your Ticket has been created
                        </Heading>
                        <Text className='text-black text-[14px] leading-[24px]'>
                            Hello {username},
                        </Text>
                        <Text className='text-black text-[14px] leading-[24px]'>
                            <strong>Support Ticket</strong> (
                            <Link
                                href={`${baseUrl}/ticket/${ticketID}`}
                                className='text-blue-600 no-underline'
                            >
                                {`#${ticketID}`}
                            </Link>
                            ) has been created successfully.
                        </Text>

                        <Text className='text-black text-[14px] leading-[24px]'>
                            The Support team will review your ticket and get back to you
                            shortly.
                        </Text>

                        <Hr className='border border-solid border-[#eaeaea] my-[26px] mx-0 w-full' />
                        <Text className='text-[#666666] text-[12px] leading-[24px]'>
                            This message was intended for{" "}
                            <span className='text-black'>{username}</span>. If you did not
                            create this ticket, please ignore this email.
                        </Text>
                    </Container>
                </Body>
            </Tailwind>
        </Html>
    );
};

最後に、それをエクスポートし、プロップスのデフォルト値を追加してください:

TicketCreated.PreviewProps = {
    username: "alanturing",
    ticketID: "9083475",
} as TicketCreatedProps;

export default TicketCreated;

ターミナルでnpm run emailを実行して、メールテンプレートをプレビューしてください。

このメールテンプレートは、顧客にサポートチケットが作成されたことを通知し、サポートチームの誰かが連絡を取ることをお知らせします。

React Emailは、さまざまな事前デザインされたメールテンプレートを提供しており、異なる目的のために美しくスタイリングされたメールを簡単に作成できます。利用可能なデモを見て例を確認できます

Resendを使ったメールの送信方法

Resendは、ソフトウェアアプリケーション内でメールを送信できるシンプルなメールAPIです。JavaScript(Next.js、Express、Node.js)、Python、PHP、Go、Rustなど、さまざまなプログラミング言語をサポートしています。

ResendとReact Emailは、Resendの共同創設者である木下武がReact Emailの作成者でもあるため、簡単に統合できます。

まず、Resendでアカウントを作成します。サインインしたら、ダッシュボードのAPIキーセクションに移動し、APIキーを.env.localファイルにコピーします。

//👇🏻 .env.local file
RESEND_API_KEY=<RESEND_API_KEY>

//👇🏻 .env.local ファイル

import { NextRequest, NextResponse } from "next/server";
React Emailテンプレートを使用してメールを送信するために、以下のようにAPIエンドポイントを更新します。
import { v4 as generateID } from "uuid";
//👇🏻 チケットID生成関数
import TicketCreated from "@/emails/TicketCreated";
//👇🏻 メールテンプレートをインポート
import { Resend } from "resend";
const resend = new Resend(process.env.RESEND_API_KEY);

export async function POST(req: NextRequest) {
    //👇🏻 Resendをインポート
    const { name, email, subject, content } = await req.json();
    //👇🏻 フロントエンドから顧客の入力を受け付ける
    console.log({ name, email, subject, content });
    //👇🏻 それらをログに記録する
    const { data, error } = await resend.emails.send({
        from: "Acme <[email protected]>",
        to: [email],
        subject: "Ticket Confirmation Email 🎉",
        react: TicketCreated({ username: name, ticketID: generateID() }),
    });

    if (error) {
        return NextResponse.json(
            { message: "Error sending email" },
            { status: 500 }
        );
    }

    return NextResponse.json({
        message: "Email sent successfully",
        data,
    });
}

//👇🏻 メールテンプレートを使用してメールを送信する

おめでとうございます!🥳 このチュートリアルを完了しました。

アプリケーションの簡単なデモはこちらです:

今後のステップ

このチュートリアルでは、React Emailを使用してメールテンプレートを作成し、Resendを使用して送信する方法を学びました。どちらのパッケージも、アプリケーション内でのメール通信を簡単に統合することを可能にします。

シンプルなメール通知、ニュースレター、マーケティングキャンペーンなど、React EmailとResendはニーズに応じた効率的でカスタマイズ可能なソリューションを提供します。

Next.jsアプリケーションにResendのインストール方法