技術系

Next.jsでメールを送る

技術系

こんにちは、なかにしです。

今回は、Next.jsでメールを送ろうと思います。

SMTPサーバはもちろん持っていないので、
外部SMTPサーバを使用します。

今回は、外部SMTPサーバ提供サービスの中でも利用者が多い、
Gmailを使用してメール送信します。

事前準備

Next.jsのプロジェクトを準備します。

今回は現在の最新バージョン、Next@14.0.4を使用します。

npx create-next-app [アプリ名]

適当にフォームを作成します。

▽ フロント側

"use client";

import axios, { AxiosError } from "axios";
import styles from "./page.module.css";

export default function Home() {
  /** 送信ボタン押下時 */
  const handleRequestData: React.FormEventHandler<HTMLFormElement> = (e) => {
    e.preventDefault();

    /** 入力内容をフォームデータにまとめる */
    const formData = new FormData(e.currentTarget);

    // データを送る
    axios
      .post("/api/mail", formData)
      .then((response) => console.log(response.data))
      .catch((error: AxiosError) =>
        console.error(`Status:${error.status}, Message:${error.response?.data}`)
      );
  };

  return (
    <main className={styles.main}>
      <p>フォーム</p>
      <form onSubmit={handleRequestData}>
        <div style={{ display: "flex", flexDirection: "column", gap: "20px" }}>
          <div style={{ display: "flex", gap: "20px" }}>
            <label htmlFor="name">名前</label>
            <input type="text" id="name" name="name" />
          </div>

          <div style={{ display: "flex", gap: "20px" }}>
            <label htmlFor="email">メールアドレス</label>
            <input type="email" id="email" name="email" />
          </div>

          <div style={{ display: "flex", gap: "20px" }}>
            <label htmlFor="content">内容</label>
            <textarea id="content" name="content" />
          </div>
          <input type="submit" value="送信" />
        </div>
      </form>
    </main>
  );
}

▽ バック側(/api/mail)
とりあえず疎通が取れるようにします。
メール送信のコードは後ほど実装します。

import { NextRequest } from "next/server";
import nodemailer from "nodemailer";

export async function POST(req: NextRequest) {
  /** formDataで来たらformData()で受け取る必要がある */
  const data = await req.formData();

  // データの取り出し
  const name = data.get("name");
  const email = data.get("email");
  const content = data.get("content");

  console.log(name)
  console.log(email)
  console.log(content)

  return NexResponse.json({nice:"Nice!"})
}

メールを送る

まず、今回のフロー図はこんな感じです。

「送信用」と「問い合わせ用」というメアドを1つずつ用意し、
「送信用」から「問い合わせ用」に、
問い合わせ者のメアドや問い合わせ内容を本文に入れたメールを送ります。

そして、管理者が「問い合わせ用」のメールボックスを確認し、
随時問い合わせ内容を返信していく、というフローです。

※EU域内のユーザーが対象に入っている場合は、個人情報取り扱いの同意が必須です。
問い合わせフォームに入れるようにしてください。

アプリパスワードの発行

GmailのSMTPサーバを使用する為には
「ユーザー名」「パスワード」が必要ですが、
それだけだと「2段階認証」ができず、メールが送れません。

代わりに「アプリのパスワード」を使用します。

以下リンクからアプリパスワードの設定画面に飛べます。
https://myaccount.google.com/apppasswords

▽ 「アプリ名」に任意の名前を入力し「作成」ボタンを押すと、パスワードが発行されます。
発行されたパスワードを控えておきます。

実装

nodemailer.createTransport を使用してメールの送信設定をします。
serviceに「gmail」、authに「ユーザー名」「パスワード」を入力します。

ユーザー名はメアド、パスワードは先ほどの「アプリパスワード」です。
見られないように.envに入れるのをお忘れなく。

▽ 実装例

import { NextRequest } from "next/server";
import nodemailer from "nodemailer";

export async function POST(req: NextRequest) {
  /** formDataで来たらformData()で受け取る必要がある */
  const data = await req.formData();

  // データの取り出し
  const name = data.get("name");
  const email = data.get("email");
  const content = data.get("content");

  const transporter = nodemailer.createTransport({
    service: "gmail",
    auth: {
      user: process.env.EMAIL_SEND_USER,
      pass: process.env.EMAIL_PASS,
    },
  });

  const mailOptions = {
    from: process.env.EMAIL_SEND_USER,
    to: process.env.EMAIL_RECEIVE_USER,
    subject: "問い合わせ",
    text: `送信者:${email}\n\n内容:${content}`,
  };

  try {
    await transporter.sendMail(mailOptions)
    return new Response(JSON.stringify({ message: "送信成功" }), { status: 200 })
  } catch (error) {
    console.log(error);
    return new Response(JSON.stringify({ message: "送信失敗" }), { status: 500 })
  }
}

これでフォームから入力した内容を、
お問い合わせ用アドレスへ送信出来るようになりました。

これにて完了です。

さいごに

今回は、Nextでメールを送ってみました!

無料でメールを送れるのは本当に助かります。
Google様様ですね。

とはいえ1回は自分でSMTPサーバを立ててみたいと思うので、それは後日やろうと思います。
(設定が複雑そうなので記事にしない可能性大)

今回はここまで!
Enjoy Hacking!!