Nuxt3で問い合わせフォーム作成

## はじめに
Nuxt3でポートフォリオ作成にあたり、お問合せ内容を自分が利用しているgmailへ届くようにお問合せフォームを実装しました。
フォーム実装にあたりNuxt3自体がJavaScript/TypeScriptで構成されていることから、同じ環境内で完結するNode.jsをベースのソリューションを採用いたしました。

## 環境
### 対応OS
・macOS

### 対応バージョン
・nuxt 3.12.3
・node v23.2.0

### 対応エディタ
・VSCode

### ディレクトリ構成
```
project/
 ├ server/
 |  └ api/
 |      └ sendMail.ts
 └ pages/
     └ index.vue
```

## 実装手順(環境構築は完了している前提)
### 1.Gmailの設定
GmailのSMTPを利用するために任意の2段階認証がONになっているアカウントでアプリ パスワードを設定する。(以下リンクの「アプリ パスワードを作成、使用する」参照)
設定したパスワードは後ほど利用するためメモの残しておく。

https://support.google.com/mail/answer/185833?hl=ja

### 2.Nodemailerのインストール
Node.jsのメール送信ライブラリをインストールする。

```ruby:Bash

npm install nodemailer

```

https://www.nodemailer.com/

上記だけだと```nodemailer```をimportしてきた際、型エラーになるので型定義のパッケージもインストールしておく。
```ruby:Bash

npm i --save-dev @types/nodemailer

```

https://www.npmjs.com/package/@types/nodemailer

### 2.環境変数に定義
セキュリティ確保のために1で利用したアカウントのGmailと設定したパスワードを環境変数として管理する

### 3.Nuxt 3のAPIハンドラーを作成
インストールしたnodemailerを利用したメールを送信するAPIを作成。
※1：1で利用したアカウントのGmailと設定したパスワード
※2：送信者のメールアドレス
※3：送信先のメールアドレス(Gmail以外でも可)
```typescript:project/server/sendMail.ts
import { defineEventHandler, readBody } from 'h3';
import nodemailer from 'nodemailer';

export default defineEventHandler(async (event) => {
    const body = await readBody(event);
    const transporter = nodemailer.createTransport(
        {
            host: 'smtp.gmail.com',
            port: 587, 
            secure: false,
            auth: { 
                user: 'メールアドレス(※1)', 
                pass: 'パスワード(※1)' 
            } 
        }
    );
    const mailOptions = { 
        from: 'メールアドレス(※2)', 
        to: 'メールアドレス(※3)', 
        subject: 'お問い合わせフォームからのメッセージ', 
        text: `名前: ${body.name}\nメールアドレス: ${body.email}\nメッセージ: ${body.message}`
    };
    
    try { 
        await transporter.sendMail(mailOptions);
        return { message: 'メールが送信されました。' };
    } catch (error) { 
        return { error: `メールの送信に失敗しました。 エラー: ${error.message}` };
    } 
});

```

### 4.画面側の処理
作成した`project/server/sendMail.ts`を利用して画面で入力した情報をメールに送る。
```vue:project/pages/index.vue
<script lang="ts" setup>
import { ref } from "vue";

const form = ref({ name: "", email: "", message: "" });
const submitForm = async () => {
  const response = await fetch("/api/sendMail", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(form.value),
  });
  if (response.ok) {
    alert("送信しました。");
    form.value = { name: "", email: "", message: "" };
    return;
  }
  alert("送信に失敗しました。");
};
</script>

<template>
  <div>
    <form @submit.prevent="submitForm">
        <label for="text">お名前:</label>
        <input
           type="text"
           id="name"
           v-model="form.name"
           required
         />
         <label for="email">メールアドレス:</label>
         <input
           type="email"
           id="email"
           v-model="form.email"
           required
         />
         <label for="message">お問い合わせ内容:</label>
         <textarea
           id="message"
           v-model="form.message"
           required
         ></textarea>
        <button type="submit">送信</button>
      </form>
  </div>
</template>
```
### 5.サーバーを起動
```Bash:Bash
yarn run dev
```
サーバーを起動して入力項目を入力して送信ボタンを押下すると指定のメールアドレスへフォームに入力した情報を受け取ることができます。

## 最後に
今回はNuxt3と親和性が高いnodemailerを利用してメール送信できるような実装をしました。
PHPでも実装を試したので時間があるときにそちらもまとめてみようと思います。