Webセキュリティを考慮してフォーム作成
  • 正常系をまず作成
  • 異常系を考える、テストする、キリがない
  • マストな異常系をルール化する(経験がものをいう)
  • 失敗する前提で記述
  • 失敗のログがでるように
  • 時間をおいてお試してください
  • SQLインジェクション、CSRF
    →参考:体系的に学ぶ 安全なWebアプリケーションの作り方 第2版[固定版] 脆弱性が生まれる原理と対策の実践

POSTリクエストはContent-Typeはapplication/json

POSTリクエストを使うとき、サーバーにデータを送信する形式を示すために「Content-Type」というヘッダーを設定する

application/json

  • JSON形式でデータを送信するときに使います。
  • 例えば、フォームデータをJavaScriptでオブジェクトにして送信したい場合に利用します。

正常系を完成させる

フロントエンドからのフォームデータ送信

script.jssendMail 関数で、axiosを使ってフォームデータをsendMailer.phpに送信しています​(script)。まず、データが正しくサーバーに送信されているかを確認します。

PHP側でのデータ受信とレスポンス

sendMailer.php で、送信されたデータを受け取り、PHPMailerを用いてメールを送信する処理を追加します。現状のコードでは、PHPMailerの処理が未実装ですので、これを追加します。

フロントエンドでの成功メッセージの表示

メール送信が正常に完了した場合、フロントエンドで成功メッセージを表示させます。すでに sendMail 関数内でレスポンスに基づく処理が行われているため、サーバーから成功レスポンスが返ってきた際に次のページにリダイレクトするか、成功メッセージを表示するように設定します。

memo

デフォルトでは Content-Type が application/json になりますが、PHP で $_POST を使用してデータを取得するには application/x-www-form-urlencoded 形式で送信する必要がある

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>フォーム送信</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="form_wrap">
        <form class="form" onSubmit="handleSubmit(event)" name="cta_form">
            <p class="form_title">form</p>
            <div class="form_area">
                <!-- メールアドレス入力欄 -->
                <input class="form_input" type="email" name="email" placeholder="メールアドレス" required>
                <div class="err" id="emailError"></div>
                
                <!-- 電話番号入力欄 -->
                <input class="form_input" type="tel" maxlength="11" name="tel" placeholder="例) 09012345678" required>
                <div class="err" id="telError"></div>

                <!-- 送信ボタン -->
                <button class="submit" type="submit">送信</button>
            </div>
        </form>
    </div>
    <div id="formMessage" class="form_message"></div>

    <!-- JavaScriptの読み込みをbodyの最後に移動 -->
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
    <script src="script.js"></script>
</body>
</html>
$(document).ready(function () {
    async function sendMail(formData) {
        try {
            const url = "https://siennahare23.sakura.ne.jp/1104_tokuform/sendMailer.php";
            console.log("送信データ:", formData);

            const res = await axios.post(url, JSON.stringify(formData), {
                headers: {
                    "Content-Type": "application/json",
                },
            });

            const json = res.data;
            console.log("サーバーからのレスポンス:", json);

            return { success: json.status === "success", data: json };
        } catch (error) {
            console.error("PHPへの送信エラー:", error);
            return { success: false, error: error };
        }
    }

    window.handleSubmit = async function (event) {
        event.preventDefault();
        const form = event.currentTarget;

        // 入力要素の取得
        const emailInput = form.querySelector('input[name="email"]');
        const telInput = form.querySelector('input[name="tel"]');
        const emailValue = emailInput.value;
        const telValue = telInput.value;

        // 電話番号とメールアドレスのバリデーション
        if (telValue.length !== 11 || !/^\d{11}$/.test(telValue)) {
            document.getElementById("telError").innerText = "11桁の電話番号を入力してください";
            return;
        } else {
            document.getElementById("telError").innerText = "";
        }

        if (!/^[\w\.-]+@[\w\.-]+\.\w+$/.test(emailValue)) {
            document.getElementById("emailError").innerText = "有効なメールアドレスを入力してください";
            return;
        } else {
            document.getElementById("emailError").innerText = "";
        }

        // フォームデータの収集
        const data = new FormData(form);
        const formData = Object.fromEntries(data.entries());

        const result = await sendMail(formData);

        // メッセージ表示要素を取得
        const messageDiv = document.getElementById("formMessage");

        // 成功・失敗のメッセージを表示
        if (result.success) {
            messageDiv.innerText = result.data.message || "メールが正常に送信されました";
            messageDiv.style.color = "green";
        } else {
            messageDiv.innerText = result.data.message || "送信エラーが発生しました。再度お試しください。";
            messageDiv.style.color = "red";
        }
    };
});
<?php
// 設定ファイルの読み込み
require_once '/home/siennahare23/config/config.php';

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

require 'vendor/autoload.php';

if ($_SERVER["REQUEST_METHOD"] == "POST") {
    // JSON データの取得と解析
    $input = file_get_contents('php://input');
    $data = json_decode($input, true);

    // 入力データの取得
    $email = filter_var($data['email'], FILTER_SANITIZE_EMAIL);
    $tel = filter_var($data['tel'], FILTER_SANITIZE_STRING);

    // デバッグ情報の出力
    // echo '取得したメールアドレス: ' . htmlspecialchars($email) . '<br>';
    // echo '取得した電話番号: ' . htmlspecialchars($tel) . '<br>';

    // メールアドレスの検証
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        echo '無効なメールアドレスです: ' . htmlspecialchars($email);
        exit;
    }

    // 電話番号の検証
    if (!preg_match('/^\d{11}$/', $tel)) {
        echo '無効な電話番号です: ' . htmlspecialchars($tel);
        exit;
    }

    // デバッグ情報の出力
    // echo '送信先メールアドレス: ' . htmlspecialchars($email) . '<br>';
    // echo '送信先電話番号: ' . htmlspecialchars($tel) . '<br>';

    $mail = new PHPMailer(true);

    try {
        // SMTP設定
        $mail->isSMTP();
        $mail->Host       = SMTP_HOST;
        $mail->SMTPAuth   = true;
        $mail->Username   = SMTP_USER;
        $mail->Password   = SMTP_PASS;
        $mail->SMTPSecure = SMTP_SECURE;
        $mail->Port       = SMTP_PORT;

        // エンコーディングの設定
        $mail->CharSet = 'UTF-8';
        $mail->Encoding = 'base64';

        // 送信者と受信者の設定
        $mail->setFrom(SMTP_USER, 'Mailer'); // 送信者
        $mail->addAddress($email); // 受信者

        // メール内容の設定
        $mail->isHTML(true);
        $mail->Subject = 'フォーム送信内容';
        $mail->Body    = 'メールアドレス: ' . htmlspecialchars($email) . '<br>電話番号: ' . htmlspecialchars($tel);
        $mail->AltBody = 'メールアドレス: ' . htmlspecialchars($email) . "\n電話番号: " . htmlspecialchars($tel);

        // メール送信
        $mail->send();
        echo json_encode(['status' => 'success', 'message' => 'メッセージが送信されました']);

    } catch (Exception $e) {
        echo json_encode(['status' => 'error', 'message' => "メッセージを送信できませんでした。エラー: {$mail->ErrorInfo}"]);
    }
} else {
    echo json_encode(['status' => 'error', 'message' => 'POSTメソッドで送信してください。']);
}
?>