📈

Next.js + Nodemailer で問い合わせformを作る

2024/01/11に公開

技術スタック

  • Frontend: Next.js
  • Backend: Node.js (Nodemailer)
  • Form Validation: Yup
  • Styling: Tailwind CSS

フォルダ構成

-app
 -_components
  .ContactFrom.tsx
 -contact
  .page.tsx
 -api
  -contact
   .router.ts
 -server
  .contact.ts
  .email.ts

install ライブラリ

yarn add yup
yarn add nodmailer

https://github.com/jquense/yup
https://nodemailer.com/

コード

_components/ContactFrom.tsx
const onSubmit = (e: FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    sendContactEmail(form)
      .then(() => {
        setBanner({
          message: "メール転送を成功しました。",
          status: "success",
        });
        setForm(DEFAULT_DATA);
      })
      .catch(() => {
        setBanner({
          message: "メール転送を失敗しました。再転送してください。",
          status: "error",
        });
      })
      .finally(() => {
        setTimeout(() => {
          setBanner(null);
        }, 3000);
      });
  };
server/contact.ts
export async function sendContactEmail(email: EmailData) {
  const res = await fetch("/api/contact", {
    method: "POST", // HTTP POST methodを使ってサーバーにデータを転送します。
    body: JSON.stringify(email), // email objectをJSONに変換してbodyに入れます。
    headers: {
      "Content-Type": "applicatioin/json", 
    },
  });

  const data = await res.json();
  if (!res.ok) {
    throw new Error(data.message || "fail server request");
  }

  return data;
}

userが入力したメールデータを/api/contactAPIに転送してAPIからの返答を処理します。

api/contact/route.ts
import { sendEmail } from "@/app/server/email";
import * as yup from "yup";

const bodySchema = yup.object().shape({
  from: yup.string().email().required(),
  subject: yup.string().required(),
  message: yup.string().required(),
});

export async function POST(req: Request) {
  const body = await req.json();
  if (!bodySchema.isValidSync(body)) {
    return new Response(JSON.stringify({ message: "メール転送失敗" }), {
      status: 400,
    });
  }
  return sendEmail(body) //
    .then(
      () =>
        new Response(JSON.stringify({ message: "メール転送成功" }), {
          status: 200,
        })
    )
    .catch((error) => {
      console.error(error);
      return new Response(JSON.stringify({ message: "メール転送失敗" }), {
        status: 500,
      });
    });
}

クライアントからHTTP POST リクエストを受け、リクエスト本文に含まれる電子メール データの有効性を検査し、有効なデータの場合は電子メールを送信します。
電子メールの送信が成功すると、成功メッセージとともに200ステータスコードを返し、失敗すると失敗メッセージとともに500ステータスコードを返します。
これにより、クライアントはリクエストが成功したかどうかを知ることができます。

yupとは

Yupは、JavaScriptTypeScriptで使用されるオブジェクトスキーマ有効性チェックライブラリです。 これにより、簡単にデータの有効性を確認し、検証できます。
ここではサーバーでクライアントから受け取ったデータが正しい形式であることを確認し、正しければ電子メールを送信し、正しければエラーメッセージを返す機能をします。

server/email.ts
import nodemailer from "nodemailer";

export type EmailData = {
  from: string;
  subject: string;
  message: string;
};

const transporter = nodemailer.createTransport({
  host: "smtp.gmail.com",
  port: 465,
  secure: true,
  auth: {
    user: process.env.AUTH_USER,
    pass: process.env.AUTH_PASS,
  },
});

export async function sendEmail({ subject, from, message }: EmailData) {
  const mailData = {
    to: process.env.AUTH_USER,
    subject: `[BLOG] ${subject}`,
    from,
    html: `
    <h1>${subject}</h1>
    <div>${message}</div>
    <br/>
    <p>送信元: ${from}</p>`,
  };
  return transporter.sendMail(mailData);
}

Nodemailerを使ってGmailにメールを送ります。Userから入力もらったEmailDataを構成して転送します。

結論

Node.jsとNodemailerを利用することにより、比較的シンプルなバックエンド設定で安全かつ効率的なメール送信機能を実現できました。これにより、従来のウェブ開発においては複雑なバックエンドシステムを必要としていたメール送信機能を、より簡単に実装することが可能になりました。Yupを使用した効率的なフォーム検証プロセスを通じて、エラーの可能性を減少させ、ユーザー体験を向上させることもできます。

コレは特に小規模から中規模のプロジェクトにおいて効果的であり、開発者は複雑なバックエンドシステムを別途構築することなく、フロントエンドから直接メール送信のような機能を実装できるという点で大きな利点があります。

google email AUTH_USER、AUTH_PASS設定


Googleアカウントを管理をクリックしてセキュリティに入ります。


2段階認証プロセスをクリックしてアプリパスワードに入ります。



アプリ名を入れるとパスが出ます!

Discussion