📑

Next.jsアプリのNodemailerをResendに置き換えた

2024/06/19に公開

はじめに

バニッシュ・スタンダード深田です。

私は業務でGoとReactをメインとしたサービス開発に携わっていますが、個人開発ではT3 Stack(Next.js、TypeScript、tRPC、Prisma、Tailwind CSS、NextAuth.jsの開発スタック)をベースとした効率的な小規模開発にも取り組んでいます。この個人開発をVercelにデプロイしましたが、メール送信機能が不安定な問題に遭遇しました。そこで、Resendを利用してこの問題を解決した方法について説明します。

問題

アプリケーション内でのユーザー登録やパスワードリセット機能にはメール送信が必要で、Nodemailerを使用して実装していました。しかし、Vercel環境ではメールが送信される場合もありましたが、何らかの制限で送信されないケースも多く発生しました。Vercelの公式ドキュメントでも、Nodemailerを使用する場合にも外部のSMTPプロバイダーを使用することが推奨されているようでした。

以下に、現状のNodemailerを使用していたコード例を示します。

import { TRPCError } from "@trpc/server"
import nodemailer from "nodemailer"

// SMTPサーバの設定
const transporter = nodemailer.createTransport({
  pool: true,
  service: "gmail",
  port: 465, // GmailのSMTPサーバのポート
  auth: {
    user: process.env.GMAILUSER || "",
    pass: process.env.GMAILPASSWORD || "",
  },
  maxConnections: 1,
})

// メール送信
export const sendEmail = async (
  subject: string,
  body: string,
  sendTo: string
) => {
  const mailOptions = {
    // 送信元
    from: `深田 <${process.env.GMAILUSER}>`,
    // 送信先
    to: sendTo,
    // 件名
    subject: subject,
    // 本文
    html: body,
  }

  // メール送信
  transporter.sendMail(mailOptions, (error) => {
    if (error) {
      console.log(error)
      throw new TRPCError({
        code: "BAD_REQUEST",
        message: "メールの送信に失敗しました",
      })
    }
  })
}

Resendの導入

Vercelの公式ドキュメントにもサードパーティのメールサービスを導入することが推奨されていたので、Nodemailerの代わりに、Resendを導入してこの問題を解決することにしました。Resendにしたのは、公式に次世代のSnedGridと書かれていたからです。

Resendを導入する手順を下記を元に進めていきます。
https://resend.com/docs/send-with-nextjs

1.Resendアカウントの設定

まず、Resendの公式サイトにアクセスし、アカウントを作成します。アカウント作成後、APIキーを取得します。

2. 独自ドメインの設定

Resendを利用して独自ドメインでメールを送信するためには、ドメイン認証を行う必要があります。動作確認を優先したい方はここはスキップして、Resendが提供する既定のドメイン(@resend.dev)を使用してください。

注意点として、既定のドメイン(@resend.dev)を利用したメール送信は、自身のメールアドレスに対してのみ実行可能です。他のメールアドレスへメール送信を行うためには、独自ドメインの認証が必要です。

独自ドメインはこちらを参考にしてください。

Resendに独自ドメインを登録

DNSレコード設定にDNSレコードを追加

ご利用のDNSプロバイダの管理画面で、以下のレコードを追加してください。ここではXserverを例に説明していますが、ご自身の環境に応じて対応してください。

  • MXレコード:Resendが提供するMXレコードを追加します。
  • SPFレコード(TXTレコード):Resendが指定するSPFレコードをTXTレコードとして追加します。
  • DKIMレコード(TXTレコード):Resendが提供するDKIMレコードをTXTレコードとして追加します。
  • DMARCレコード(オプション、TXTレコード):必要に応じてDMARCレコードをTXTレコードとして追加します

認証開始

Resend側で認証を開始してください。画像は一度失敗したものなので Restarg verificationとなっています。

認証済み確認

Resend側で認証済みであることを確認してください。

3.環境変数の登録

.env.local
RESEND_API_KEY="API Key"

4.Resendのインストール

npm install resend

5.Resendによるメール送信ロジックの実装

import { TRPCError } from "@trpc/server";
import { Resend } from "resend";

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

interface SendEmailOptions {
  subject: string;
  body: string;
  sendTo: string;
}

// メール送信
export const sendEmailByResend = async ({
  subject,
  body,
  sendTo,
}: SendEmailOptions) => {
  try {
    const response = await resend.emails.send({
      from: "深田 <onboarding@resend.dev>", // 独自ドメインの認証が通ったら置き換える
      to: [sendTo],
      subject: subject,
      html: body,
    });

    if (!response) {
      throw new TRPCError({
        code: "BAD_REQUEST",
        message: "メールの送信に失敗しました",
      });
    }
  } catch (error) {
    console.error(error);
    throw new TRPCError({
      code: "BAD_REQUEST",
      message: "メールの送信に失敗しました",
    });
  }
};

6.動作確認

ローカルでもVercelでもResend経由でメールが送信されるようになりました。何度か試していますが、送信されないという問題は今のことろ発生していません。

まとめ

今回のケースでは、VercelにデプロイしWEBアプリケーション上でNodemailerを使用したメール送信がうまく機能しない問題に直面しましたが、Resendを利用することで問題を解決しました。

最後に

弊社「株式会社バニッシュ・スタンダード」では、現在エンジニアおよびデザイナーを積極的に募集しています。

私も入社してから数ヶ月ですが、幅広い技術領域に携わることができ、日々充実した仕事ができています。技術レベルの高いエンジニアが多く、成長意欲のある方には特におすすめです。また、みんなが仕事に対して責任感を持ち、親切な人ばかりなので、非常に働きやすい環境です。

少しでも興味を持たれた方は、ご応募をお待ちしています。
https://v-standard.notion.site/Engineering-at-VANISH-STANDARD-929c17c0252c4d4a92fefc9a90b04d1a

Discussion