SP用メニューボタン
ソレゾレブログ

技術的な事だったり日常の気になる事だったり

お問い合わせフォームをレンタルサーバーのSMTPサーバーやWP Mail SMTPを使ってWP環境で自作する①

スポンサーリンク

目次

はじめに

この記事を読むには、Wordpressによる静的ページの作成に関する知識が必要となります。

スポンサーリンク

ページの構成

作成するページの構成は下記となります。

  • トップページ(page-top.php)
  • お問い合わせ送信ページ(page-contact.php)
  • 送信確認ページ(page-confirm.php)
  • 送信及び送信完了ページ(page-complete.php)
  • 不正アクセスエラーページ(page-contacterror.php)
  • セッションタイムアウトページ(page-contacttimeout.php)

これから作成していくお問い合わせフォームを構成するページと、各ページの関係は下記の通りです。

ページの構成

ページの作成

まずは必要なページを作成していきます。Wordpressに静的ページを固定ページのテンプレートとして読み込むため、ヘッダーとフッター以外のページに「Template Name」を記載しています。

ヘッダーとフッターの作成

ヘッダーとフッターは共通部分としてテンプレートを用意して、各ページではget_header()get_footer()関数で読み込みます。

<!DOCTYPE html>
<html lang="jp">
<head>
    <meta charset="UTF-8">
    <?php wp_head(); ?>
</head>
<body>
<?php wp_footer(); ?>
</body>
</html>

トップページの作成

下記のようなページを作成していきます。

トップページの作成

トップページは、送信及び送信完了ページに設置する「トップページに戻る」ボタンをクリックした時に表示させるために作成します。

<?php
/*
Template Name: top
*/
?>

<?php get_header(); ?>

<main class="top">
    <h1>TOPページ</h1>
    <a href="<?php echo esc_url(home_url('/contact')); ?>">お問い合わせ</a>
</main>

<?php get_footer(); ?>

お問い合わせページの作成

下記のようなページを作成していきます。

お問い合わせページの作成

お問い合わせ内容を入力するページです。「送信確認」ボタンをクリックすると送信確認ページに遷移します。

コードは下記となります。

<?php
/*
Template Name: contact
*/
?>

<?php get_header(); ?>

<main class="contact">
    <h1>お問い合わせフォーム</h1>
    <form action="/confirm" method="post">
        <div>
            <label for="your-name">氏名</label>
            <input type="text" name="your-name" id="your-name" value="">
        </div>
        <div>
            <label for="your-email">メールアドレス</label>
            <input type="email" name="your-email" id="your-email" value="">
        </div>
        <div>
            <label for="your-textarea">お問い合わせ内容</label>
            <textarea name="your-text" id="your-text" rows="10"></textarea>
        </div>
        <input type="submit" value="送信確認" class="confirm-button" id="confirm-check">
    </form>
</main>

<?php get_footer(); ?>

送信確認ページの作成

下記のようなページを作成していきます。

送信確認ページの作成

送信確認ページでお問い合わせ内容に不備が無いか確認出来ます。

お問い合わせページからPOSTされてきたお問い合わせ情報をPHPで取得して、ページに埋め込んで表示します。残念ながら、現段階ではPOSTされてきた情報を取得する設定をしていないので、右側は空で表示されると思います。

お問い合わせ内容を修正したい場合は「修正する」ボタンをクリックします。お問い合わせページに戻ると共に、入力された内容がPOSTされて、input要素やtextarea要素に表示され修正することが出来ます。

お問い合わせ内容に問題が無い場合は「送信する」ボタンをクリックします。送信及び送信完了ページに遷移すると共に、入力された内容がPOSTされます。

コードは下記となります。

<?php
/*
Template Name: confirm
*/
?>

<?php get_header(); ?>

<main class="confirm">

    <h1>送信確認</h1>
    <table>
        <tr>
            <td>氏名</td>
            <td></td>
        </tr>
        <tr>
            <td>メールアドレス</td>
            <td></td>
        </tr>
        <tr> 
            <td>お問い合わせ内容</td>
            <td></td>
        </tr>
    </table>
    <div>
        <form action="/contact" method="post">
            <input type="submit" value="修正する">
        </form>
        <form action="/complete" method="post">
            <input type="submit" value="送信する">
        </form>
    </div>
</main>

<?php get_footer(); ?>

送信及び送信完了ページの作成

送信及び送信完了ページの作成1
送信及び送信完了ページの作成2

送信確認ページからPOSTされてきた情報をWordpressのwp_mail関数に渡してメールを送信します。wp_mail関数は、送信成功するとtrue、送信エラーになるとfalseを戻り値として返します。これと利用して表示する内容を制御します。wp_mail関数によるメール送信の実装は後述します。

コードは下記となります。

<?php
/*
Template Name: complete
*/
?>

<?php get_header(); ?>

<main class="complete">

    <p>お問い合わせは正常に送信されました。</p>
    <button type="button" onclick="location.href='<?php echo esc_url(home_url('/')); ?>'">トップページに戻る</button>

    <p>送信エラーが発生しました。</p>
    <p>「入力画面に戻る」ボタンでお問い合わせフォームに戻り再度送信を試してください。</p>
    <p>エラーが再度発生する場合は、インターネットへの接続をご確認ください。</p>
    <p>それでもエラーが発生する場合は、お電話によりお問い合わせいただきますようよろしくお願いいたします。</p>

    <form action="/contact" method="post">
        <input type="submit" value="入力画面に戻る">
    </form>

</main>

<?php get_footer(); ?>

現段階では、メール送信及びメール送信成功とエラーの条件分岐を書いていないので、ページは下記のように表示されます。

送信及び送信完了ページの作成3

不正アクセスエラーページ

下記のようなページを作成していきます。

不正アクセスエラーページ

このページは、送信確認ページや送信及び送信完了ページにユーザーや攻撃者が直接アクセスしてきた場合に表示されるエラーページです。正常なお問い合わせは、必ずお問い合わせページへのアクセスから始まるので、送信確認ページや送信及び送信完了ページに直接アクセスしてくるケースは、悪意のある攻撃か、ユーザーが間違ってアクセスしてくるケースです。送信確認ページと送信及び送信完了ページに直接アクセスしてきた場合は、不正アクセスエラーページにリダイレクトさせます。

コードは下記となります。

<?php 
/*
Template Name: contacterror
*/
?>

<?php get_header(); ?>

<main class="contacterror">
    <p>不正な操作が発生しました。</p>
    <p>お問い合わせ画面に戻って初めからやり直してください。</p>
    <button type="button" onclick="location.href='<?php echo esc_url(home_url('/contact')); ?>'">入力画面に戻る</button>
</main>

<?php get_footer(); ?>

セッションタイムアウトページ

下記のようなページを作成していきます。

セッションタイムアウトページ

このページは、セッションタイムアウト時に表示されます。ユーザーが一定時間お問い合わせフォームを操作しなかった場合、セキュリティの観点からセッションの切断処理をし、 セッションタイムアウトページにリダイレクトさせます。ユーザーはお問い合わせページからお問い合わせをやり直すこととなります。

コードは下記となります。

<?php 
/*
Template Name: contacttimeout
*/
?>

<?php get_header(); ?>

<main class="contacttimeout">
    <p>無操作が続いた為セキュリティ上セッションをタイムアウトしました。</p>
    <p>お問い合わせ画面に戻って初めからやり直してください。</p>
    <button type="button" onclick="location.href='<?php echo esc_url(home_url('/contact')); ?>'">入力画面に戻る</button>
</main>

<?php get_footer(); ?>

スポンサーリンク

事前作業

今回対象となるスーパーグローバル変数について簡単に触れていきます。

$_POSTスーパーグローバル変数

今まで作成してきた各ページにはform要素が設定されていますが、form要素内に設置したinput要素やtextarea要素に入力した値は、同じくform要素内に用意したsubmitボタンをクリックすることで、form要素のaction属性に指定したスクリプトファイル(ここでは遷移先ページを構成するphpファイルのこと)に渡されます。この時、渡された値が格納されるのが$_POSTスーパーグローバル変数です。

$_SESSIONスーパーグローバル変数

session_start関数を使ってセッションを作成すると、セッションが有効な間だけ$_SESSION変数が有効になります。$_SESSION変数は、他のページにも値を渡すことが出来る変数で、格納した値はサーバー側に保存されます。対してCookieはユーザーのブラウザに保存されます。

お問い合わせページのinput要素やtextarea要素に入力された値を送信確認ページに値を渡す場合は、お問い合わせフォームのsubmitボタンをクリックすることで$_POST変数を使って渡すことが出来ましたが、それ以降のページ遷移ではこの方法が使えません。そこで$_SESSION変数の出番です。送信確認ページにPOSTされた値($_POST変数に格納された値)を$_SESSION変数にコピーすることで、セッションが有効な間以降のページ遷移時に値を受け渡し続けることが出来ます。

他にもページ間で値を受け渡す方法はあります。hiddenタイプのinput要素を作成して、value属性に受け渡したい値を格納します。submitボタンをクリックすることで、次のページにPOSTして受け渡すことが出来ますが、この値はユーザー側で簡単に書き換えられる為、セキュリティ的に良くありません。セッションはあくまでもサーバー側に値が格納されているので、ユーザーに書き換えられリスクが無く安全です。ページ間で値を受け渡す方法としてはセッションを使うことをお勧めします。

$_SESSION変数にを使ってページ間で値を受け渡す実装は後述します。

$_COOKIEスーパーグローバル変数

$_COOKIEスーパーグローバル変数はユーザーのブラウザに保存されている値であるCookieを格納する変数です。ユーザーのブラウザに格納されているCookieはPHPの$_COOKIE変数に格納され、サーバーとやり取りするたびにサーバーに渡されます。$_SESSION変数はサーバー側に保存されている値をページ間で受け渡す変数でしたが、$_COOKIEはユーザー側に保存されているCookieをサーバーに渡すために使われます。

お問い合わせフォームで$_COOKIE変数がどう使われるかですが、セッションを認識するためのセッションIDの保存に使われます。

スーパーグローバル変数をページ上で確認するための設定

ページが表示されるたびに、スーパーグローバル変数がページで確認できるように設定します。

頭にsession_id関数が付け加えられていますが、これはセッションIDを確認する関数です。セッションIDが$_COOKIEに格納されるタイミングの関係で、お問い合わせページで最新のセッションIDが$_COOKIEに表示されない場合があります。$_COOKIEとsession_id関数のセッションIDが異なる場合は、現在値はsession_id関数の値だと覚えておいてください。

作成した全てのページのmain要素の後get_footer関数の上に下記コードを追記してください。

</main>

<br><br><br><br>
<hr>
<h2>session_id</h2>
<?php echo session_id(); ?>
<hr>
<h2>$_SESSION</h2>
<?php var_dump($_SESSION); ?>
<hr>
<h2>$_COOKIE</h2>
<?php var_dump($_COOKIE); ?>
<hr>
<h2>$_POST</h2>
<?php var_dump($_POST); ?>
<hr>

<?php get_footer(); ?>

設定後お問い合わせページにアクセスすると、下記のように変数が表示されると思います。下記は送信確認ページで取得した画像です。

スーパーグローバル変数をページ上で確認する設定

開発段階や検証では、このように変数の中身を確認しながら作業すると値が渡されているかわかりやすいと思いますが、スーパーグローバル変数には様々な設定情報が格納されているので、ローカル環境でのみ使用されることをお勧めします。公開サーバー上では情報漏洩のリスクがあるため設定しないことをお勧めします。

予備知識

ページ間の値の受け渡し方法

お問い合わせフォームは、お問い合わせページから送信確認ページ、送信確認ページから送信及び送信完了ページ、などのように、ページ遷移が伴います。ページの遷移時に、入力されたお問い合わせ内容がページ間で渡されなければいけません。ここでは、ページ遷移ごとにどのような方法で値を受け渡すのか説明していきます。

$_POST変数によって値を受け渡すページ遷移

下記のページ遷移における値の受け渡しは$_POST変数を使います。

form要素内のinput要素やtextarea要素の値は、同じくform要素内に設置したsubmitボタンをクリックすることで、form要素のaction属性に設定したスクリプトファイル(遷移先ページのphpファイル)に$_POST変数を使って渡されます。

  • お問い合わせページで「送信確認」submitボタンをクリックして送信確認ページに遷移する時

$_SESSION変数によって値を受け渡すページ遷移

下記のページ遷移における値の受け渡しは$_SESSION変数を使います。

  • 送信確認ページで「修正する」submitボタンをクリックしてお問い合わせページに戻る時
  • 送信確認ページで「送信する」submitボタンをクリックして送信に遷移する時
  • 送信及び送信完了ページで送信エラーとなった時に表示される「入力画面に戻る」submitボタンをクリックしてお問い合わせページに戻る時

値を受け渡す必要が無いページ遷移

下記のページ遷移時は値を受け渡す必要がありません。私の作成例では値を受け渡さない作り込みとしています。

  • 送信及び送信完了ページで送信成功となった時に表示される「トップページに戻る」submitボタンをクリックしてトップページに戻る時
  • 不正アクセスによって不正アクセスエラーページが表示された時に、表示される「入力画面に戻る」submitボタンをクリックしてお問い合わせページに戻る時
  • セッションタイムアウトによってセッションタイムアウトページが表示された時に、「入力画面に戻る」submitボタンをクリックしてお問い合わせページに戻る時

セッションの概要

セッションは、$_SESSION変数を使ってページ間で値を受け渡すために利用します。$_SESSION変数はセッションを作成すると同時に初期化されます。

セッションの作成は、PHPのsession_start関数を使います。session_start関数は、セッションが作成されていない場合はセッションの初期化、セッションが作成済みの場合はセッションの維持の役割を持ちます。

セッション作成後、セッションを維持するにはセッションIDを使います。

セッションIDは、session_start関数によってセッションが初期化された時(既にセッションが開始されている場合session_start関数はセッションの維持が役割となるためセッションIDは作成されない)や、session_regenerate_id関数によってセッションIDの再作成を促された場合に生成されます。

セッションIDは、サーバーのセッションファイルとユーザー側ブラウザのCookieに保存されます。ユーザーがブラウザでサーバーからコンテンツを取得するたびに、セッションIDが格納された$_COOKIE変数を渡します。サーバーは、受け取ったセッションIDと自身が持つセッションIDがマッチするかチェックし、マッチしたらセッションを維持します。

セッションは、有効期限が切れるかsession_destroy関数を使って削除するまで維持されます。

セッションについて更に詳しく知りたい方は下記を参照してください。

お問い合わせ機能の作成

セッションの作成

セッションを作成するsession_start関数を、お問い合わせページ、送信確認ページ、送信及び送信完了ページ、に追記します。ページの最上部(Template Nameの下)に設定を追加します。

<?php
/*
Template Name: *********
*/
?>

<?php
session_start();
?>

ページを表示すると、「session_id」と$_COOKIE変数のセッションID要素にセッションIDが表示されるようになります。これでセッションが作成/維持されるようになりました。

$_POST変数の値を$_SESSION変数にコピーする

お問い合わせページから送信確認ページにPOSTされてきたデータをさらにほかのページに受け渡せるようにするには、送信確認ページで$_POST変数に格納されている入力値を$_SESSION変数にコピーする必要があります。そのための関数をmy_get_session_execという関数名でfunction.phpに作成していきます。関数名は任意です。

function my_get_session_exec() {
    my_set_session_input('your-name');
    my_set_session_input('your-email');
    my_set_session_textarea('your-text');
}

function my_set_session_input($name) {
    $_SESSION[$name] = esc_attr($_POST[$name]);
}

function my_set_session_textarea($name) {
    $_SESSION[$name] = esc_textarea($_POST[$name]);
}

7~9行目は、お問い合わせページから送信確認ページにPOSTされてきたinput要素の値を、$_POST変数から$_SESSION変数にコピーしています。esc_attr関数を付けることで文字列をエスケープ処理しています。

11~13行目は、お問い合わせページから送信確認ページにPOSTされてきたtextarea要素の値を、$_POST変数から$_SESSION変数にコピーしています。esc_textarea関数を付けることで文字列をエスケープ処理しています。

1~5行目は、my_get_session_exec関数を定義し、上記関数を呼び出しています。引数にinput要素やtextarea要素のname属性を設定します。

文字列をPOSTする時にはXSS(クロスサイトスクリプティング)攻撃対策として文字列の無害化(サニタイズ、エスケープ)が必要です。詳しくは下記を参照してください。

次に、my_get_session_exec関数を呼び出す設定を送信確認ページに追加します。

<?php
/*
Template Name: *********
*/
?>

<?php
session_start();
my_get_session_exec(); //ここに追加
?>

セッション作成の設定が追加できたので動作確認をしていきます。

お問い合わせページにアクセスし、各値を入力して「送信確認」ボタンをクリックすると、送信確認ページの$_SESSIONに入力した値が表示されたと思います。$_POSTにも同じ要素と値が表示されているはずです。これでOKです。

$_POST変数の値を$_SESSION変数にコピーする

お問い合わせページから送信確認ページにPOSTされた値をページに表示させる

$_SESSION変数に値が格納できたので、次はページに値を表示させます。

送信確認ページの値を表示させるほうのtd要素に、$_SESSION変数に格納されている値を表示させるよう書き換えます。値を表示させるtd要素にecho $_SESSION['name属性値']を追記します。具体的には下記のように追記します。

<main class="confirm">
    :
    <table>
        <tr>
            <td>氏名</td>
            <td><?php echo $_SESSION['your-name']; ?></td> //ここに追記
        </tr>
        <tr>
            <td>メールアドレス</td>
            <td><?php echo $_SESSION['your-email']; ?></td> //ここに追記
        </tr>
        <tr> 
            <td>お問い合わせ内容</td>
            <td><?php echo $_SESSION['your-text']; ?></td> //ここに追記
        </tr>
    </table>
    :
</main>

設定が出来たので動作確認します。

お問い合わせページに値を入力して「送信確認」ボタンをクリックします。送信確認ページが表示されると、下記のように値が表示されていると思います。これでOKです。

お問い合わせページから送信確認ページにPOSTされた値をページに表示させる

送信確認ページの「修正する」をクリック後、お問い合わせページに値を表示する設定

セッションの作成と$_POSTから$_SESSION変数への値のコピーが済んでいますので、「修正する」ボタンをクリックしてお問い合わせページに遷移した時に$_SESSION変数が渡されて値が表示されると思います。「修正する」ボタンをクリック$_SESSION変数を確認してみてください。

送信確認ページの「修正する」をクリック後、お問い合わせページに値を表示させる設定1

ただ、今の段階でinput要素やtextarea要素は空になっていると思います。これでは値を再入力しなければいけないため、下記条件の時は、お問い合わせページの入力欄に$_SESSION変数に格納されている値を組み入れて表示されるように設定します。

  • 送信確認ページで「修正する」ボタンをクリックしてお問い合わせページに遷移したとき

また下記の時も、お問い合わせページの入力欄に$_SESSION変数に格納されている値を組み入れて表示されるように設定します。

  • 送信及び送信完了ページで送信エラーとなった時の「入力画面に戻る」ボタンをクリックしてお問い合わせページに遷移したとき

ページ表示初期状態で入力欄に値が表示されるようにするには、input要素のvalue属性に値を設定します。$_SESSION変数の対応する値を代入すればよさそうです。textarea要素にはvalue属性が無いため、textareaタグの属性ではなく値(開始タグと終了タグの間)に設定します。

ただし、初回アクセス時には$_SESSION変数の値を組み入れたくないため、初回アクセス時は$_SESSION変数が空であることを利用して、$_SESSION変数の対応する要素が空(empty)なら$_SESSION変数を組み入れない、$_SESSION変数に値が格納されていたら$_SESSION変数を組み入れるようIF文で条件判定して処理を分けます。

具体的には下記のようにinput要素にvalue属性を追記します。

<main class="contact">
       :
    <form action="/confirm" method="post">
        <div>
            <label for="your-name">氏名</label>
            <input type="text" name="your-name" id="your-name" value="<?php if( !empty($_SESSION['your-name']) ){ echo $_SESSION['your-name']; } ?>"> //ここに追記
        </div>
        <div>
            <label for="your-email">メールアドレス</label>
            <input type="email" name="your-email" id="your-email" value="<?php if( !empty($_SESSION['your-email']) ){ echo $_SESSION['your-email']; } ?>"> //ここに追記
        </div>
        <div>
            <label for="your-textarea">お問い合わせ内容</label>
            <textarea name="your-text" id="your-text" rows="10"><?php if( !empty($_SESSION['your-text']) ){ echo trim($_SESSION['your-text']); } ?></textarea> //ここに追記
        </div>
        <input type="submit" value="送信確認" class="confirm-button" id="confirm-check">
    </form>
</main>

設定後、送信確認ページまで移動したら「修正する」ボタンをクリックしてお問い合わせページに戻ってみてください。送信及び送信完了ページのエラー時の「入力画面に戻る」ボタンもクリックして確認してみてください。

下記のように値が入っていればOKです。

送信確認ページの「修正する」をクリック後、お問い合わせページに値を表示させる設定2

この時、入力値を変更して「送信確認」をクリックして送信確認ページに遷移してください。変更後の値が送信確認ページの対象欄、$_POST、$_SESSION、それぞれに格納されてると思います。

更に、送信確認ページで「修正する」ボタンをクリックしてお問い合わせページに遷移してください。変更後の値が表示されていれば成功です。

送信確認ページから「送信する」ボタンをクリックしてメール送信する設定

メール送信の準備

まずはメール送信機能を省いた状態で作り込みをしていきます。

WordPressではメール送信用のwp_mail関数が用意されており、これを使ってお問い合わせをメール送信します。wp_mail関数にはwp_mail( $to, $subject, $message, $headers, $attachments)のように5つのパラメーターが設定出来ます。「$to」は宛先、「$subject」はメールのタイトル、「$message」はメール本文、「$headers」はメールヘッダーに付加する情報、「$attachments」は添付ファイルになります。

ここでは、「$attachments」以外のパラメーターを設定していきます。

送信確認ページの「送信する」ボタンをクリックすると、送信及び送信完了ページの作成ページに遷移しつつ$_SESSION変数が渡されます。その$_SESSION変数に格納された値をメール送信用の変数に加工してコピーします。

尚、宛先メールアドレスはご自分が宛先ににするメールアドレスに書き換えてください。また、本文やタイトルは自由にカスタマイズしてください。

2~14行目の部分を追記します。

<main class="complete">
    <?php
	    $TO = '任意の宛先メールアドレスを設定してください';
	    $SUBJECT = '【' . $_SESSION['your-name'] . '】様からのお問い合わせ';
	    $MESSAGE = "【氏名】\n" . $_SESSION['your-name'] . "\n" .
	                "【メールアドレス】\n" . $_SESSION['your-email'] . "\n" .
	                "【お問い合わせ内容】\n" . $_SESSION['your-text'] . "\n";
	    $HEADER = "From: " . $_SESSION['your-name'] . " <" . $_SESSION['your-email'] . ">\r\n";

	    echo '<p>' . $TO . '</p>';
	    echo '<p>' . $SUBJECT . '</p>';
	    echo '<p>' . $MESSAGE . '</p>';
	    echo '<p>' . $HEADER . '</p>';
    ?>

    <p>お問い合わせは正常に送信されました。</p>
    :
</main>

設定後、お問い合わせページ → 送信確認ページ → 送信及び送信完了ページまで遷移してください。下記のように、宛先、メールのタイトル、メール本文、メールヘッダーが設定どおり表示されれがOKです。

お問い合わせ送信成功時と失敗時に出力されるメッセージとボタンも一通り表示されていますが、あとで修正するので現段階では問題ありません。

$MESSAGEに設定した改行コードはブラウザで見た時は改行されていなくて良いです。メーラーで表示した時に効果が出ます。

メール送信の準備
wp_mail関数によるお問い合わせ送信

wp_mail関数は、実行結果の戻り値として成功時はtrue、失敗時はfalseを返します。これを利用して、お問い合わせ成功時と失敗時の出力メッセージを分けます。wp_mail関数によるお問い合わせ送信と、返り値によるメッセージ出力の作り込みをしていきます。

まずは、下記の変数確認用コードを削除してください。

	    echo '<p>' . $TO . '</p>';
	    echo '<p>' . $SUBJECT . '</p>';
	    echo '<p>' . $MESSAGE . '</p>';
	    echo '<p>' . $HEADER . '</p>';

main要素の中を書き換えていきます。

<?php
/*
Template Name: complete
*/
?>

<?php get_header(); ?>

<main class="complete">
       :
    <?php if(wp_mail($TO, $SUBJECT, $MESSAGE, $HEADER)) { ?>
        <p>お問い合わせは正常に送信されました。</p>
        <button type="button" onclick="location.href='<?php echo esc_url(home_url('/')); ?>'">トップページに戻る</button>
    <?php } else { ?>
        <p>送信エラーが発生しました。</p>
        <p>「入力画面に戻る」ボタンでお問い合わせフォームに戻り再度送信を試してください。</p>
        <p>エラーが再度発生する場合は、インターネットへの接続をご確認ください。</p>
        <p>それでもエラーが発生する場合は、お電話によりお問い合わせいただきますようよろしくお願いいたします。</p>
        <form action="/contact" method="post">
            <input type="submit" value="入力画面に戻る">
        </form>
    <?php } ?>
</main>
   :

11行目に、if文を追加します。条件としてwp_mail関数を指定します。これにより、お問い合わせ送信と共に実行結果の戻り値を取得してくれます。戻り値がtrueであった場合は、成功メッセージが出力されます。

14行目に、else分を追加します。お問い合わせ送信に失敗した時のメッセージ出力となります。

22行目でif文を閉じます。

これでお問い合わせ送信の作り込みは完了です。お問い合わせページ → 送信確認ページで「送信確認」をクリックしてみてください。

レンタルサーバーなど利用されている方はメールサーバー(SMTPサーバー)が標準装備されていているので、メールサーバーでメールアカウントの発行などを終えていてメール送信の設定条件がそろっている方は、下記のように正常送信されると思います。

wp_mail関数によるお問い合わせ送信1

自前サーバーやローカル検証環境など、SMTPサーバー未実装の場合はエラーになると思います。

wp_mail関数によるお問い合わせ送信2

次は、SMTPサーバの設定をしていきます。

スポンサーリンク

WP Mail SMTPの必要性について

wp_mail関数は、PHPのメール送信ライブラリであるphpmailerを利用してメール送信します。そして、phpmailerはSMTPサーバーにメールを受け渡します。

メール送信にまつわるエージェントは、MUA(Mail User Agent)、MTA(Mail Transfer Agent)、MDA(Mail Delivery Agent)、3つが挙げられます。MUAはOutlookやwp_mail関数になると思います。MTAやMDAはSMTPサーバーの役割かと思います。そのあたりは下記を参照するとわかりやすいと思います。

今まで構築してきた環境でそろっているのはMUAです。レンタルサーバーで構築している方は、既にMTAやMDAもそろっています。

つまり、SMTPサーバー構築が必要なのは、自前サーバーやローカル検証環境で構築されている方です。

そのほかWP Mail SMTPプラグインを導入する理由がいくつかありますので、下記で確認後、導入するか判断してください。

SMTPサーバーが無い環境上にお問い合わせページを設置している方。Xserverやさくらインターネットなど(私が確認済みの範囲)のレンタルサーバーでは、SMTPサーバーが標準装備されています。メールアドレスの発行などは必要ですが、メールアドレスを発行してwp_mail関数でメール送信すれば、ユーザーがSMTPサーバーを構築しなくてSMTPサーバー経由でメール送信してくれるようになっています。ローカル検証環境や自前のサーバーでお問い合わせフォームを運用されている方で、SMTPサーバーが未実装の場合はこのプラグインを使うことでメール送信が出来るようになります。

レンタルサーバー標準装備のSMTPサーバーを使いたくない方。何らかの理由で、他のSMTPサーバー経由でメールを送信したい場合は、WP Mail SMTPを導入することで可能になります。

WP Mail SMTPで送信元アドレスを変えたい方

// $HEADER行を削除
$HEADER = "From: " . $_SESSION['your-name'] . " <" . $_SESSION['your-email'] . ">\r\n";

// wp_mail関数のパラメータから$HEADERを削除
<?php if(wp_mail($TO, $SUBJECT, $MESSAGE, $HEADER)) { ?>
   ↓
<?php if(wp_mail($TO, $SUBJECT, $MESSAGE)) { ?>

WP Mail SMTPの設定

それではWP Mail SMTPプラグインの導入と設定に入っていきます。

WP Mail SMTPの設定1

インストール後有効化してください。

下記ウィザードが表示された場合はこれは使わず、[ダッシュボード]をクリックしてください。

WP Mail SMTPの設定2

インストールすると、左メニュー直下に [WP Mail SMTP] が追加されます。[一般]タブを設定していきます。

WP Mail SMTPの設定3

[送信元メールアドレス]を設定します。[このメールを強制使用]のチェックは他に[送信元メールアドレス]を上書きするようなプラググインが入っていた場合に、他の設定を上書きするようです。基本的にはチェック不要です。様子見で設定してください。

[フォーム名]を必要に応じて設定します。[フォーム名]に名前や組織名を設定すると、送信元が「フォーム名<送信元メールアドレス>」のように相手に通知されます。設定しない場合は単に「送信元メールアドレス」と通知されます。[このメールを強制使用]のチェックは様子見で設定してください。基本的にはチェック不要です。

[返信先]は任意で設定してください。基本チェック不要です。

[メーラー]は下記のように設定してください。

  • 一覧に使用するSMTPサーバーがある場合は一覧から選択してください。
  • WP Mail SMTPの力を借りなくてもレンタルサーバーのメール送信機能でメール送信できるけど、単に送信元アドレスを変える為だけにWP Mail SMTPを使う場合は、[デフォルト(無し)]を選択してください。
  • 自前の環境からメール送信したい場合やレンタルサーバーが持っているSMTPサーバー以外を経由させたい場合は、[そのほかのSMTP]を選択して経由する外部のSMTPサーバーを手動で設定してください。
  • 一覧に使いたいSNMTPサーバーがあるけど、動作確認してみてうまく送信出来ない場合は、[そのほかのSMTP]でSMTP送信設定を手動設定して試してみてください。
WP Mail SMTPの設定4

[SMTPホスト] [暗号化] [SMTPポート] [TLS自動化] [認証(SMTPユーザー名とSMTPパスワード)] は、[そのほかのSMTP]を選択された方のみ設定が必要です。個々の環境に合わせて設定してください。

全て設定し終えたら [設定を保存] をクリックして保存します。「設定を保存しました。」が表示されたらOKです。

WP Mail SMTPの設定5

WP Mail SMTPのメール送信テスト

設定したSMTPサーバーと送信元アドレスでメールが届くかテストします。[WP Mail SMTP] – [メールテスト]タブを開きます。

WP Mail SMTPのメール送信テスト1
WP Mail SMTPのメール送信テスト2

[送信先に]テストメールを受け取る任意の宛先メールアドレスを設定してください。

[HTML]のチェックをオンにすると、HTML形式のテストメールが届きます。オフにするとテキスト形式です。どちらでもかまいません。

設定後、[メールを送信]をクリックします。

WP Mail SMTPのメール送信テスト3

私の環境では、「The test email might have sent, but its deliverability should be improved.(テストメールが送信された可能性がありますが、配信可能性を改善する必要があります。)」と表示されました。メールは送れましたがメールのなりすまし対策が甘いですよと言われています。これは、私の検証環境にDMARCの設定が入っていないからですが、メールは送れているのでひとまず無視します。気になる方は対策方法を個別に調べてください。

テストメールを受信確認してみてください。受信できれば、WP Mail SMTPを利用したお問い合わせフォームの作成は完了です。メールヘッダを確認して、送信元(FROM)がきちんと書き変わっていることも確認してください。

セッションの切断

次に、セッションの切断設定をしていきます。$_SESSION変数を使ってページ間で値を受け渡すためにセッションの作成を設定しましたが、セッションは削除処理をしない限り一定期間残ってしまい、$_SESSION変数に保存されている値も消えずに残ってしまいます。お問い合わせ完了後や途中でお問い合わせを止めてページを閉じたりしても、ページを再度開くとセッションが維持されたままとなってしまい、$_SESSION変数の値を拾って入力欄に以前入力した値が表示されてしまいます。共用PCなど使っていた場合は、悪意のあるユーザーがそのページを再度開いて情報を悪用してしまえるというわけです。これではまずいので、セッションを切断する作り込みをしていきます。

お問い合わせ完了後のセッション切断

  • session_start関数でセッションを維持する。
  • $_SESSION変数を空にします。
  • $_COOKIE変数のセッションIDを削除します。
  • セッションを削除します。

セッション切断コードは使いまわしたいので、function.phpにmy_session_destroy関数として作成します。

function my_session_destroy() {
    session_start();
    $_SESSION = array();
    if (isset($_COOKIE['セッションID'])) {
        setcookie('セッションID', '', time() - 1800, '/');
    }
    if (session_status() == PHP_SESSION_ACTIVE) { session_destroy(); }
}

1行目は、関数を作成しています。

2行目は、セッションを維持しています。

3行目は、$_SESSION変数を空にしています。

クッキーを削除するにはsetcookie関数でクッキーの有効期限を現在時刻より過去にしてあげる必要があります。

第一引数はクッキーの名前(PHPセッションIDを指定)を指定します。

第二引数はクッキーの値(空欄を指定)を指定します。

第三引数は有効期限(現在時刻より過去の時間)を指定します。time関数は現在のUnixタイムスタンプです。そこから1800秒過去を有効期限として指定することでクッキーを有効期限切れにして削除します。1800秒の指定は多くの人が指定する一般的な値です。過去になるようなら秒数は1800秒でなくても良いです。

第四引数はクッキーの有効なパス範囲を指定します。無いと削除できないのでお決まりだと思ってください。特別指定した記憶が無ければ「’/’」で試してください。

5行目は、セッションを切断しています。

次に、作成したmy_session_destroy関数を呼び出す設定をします。送信及び送信完了ページの成功メッセージと「トップページに戻る」ボタンの間に追加してください。

    :
<p>お問い合わせは正常に送信されました。</p>
<?php my_session_destroy(); ?>  //ここに追加
<button type="button" onclick="location.href='<?php echo esc_url(home_url('/')); ?>'">トップページに戻る</button>
    :

これで、お問い合わせ送信後にセッションを切断する準備ができました。実際に、お問い合わせページからお問い合わせ送信を行って、お問い合わせページに戻ってみてください。設定する前は入力欄に値が残っていましたが、設定後はセッションが削除されてinput要素やtextarea要素に値が入っていないと思います。

エラーページが表示されたらセッションを切断する

不正アクセスエラーページとセッションタイムアウトページが表示された時もセッションを切断するように、先程作成したmy_session_destroy関数を追記します。

<?php 
/*
Template Name: contacterror
*/
?>

<?php my_session_destroy(); ?>  //ここに追加
<?php get_header(); ?>
 :
<?php 
/*
Template Name: contacttimeout
*/
?>

<?php my_session_destroy(); ?>  //ここに追加
<?php get_header(); ?>
 :

この動作確認は今できないので、不正アクセスエラーやセッションタイムアウトの作り込みが終わったら確認してみてください。

スポンサーリンク

お問い合わせ途中でページを閉じた時にセッションを切断する

お問い合わせ途中でページを閉じて、セッションがタイムアウトする間に他の誰かがお問い合わせページを閲覧して入力情報が残っていたらそれは非常にまずいです。悪用されたり、個人情報の漏洩につながります。そのための対策をしていきます。

まずは、ユーザーがページにアクセスするパターンを下記のように分類します。

①submitボタンをクリックしてページ間を移動するパターン
「お問い合わせページ → 送信確認ページ → お問い合わせページ」のようなページ遷移や、「お問い合わせページ → 送信確認ページ → 送信及び送信完了ページ(送信エラー) → お問い合わせページ」のようなページ遷移の場合がこれにあたります。

②途中離脱して再度お問い合わせページにアクセスしてくるパターン
お問い合わせ途中でページを閉じてお問い合わせページに再アクセスしてきたパターンがこれにあたります。セッションが残っているので情報を悪用される危険性があります。

③途中離脱してお問い合わせページ以外に直接アクセスしてくるパターン
お問い合わせ途中でページを閉じてお問い合わせページ以外に直接再アクセスしてきたパターンがこれにあたります。セッションが残っているので情報を悪用される危険性があります。

①の場合はセッションを維持させる必要があるので、submitボタンをクリックしてページ移動してきたことを判定してセッションを維持させます。

②の場合は不正アクセスとして不正アクセスページにリダイレクトさせたいので、①の対策で条件にマッチしなかったものを初回アクセスとみなして、セッションの初期化などの処理を行います。

次に、①②のパターンそれぞれに設定を加えていきます。まずは①②を区別しなくてはいけません。どうやって区別するかと言うと、①のページアクセスパターンであると判断するために、submitボタンにname属性を設定します。name属性が付与されたsubmitボタンをクリックしてページ遷移してくると、name属性の値が次のページにPOSTされてきます。次のページで$_POSTの中にname属性に設定した値があれば、①のアクセスと判断できますし、無ければ②のアクセスであると判断できます。

それではまず、submitボタンにname属性を追加していきます。お問い合わせページに戻るsubmitボタンに対してname属性を追加します。

<main class="confirm">
            :
        <form action="/contact" method="post">
            <input type="submit" value="修正する" name="submit-return"> //name属性を追加
        </form>
            :
    </div>
</main>
<main class="complete">
            :
        <form action="/contact" method="post">
            <input type="submit" value="入力画面に戻る" name="submit-return"> //name属性を追加
        </form>
    <?php } ?>
</main>

次は、セッションの維持(①のアクセス)か初回アクセス(②のアクセス)かの判定をしてそれらに合わせた処理をするコードを書いていきます。

お問い合わせページにsubmitボタンで移動してくるときは、name属性に「submit-return」が格納されてくるよう設定しましたので、if文の条件にisset($_POST['submit-return'])を設定して、マッチした場合はセッションの維持(①のアクセス)と判断して対応する処理を実行します。

追加するコードは下記となります。

<?php
/*
Template Name: contact
*/
?>

<?php
if (isset($_POST['submit-return'])) {
    session_start();
} else {
    my_session_destroy();
    session_start();
    session_regenerate_id();
}
?>

<?php get_header(); ?>

これで設定が終わりました。下記3点を確認してみてください。

  • submitボタンでページを移動するときは入力した値が$_SESSION変数もしくはinput要素やtextareaに残っているることを確認
  • どの段階でも一度ページを閉じてからお問い合わせページにアクセスすると$_SESSION変数は削除されている
  • お問い合わせ送信成功後や途中でページを閉じてお問い合わせページに再アクセスするとセッションIDが再生成されている

これらに問題が無ければ成功です。

無操作によるセッションのタイムアウト

PHPのセッションは、初期値では1440秒(24分)でタイムアウト(有効期限切れ)するようになっています。ですが、確実にタイムアウトするわけではなく初期値では100分の1の確率でタイムアウトするようになっています。これらの設定はphp.iniに設定されており、タイムアウト値は「session.gc_maxlifetime = 1440」、確率は「session.gc_probability = 1」(分子)と「session.gc_divisor = 100」(分母)に設定されています。

php.iniの初期値については下記を参照してください。

タイムアウト処理はPHPのガベージコレクション(GC)によって行われ、ガベージコレクションはセッションの開始時(session_start)に動作しますが、GCの動作には負荷がかかるため、ページの読み込みが遅くなるという欠点があるため、毎回削除するのではなく確率によって動作するようになっています。

「session.gc_probability」と「session.gc_divisor」 を両方1にすれば期限切れセッションを毎回削除してくれるようになりますが、負荷が高くなるため現実的ではありません。

そこで、セッションに自作のタイムスタンプ(有効期限)を設定する方法を使います。コードは使いまわしたいのでえ、下記のようにfunctoin.phpに関数で作成します。

function my_session_start() {
    session_start();
    if (isset($_SESSION['timestamp']) && (time() - $_SESSION['timestamp'] > 10)) {
        header('location: ' . esc_url(home_url('/contacttimeout')));
    }
    $_SESSION['timestamp'] = time();
}

1行目は、セッションタイムアウト判定用の関数を作成しています。

2行目は、セッションの開始もしくは維持をしています。

3行目は、$_SESSION変数にtimestamp要素が存在するか、且つ、セッション作成時にタイムスタンプと現在のタイムスタンプを比較して、指定の時間が経過しているかif文で判定しています。ここでは試験的に10秒にしていますが、実際運用するときは適宜1時間とか30分とか環境に合わせて設定してください。

4行目は、タイムアウト判定され、セッションタイムアウトページにリダイレクトする設定です。セッションタイムアウトページにはmy_session_destroy関数が書いてあるので、セッションが切断されます。

6行目は、タイムアウトしていないと判定されてタイムスタンプ値が現在時刻に更新されます。

これでセッションタイムアウト用の関数が作成出来ました。この関数を各ページに設定していきます。

お問い合わせページのsession_start関数をmy_session_start関数に書き換えます。

<?php
/*
Template Name: contact
*/
?>

<?php
if (isset($_POST['submit-return'])) {
    my_session_start(); // session_start関数をmy_session_start関数に書き換え
} else {
    my_session_destroy();
    my_session_start(); // session_start関数をmy_session_start関数に書き換え
    session_regenerate_id();
}
?>

送信確認ページのsession_start関数をmy_session_start関数に書き換えます。

<?php
/*
Template Name: confirm
*/
?>

<?php
my_session_start(); // session_start関数をmy_session_start関数に書き換え
my_get_session_exec();
?>

送信及び送信完了ページのsession_start関数をmy_session_start関数に書き換えます。

<?php
/*
Template Name: complete
*/
?>

<?php
my_session_start(); // session_start関数をmy_session_start関数に書き換え
?>

これで完成です。お問い合わせページにアクセスしてみてください。$_SESSION変数の「timestamp」要素が追加されていると思います。

無操作によるセッションのタイムアウト1

送信確認ぺージまで移動して、設定したタイムアウト時間まで待ってみてください。その後、「修正する」か「送信する」をクリックしてください。セッションタイムアウトページにリダイレクトされ、セッションが切断され$_SESSION変数が空になったはずです。これで完成です。

無操作によるセッションのタイムアウト2

続編に続く

記事が長くなってきましたのでに記事を分割します。