Astro×Express×Render.comで作成するお問い合わせフォーム

Astro×Express×Render.comで作成するお問い合わせフォーム

この記事でわかること

  • Astroで作成したお問い合わせフォームでメールの送信ができるようになる。

実装ゴール

  • Astroでお問い合わせフォームから、Render.comにアップロードしたExpressに向けてformの入力データを送信し、メールの送信が実行されること。

おおまかな実装の流れ

  1. Expressでメールを送信用のAPIを作る
  2. AstroでExpressに入力データの送信ができるお問い合わせフォームを作る
  3. ExpressをRender.comにアップロードする

準備するもの

  • 環境構築が完了したAstro※1
  • 環境構築が完了したExpress※2
  • メール送信に利用するGmailのメールアドレスとアプリパスワード※3
  • Node.js v16.13.0の環境

※1環境構築参考

https://docs.astro.build/ja/install/auto/

※2環境構築参考

https://expressjs.com/ja/starter/installing.html

※3アプリパスワード作成方法参考

https://pc-karuma.net/google-account-generate-app-password/

手順

1、Expressに以下のpackageをinstallする

npm i nodemailer // メール送信用ライブラリ

npm i cors //corsのエラーを回避するため

npm i dotenv //環境変数を利用できるようにするため

2、.envファイルを作る

MAILER_PORT = 465
MAILER_HOST = smtp.gmail.com
MAILER_USER = *********@gmail.com //Gmailのメールアドレス
MAILER_PASS = **************** //アプリパスワードを入力

3、Express.jsでメール送信用のAPIを作る

app.js(メール送信API)

const express = require("express");
const nodemailer = require("nodemailer");
const cors = require("cors");
require("dotenv").config();
const app = express();
app.use(cors());
const port = 3002;

// 送信用アカウントの設定(ここでGmailのメールアドレスとアプリパスワードを利用します。)
const transporter = nodemailer.createTransport({
  port: process.env.MAILER_PORT,
  host: process.env.MAILER_HOST,
  auth: {
    user: process.env.MAILER_USER,
    pass: process.env.MAILER_PASS,
  },
  secure: true,
});

//メールの文面
async function sendmail(req, res) {
  await new Promise((resolve, reject) => {
    const name = req.body.name;
    const furigana = req.body.furigana
    
    const textContent = "お問い合わせ、ありがとうございました。\n"+
                        "======================\n"+
                        "【名前】"+name+"\n"+
                        "【ふりがな】"+furigana+"\n"+
                        "======================\n"

    const toAdminMail = {
      from: process.env.USER,
      to:   process.env.MAILER_USER,
      subject: `【お問い合わせ】${name}様より`,
      text: textContent};

    transporter.sendMail(toAdminMail, function (err, info) {
      if (err) {
        console.log(err);
        reject(err);
      } else {
        console.log(info);
        resolve(info);
      }
    });
  });
}

//POSTのパラメータを取得できるようにする
const bodyParser = require("body-parser");
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.listen(port);

app.post("/contact", (req, res) => {
  sendmail(req, res);
  res.status(201).send("ok");
});

4、Astroでformを作成する

src/pages/index.astro

---
import Layout from "../layouts/Layout.astro";
---

<Layout title="formtest">
  <form>
    <div>
      <label for="js-name">名前</label>
      <input type="text" name="name" id="js-name" />
    </div>
    <div>
      <label for="js-furigana">ふりがな</label>
      <input type="text" name="furigana" id="js-furigana" />
    </div>
    <button type="button" id="js-submitbtn">送信する</button>
  </form>

  <script is:inline>
    const submitBtn = document.getElementById("js-submitbtn");
    const input_name = document.getElementById("js-name");
    const input_furigana = document.getElementById("js-furigana");
    submitBtn.addEventListener("click", (event) => {
      const formData = {
        name: input_name.value,
        furigana: input_furigana.value,
      };
      fetch(new Request("http://localhost:3002/contact"), {
        method: "POST",
        body: JSON.stringify(formData),
        mode: "cors",
        headers: { "Content-Type": "application/json" },
      })
        .then((response) => {
          console.log(response);
          window.alert("送信できました。");
        })
        .catch((error) => {
          console.error(error);
        });
    });
  </script>
</Layout>

5、ローカル環境で実施してみる。

以下のように、メールが届けば成功です。

6、ExpressをRender.comにデプロイする。

1、会員登録する

2、「Web service」を選択

3、GitHub又はGitLabを紐づける

4、ビルドの設定をする。

以下の設定を確認して「Create Web Service」を押す

  • Brunch
    • デプロイしたいブランチを設定
  • Build Command
    • npm ci
  • Start Command
    • node app.js
  • Add Sercret File
    • envファイルを追加※4

※4参考

5、デプロイ完了

7、AstroのformのPOST先のURLをRender.comに変更

//略
      //以下にデプロイ先のURLを入れる
      fetch(new Request("****************/contact"), {
        method: "POST",
        body: JSON.stringify(formData),
        mode: "cors",
        headers: { "Content-Type": "application/json" },
      })
        .then((response) => {
          console.log(response);
          window.alert("送信できました。");
        })
        .catch((error) => {
          console.error(error);
        });
    });
//略

8、再度AstroからPOSTしてメールが送信されていれば成功です。

あとがき

ここまで読んでくださりありがとうございました。今回はミニマムな実装ということでastroファイルでformを作成しましたがその場合、バリデーションの実装がPure JSになり長文になってしまいます。そのため、仕様的に問題が無ければpreactのコンポーネントを作成しreact-hooks-formといったライブラリを使うことをお勧めします。