[php]PHP Mailerを使って問い合わせフォームを作成する

使ってたバージョンがいい加減古くなってきたので新しいのを導入する。
おさらいと、現行バージョンのハウツーを兼ねて。

なんでPHP Mailerを使うのか

mb_send_mail()を使えばメール送信自体はできるんだけど、ここ数年で迷惑メール扱いされる率が跳ね上がった。
都度迷惑メールフォルダ見てくれとか言ったりするのは手間でしか無い、受信ボックスに入れる前の段階で弾かれてるのかもで送られてないんじゃないのみたいに揉めたり、誰も幸せにならない、用事にならない。
多分これはメール送信元がまともなアカウントかどうかをメーラー(メールサービス)が判定して、結果蹴られたって話なんだろう。
発信元のメールアドレスは指定できるけどメールサーバー通してないし、だとすると偽装だもんね。
しょうがないね。

で、PHP Mailerはメールアカウントにログインして送信処理してるから安心。
設定さえちゃんと出来てればエラーも吐かないし迷惑メールにならない。
詳細については他所のサイトで説明されてるだろうからそちらに求めてください。
概要としてはそんな感じ。

参考

使い方

  1. PHPが使えるWEBサーバーを用意する
  2. PHPMailerのファイルをアップロードする
  3. PHPMailerを噛ませた内容のメールフォームをアップロードする

PHPMailer自体はいじらない。
記述ミスは自分で用意したデータでしか発生しないから安心感がある。

ダウンロード

GitHubで公開されてるからダウンロード。
GitHub – PHPMailer/PHPMailer: The classic email sending library for PHP
今見たら安定版が6.0.7だったんでこれでやっていく。

ディレクトリ構成

  1. 「PHPMailer」フォルダを作る。
  2. 「PHPMailer」に「src」フォルダごと全部突っ込む。
  3. 「PHPMailer」に「language」フォルダを作って「phpmailer.lang-ja.php」だけ入れる。

送信部分

上項目の「PHPMailer」と同じディレクトリで送信作業をするとして。
要するにこう。

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

require 'PHPMailer/src/Exception.php';
require 'PHPMailer/src/PHPMailer.php';
require 'PHPMailer/src/SMTP.php';
require 'PHPMailer/language/phpmailer.lang-ja.php';

$mail = new PHPMailer(true); // Passing `true` enables exceptions
try {
//Server settings
$mail->SMTPDebug = 2; // Enable verbose debug output
$mail->isSMTP(); // Set mailer to use SMTP
$mail->Host = 'smtp.lolipop.jp'; // Specify main and backup SMTP servers
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = '****@megefeps.info'; // SMTP username
$mail->Password = '****'; // SMTP password
$mail->SMTPSecure = 'ssl'; // Enable TLS encryption, `ssl` also accepted
$mail->Port = 465; // TCP port to connect to (ssl:465)

//Recipients
$mail->setFrom('****@megefeps.info', 'MEGEFEPS'); // 送信者のメールアドレスと名前
$mail->addAddress('****@gmail.com', '****'); // 送信先のメールアドレスと名前
// $mail->addAddress('****@gmail.com'); // 送信先追加
// $mail->addReplyTo('****@gmail.com', '****'); // 返信先
// $mail->addCC('****@gmail.com'); // CC
// $mail->addBCC('****@gmail.com'); // BCc

//Attachments 添付ファイル
// $mail->addAttachment('/var/tmp/file.tar.gz'); // Add attachments
// $mail->addAttachment('/tmp/image.jpg', 'new.jpg'); // Optional name

//Content 送信内容
// $mail->isHTML(true); // Set email format to HTML HTML形式で送るかどうか
$mail->Subject = ''; // 件名
$mail->Body = ''; // 本文
// $mail->AltBody = ''; // HTML形式で送る場合の非HTML本文

$mail->send();
}

ロリポップサーバーを使ってるのでメモがてらに一部それを入れてる。
記入内容は変数で指定できるので都合のいいように成形。
要らない項目はコメントアウトなり削除なりしてしまう。
ちゃんとした使い方は「README.md」に書いてある。

入力画面→確認画面→送信完了までの流れ

どんな感じで作るのが良いのかなーって考えると、

  • ブラウザの「戻る」禁止
  • 前ページに戻るのはフォーム内で処理
  • 戻った場合入力情報を残す
  • 入力フローに沿わないアクセスは弾く

でやっていくのがいいよなってなる。
ブラウザ機能で戻れちゃうと送信処理のおかわりができちゃうのでよろしくない。
直接送信処理してるページにアクセスできちゃうとよろしくない。
気にしてる人としてない人がいるっぽいのでちょっと危ないんじゃないのって気持ちがある。

入力画面

<?php
    $text = htmlspecialchars($_POST['text']);
    $password = htmlspecialchars($_POST['password']);
    $tel = htmlspecialchars($_POST['tel']);
    $date = htmlspecialchars($_POST['date']);
    $email = htmlspecialchars($_POST['email']);
    $radio = $_POST['radio'];
    $checkbox = $_POST['checkbox'];
    $select = $_POST['select'];
    $textarea = htmlspecialchars( $_POST['textarea'] );
    $required = $_POST['required'];

    // radio選択チェック
    if($radio == 'radio01'){
        $radio01 = 'checked';
    }elseif($radio == 'radio02'){
        $radio02 = 'checked';
    }elseif($radio == 'radio03'){
        $radio03 = 'checked';
    }

    // checkbox選択チェック
    if(in_array('checkbox01',$checkbox)){ $checkbox01 = 'checked';}
    if(in_array('checkbox02',$checkbox)){ $checkbox02 = 'checked';}
    if(in_array('checkbox03',$checkbox)){ $checkbox03 = 'checked';}
    if(in_array('checkbox04',$checkbox)){ $checkbox04 = 'checked';}

    // select選択チェック
    if($select == 'select01'){
        $select01 = 'selected';
    }elseif($select == 'select02'){
        $select02 = 'selected';
    }elseif($select == 'select03'){
        $select03 = 'selected';
    }elseif($select == 'select04'){
        $select04 = 'selected';
    }else{
        $select00 = 'selected';
    }

    // input:requiredチェック
    if(in_array('required',$required)){ $requiredCheck = 'checked';}
?>

<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha256-pasqAKBDmFT4eHoN2ndd6lN370kFiGUFyTiUHWhU7k8=" crossorigin="anonymous"></script>
<script>
    history.pushState(null, null, null);
    $(window).on("popstate", function (event) {
        if (!event.originalEvent.state) {
            history.pushState(null, null, null);
            return;
        }
    });
</script>

<form action="check.php" method="post">
<ul>
 	<li><input type="text" name="text" placeholder="text" value="<?php echo $text; ?>" /></li>
 	<li><input type="password" name="password" placeholder="password" value="<?php echo $password; ?>" /></li>
 	<li><input type="tel" name="tel" placeholder="tel" value="<?php echo $tel; ?>" /></li>
 	<li><input type="date" name="date" placeholder="date" value="<?php echo $date; ?>" /></li>
 	<li><input type="email" name="email" placeholder="email" value="<?php echo $email; ?>" /></li>
 	<li>
            <label><input type="radio" name="radio" value="radio01" php="" echo="" radio01="" />radio01</label>
            <label><input type="radio" name="radio" value="radio02" php="" echo="" radio02="" />radio02</label>
            <label><input type="radio" name="radio" value="radio03" php="" echo="" radio03="" />radio03</label>
        </li>
 	<li>
            <label><input type="checkbox" name="checkbox[]" value="checkbox01" php="" echo="" checkbox01="" />checkbox01</label>
            <label><input type="checkbox" name="checkbox[]" value="checkbox02" php="" echo="" checkbox02="" />checkbox02</label>
            <label><input type="checkbox" name="checkbox[]" value="checkbox03" php="" echo="" checkbox03="" />checkbox03</label>
            <label><input type="checkbox" name="checkbox[]" value="checkbox04" php="" echo="" checkbox04="" />checkbox04</label>
        </li>
 	<li>
            <select name="select">
                <option value="" php="" echo="" select00="">select</option>
                <option value="select01" php="" echo="" select01="">select01</option>
                <option value="select02" php="" echo="" select02="">select02</option>
                <option value="select03" php="" echo="" select03="">select03</option>
                <option value="select04" php="" echo="" select04="">select04</option>
            </select>
        </li>
        <li><textarea name="textarea"><?php echo $textarea; ?></textarea></li>
        <li><label><input type="checkbox" name="required[]" value="required" required="" php="" echo="" requiredcheck="" />必須</label></li>
        <li><button type="submit">確認画面へ</button></li>
    </ul>
</form>

check.phpから戻ってきた場合もvalueを受け取って表示させたいからこんな感じ。
変数にするにあたって自由入力項目についてはタグ入力とかされた場合に作動しちゃうのを回避するために「htmlspecialchars()」を噛ませる。

jsでブラウザの戻るを禁止。
他ページから来た場合違和感になるので、target=”_blank”でリンクさせるのがいいかも。
いや、むしろ無くてもいいか?

radio、checkbox、selectはvalueを手打ちでいちいち指定して照合するしかないよなって気持ち。
jsでvalue読み取って照合するなら別案件もコピペでいけますよみたいな汎用性持たせたスマートな書き方もできるけど、phpでもできんこたないみたいだけど、ここはベタ打ちでやるのが正義かなってちょっと思った。

確認画面

<?php
$text = htmlspecialchars($_POST['text']);
$password = htmlspecialchars($_POST['password']);
$tel = htmlspecialchars($_POST['tel']);
$date = htmlspecialchars($_POST['date']);
$email = htmlspecialchars($_POST['email']);
$radio = $_POST['radio'];
$checkbox = $_POST['checkbox'];
$select = $_POST['select'];
$textarea = htmlspecialchars( $_POST['textarea'] );
$required = $_POST['required'];

// input:requiredチェック
if(!in_array('required',$required)){ header('Location: index.php');}
if(isset($required) && is_array($required)){
	$requiredShow = implode("<br>",$required);
$requiredVal = implode('<input type="hidden" name="required[]" value="',$required,'">');
}

//checkbox
if(isset($checkbox) && is_array($checkbox)){
	$checkboxShow = implode("<br>",$checkbox);
$checkboxVal = implode('<input type="hidden" name="checkbox[]" value="',$checkbox,'">');
}
?>


<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha256-pasqAKBDmFT4eHoN2ndd6lN370kFiGUFyTiUHWhU7k8=" crossorigin="anonymous"></script>
<script>
history.pushState(null, null, null);
$(window).on("popstate", function (event) {
    if (!event.originalEvent.state) {
        history.pushState(null, null, null);
        return;
    }
});
$(function(){
	$('button[type="submit"]').on('click',function(){
		$(this).parents('form').attr('action',$(this).data('action'));
		$(this).parents('form').submit();
	});
});
</script>
<ul>
 	<li><?php echo $text; ?></li>
 	<li><?php echo $password; ?></li>
 	<li><?php echo $tel; ?></li>
 	<li><?php echo $date; ?></li>
 	<li><?php echo $email; ?></li>
 	<li><?php echo $radio; ?></li>
 	<li><?php echo $checkboxShow; ?></li>
 	<li><?php echo $select; ?></li>
 	<li><?php echo nl2br($textarea); ?></li>
 	<li><?php echo $requiredShow; ?></li>
</ul>
    <form action="finish.php" method="post"><input type="hidden" name="text" value="<?php echo $text; ?>" />
    <input type="hidden" name="password" value="<?php echo $password; ?>" />
    <input type="hidden" name="tel" value="<?php echo $tel; ?>" />
    <input type="hidden" name="date" value="<?php echo $date; ?>" />
    <input type="hidden" name="email" value="<?php echo $email; ?>" />
    <input type="hidden" name="radio" value="<?php echo $radio; ?>" />
    <input type="hidden" name="select" value="<?php echo $select; ?>" />
    <input type="hidden" name="textarea" value="<?php echo $textarea; ?>" />
    <input type="hidden" name="checkbox[]" value="<?php echo $checkboxVal; ?>" />
    <input type="hidden" name="required[]" value="<?php echo $requiredVal; ?>" />
    <button type="submit" id="submit" data-action="finish.php">決定</button>
    <button type="submit" id="back" data-action="index.php">戻る</button>
</form>

[name=”reqired”]のチェックの有無でindex.phpからアクセスされてるかどうかを判別する。
チェックがなければindex.phpに飛ばす。
jsで操作してるからモヤモヤするんだけど、「決定」と「戻る」でそれぞれ遷移先を変更してる。

送信完了画面

確認画面と同じくphpでrequiredのチェックを確認して、無ければindex.phpに飛ばす。
入力画面、確認画面と同じくjsでブラウザの戻るを禁止する。
入力画面、確認画面よろしくpostを受け取ってメール本文の体裁を整える。
PHPMailerで送信する。

select、radio、checkboxの応用

phpを前提に考えた時、選択肢を配列で用意してそこからforeachで書き出すのが楽だったりする。
上の項目みたいにブラウザバックを使わずに確認画面から戻った場合、postを受け取ってるからそれにも対応させるとこんな感じ。

select

<select name="select">
<option value="">選択してください</option>
<?php
    //postを変数化
    $select = $_POST['select'];
    //項目を配列で用意
    $selectArray = array('select01','select02','select03','select04','select05','select06','select07','select08');
    //配列をoptionとして書き出し
    foreach($timeAry as $value){
    //選択済みのpostがあったらselectedにする
    if($select == $value){
        echo '<option value="'.$value.'" selected >'.$value.'</option>'; 
    }else{
        echo '<option value="'.$value.'">'.$value.'</option>'; } 
    }
?>
</select>

表示とvalueを別々にしたいってんなら多次元配列を使うことになるのでちょっとめんどくなる。

checkbox

<?php
    $checkAry = array('あああ','いいい','ううう','えええ','おおお');
    $check = $_POST['check'];
?>
<?php
    foreach($checkAry as $value){
        if(in_array($value, $check)){
            echo '<label><input type="checkbox" name="check[]" value="'.$value.'" checked="checked" />'.$value.'</label>';
        }else{
            echo '<label><input type="checkbox" name="check[]" value="'.$value.'" />'.$value.'</label>';
        }
    }
?>

項目を配列で用意して書き出す。
in_arrayでチェックしたvalueとぶつけてその有無で振り分け。

コメント

タイトルとURLをコピーしました