WordPress で自作メールフォーム【高速】プラグインを使わず画面遷移しない非同期処理で実装
WordPress に「お問い合わせ」のメールフォームを設置する最も簡単な方法はプラグインの導入です。代表的なものとして、次の2つがよく利用されています。
これらのプラグインは、汎用的に使えるよう設計されています。テキストボックスやラジオボタン、プルダウンのような入力項目が設置できます。ブログ用に簡易的に設置するには、余計な機能が多すぎます。
しかもこれらプラグインを導入すると、余計な JavaScript やスタイルシートの読み込みが発生します。ページの描画速度を速くするには、プラグインを使わないのが理想的です。
そこでプラグインを利用せず、簡易的なメールフォームを自作で設置する方法について、サンプルプログラムを用いて紹介していきます。
作成するオリジナルのメールフォーム【仕様】
- 入力項目は名前・メールアドレス・ウェブサイト(URL)・内容のみ
- URL 以外は入力必須チェックを実施
- 簡易入力チェックは html 上で実施
- 外部からのアクセスを排除するため、リファラチェックを行う
- セキュリティの面から HTML 形式ではなくテキスト形式で送信
- 日時や IP アドレス等の送信者情報も送信
- 画面遷移せず非同期でメール送信処理を実施
ごくありふれたメールフォームですが、最大の特徴は 画面遷移をしない こと。つまり画面上から「送信」ボタンを押しても、画面遷移せずに処理結果を表示する仕組みにします。この非同期処理により、複数の画面を用意することなくシンプルな構成で実装できるのです。
実装に必要な画面・ファイル
- メールフォームを設置する固定ページ
- メール送信用 PHP ファイル
用意するのはこれだけです。では、ソースコードをご覧ください。
メールフォーム実装【ソースコード】
固定ページ(HTML・CSS・JavaScript)
固定ページの入力画面に直接貼り付けられるように記しています。p タグや br タグが自動挿入されないように考慮しているため、見づらい部分もありますがご了承ください。
<!-- HTML --> <form id="mailform"> <div> <label for="nameval">名前<span>(必須)</span></label> <input type="text" name="nameval" id="nameval" required /> </div> <div> <label for="mailval">メールアドレス<span>(必須)</span></label> <input type="email" name="mailval" id="mailval" required /> </div> <div> <label for="urlval">ウェブサイト</label> <input type="text" name="urlval" id="urlval" /> </div> <div> <label for="textval">内容<span>(必須)</span></label> <textarea name="textval" id="textval" rows="12" required></textarea> </div> <p class="contact-submit"> <input type="submit" value="送信 »" id="submit"> <input id="referrer" type="hidden" name="referrer" /> </p> </form> <div id="dispmsg"></div> <!-- スタイルシート --> <div> <style> #mailform input[type='text'], #mailform input[type='email'] { font-size: 1em; width: 300px; max-width: 100%; margin-bottom: 13px; box-sizing: border-box; } #mailform input, #mailform button { height: 40px; padding: 0 10px; } #mailform textarea { font-size: 1em; margin-bottom: 13px; padding: 2px 5px; width:100%; box-sizing: border-box; } #mailform label { margin-bottom: 3px; font-weight: bold; display: block; } #mailform label span { color: #aaa; margin-left: 4px; font-weight: normal; } #submit{ width:200px; } #dispmsg > p{ border: 3px solid #ffe3b3; background: #ffffeb; border-radius: 7px; padding: 15px; margin: 30px 0; text-align: center; font-weight: bold; } #dispmsg blockquote { margin: 30px 0; padding: 15px; background-color: #f3f3f3 } #dispmsg pre { font-family: -apple-system,BlinkMacSystemFont,Meiryo,Verdana, "Helvetica Neue","Segoe UI","Noto Sans Japanese","ヒラギノ角ゴ ProN W3",sans-serif; line-height: 1.7; white-space: pre-wrap; background: #fafafa; margin: 15px 0 0; padding: 10px; } #dispmsg #errmsg{ background: #fff5f5; border: 3px solid #fcc; color: #e1536a; } </style> </div> <!-- JavaScript --> <div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <script> jQuery(function ($) { $("#referrer").val(document.referrer); $("#mailform").submit(function(){ $.ajax({ url : 'PHPソースコードのパス', type: 'POST', dataType: 'json', data: $(this).serialize() }) .done( function(data){ $("#dispmsg").empty(); $("#dispmsg").html(data.dispmsg); if(data.errflg != 1){ $("#mailform").remove(); } }) .fail( function(data){ alert('メール送信に失敗しました'); }) return false; }); }); </script> </div>
スタイルシートと JavaScript は、テーマ用ファイルに記載しても構いません。ただ jQuery の Ajax 処理を利用しているため、jQuery のライブラリを読み込む必要があります。ここでは 73 行目の処理で、Google の CDN からスクリプトのファイルを読み込んでいます。
JavaScript のプログラムは、jQuery ライブラリの読み込み後に記載する必要があります。WordPress の設定で jQuery を読み込んでいる場合、</body> タグの直前で読み込んでいるとエラーになります。上記のように、処理の直前に記載してください。なお jQuery ファイルは二重で読み込まれても問題ありません。
処理用のスクリプトやスタイルシートは、このメールフォームでしか使わないため、テーマ内のファイルに記述するより、画面内で定義するのをおすすめします。
CSS は現状設定しているものと重複する場合があります。必要に応じて適宜変更してください。
【重要】100 行目の「PHPソースコードのパス」は、このあと作成する PHP のファイルパスに書き換えてください。
メール送信用 PHP ファイル
メール送信部分は PHP で実装します。
<?php // json 形式のデータを扱うための定義 header('Content-type: application/json'); // PHP5.1.0以上はタイムゾーンの定義が必須 date_default_timezone_set('Asia/Tokyo'); // -------------------------- // 個別設定項目(3つ) // -------------------------- // 送信先メールアドレス $to = 'xxxx@xxxx.com'; // メールタイトル $subject = 'お問い合わせフォームより'; // ドメイン(リファラチェックと送信元メールアドレスに利用) $domain = 'xxxx.xxxxxxxx.com'; //変数初期化 $errflg =0; // エラー判定フラグ $dispmsg =''; // 画面出力内容 // 入力項目 $nameval = ''; // 名前 $mailval = ''; // メールアドレス $urlval = ''; // ウェブサイト $textval = ''; // 内容 $referrer = ''; // 遷移元画面 // 画面からのデータを取得 if(isset($_POST['nameval'])){ $nameval = $_POST['nameval']; } if(isset($_POST['mailval'])){ $mailval = $_POST['mailval']; } if(isset($_POST['urlval'])){ $urlval = $_POST['urlval']; } if(isset($_POST['textval'])){ $textval = $_POST['textval']; } if(isset($_POST['referrer'])){ $referrer = $_POST['referrer']; } if(strpos($_SERVER['HTTP_REFERER'], $domain) === false){ // リファラチェック $dispmsg = '<p id="errmsg">【リファラチェックエラー】お問い合わせフォームから入力されなかったため、メール送信できませんでした。</p>'; $errflg = 1; } else if($nameval == '' || $mailval == '' || $textval == ''){ //必須チェック $dispmsg = '<p id="errmsg">【エラー】名前・メールアドレス・内容は必須項目です。</p>'; $errflg = 1; } else if(!preg_match("/^[.!#%&-_0-9a-zA-Z?/+]+@[!#%&-_0-9a-z]+(.[!#%&-_0-9a-z]+)+$/", $mailval) || count( explode('@',$mailval) ) !=2){ //メールアドレスチェック $dispmsg .= '<p id="errmsg">【エラー】メールアドレスの形式が正しくありません。</p>'; $errflg = 1; } else{ // メールデータ作成 $subject = "=?iso-2022-jp?B?".base64_encode(mb_convert_encoding($subject,'JIS','UTF-8'))."?="; $message= '名前:'.$nameval."n"; $message.='メール:'.$mailval."n"; $message.='ウェブサイト:'.$urlval."n"; $message.="n――――――――――――――――――――――――――――――nn"; $message.=$textval; $message.="nn――――――――――――――――――――――――――――――n"; $message.='送信日時:'.date( "Y/m/d (D) H:i:s", time() )."n"; $message.='送信元IPアドレス:'.@$_SERVER["REMOTE_ADDR"]."n"; $message.='送信元ホスト名:'.getHostByAddr(getenv('REMOTE_ADDR'))."n"; $message.='リファラURL:'.$referrer."n"; $message.='お問い合わせページ:'.@$_SERVER['HTTP_REFERER']."n"; $message= mb_convert_encoding($message,'JIS','UTF-8'); $fromName = mb_encode_mimeheader(mb_convert_encoding($nameval,'JIS','UTF-8')); $header ='From: '.$fromName.'<wordpress@'.$domain.'>'."n"; $header.='Reply-To: '.$mailval."n"; $header.='Content-Type:text/plain;charset=iso-2022-jpnX-Mailer: PHP/'.phpversion(); // メール送信 $retmail = mail($to,$subject,$message,$header); // 送信結果の判定 if( $retmail ){ $dispmsg ='<p class="success">メールを送信しました。返信までしばらくお待ちください。</p>'; $dispmsg.='<blockquote><p>名前: '.hsc_utf8($nameval).'<br />'; $dispmsg.= 'メール: '.hsc_utf8($mailval).'<br />'; $dispmsg.= 'ウェブサイト: '.hsc_utf8($urlval).'</p>'; $dispmsg.= '<pre>'.hsc_utf8($textval).'</pre></blockquote>'; }else{ $dispmsg .= '<p id="errmsg">【エラー】メール送信に失敗しました。。</p>'; $errflg = 1; } } // 処理結果を画面に戻す $result = array('errflg'=>$errflg, 'dispmsg'=>$dispmsg); echo json_encode( $result ); // HTMLエスケープ処理 function hsc_utf8($str) { return htmlspecialchars($str, ENT_QUOTES,'UTF-8'); } ?>
上記 PHP プログラムのダウンロードファイルを用意したのでご利用ください。
保存したファイルは zip 形式です。解凍した上で、プログラム内の個別設定項目(11, 13, 15 行目)を自身の環境に合わせて書き換えてください。
あとは FTP を使って任意の場所にアップロードし、このアップロードした場所に応じて、HTML 側の 100 行目「PHPソースコードのパス」を指定します。
メール送信プログラムの実装内容
実装画面のイメージ
上記のソースコードをそのまま利用すると、画面イメージは次のようになります。
入力フォーム画面イメージ
メール送信 正常終了時の画面
メールフォームに正しい情報を入力して送信すると、入力フォームが画面上から非表示になり、送信した情報が画面に表示されます。このとき画面遷移せず、裏でメールを送信した後、画面表示切り替えを行います。
メールフォームは画面から消えて、送信した情報が画面に表示されます。
メール送信 エラー時の画面
エラー時はメールフォームの情報はそのままで、送信ボタンの下部にエラーメッセージを表示します。
HTML5 のフォームオブジェクトで簡易入力チェック
メールアドレスのフォーマットチェックと、必須項目のチェックが html 上で行われます。正確にはブラウザ側がチェックをしてくれるもので、HTML5 により実装された機能です。
例えばメールアドレスの場合、input の type 属性は text でなく email を採用しています。これにより、不正なメールアドレスが入力された場合、送信時に入力エラーとしてメッセージが表示されます。ブラウザによって表示形式は異なりますが、概ね同様のチェックが行われます。
以下の画像は、Chrome ブラウザにてチェック処理が行われた場合の表示イメージになります。
必須項目は input タグに required の属性を追加することで、送信時に入力チェックが行われます。こちらも HTML5 の新機能になります。
ブラウザが古い場合、これらのチェック機能が正しく動かないケースがあります。そのためサーバー側の PHP の処理においても、同様の入力項目チェックを用意しています。
変更が必要な箇所は4箇所
上記のソースコードを丸ごとコピーしても正しく動作しません。利用する環境に応じて、必ず次の項目を書き換えてください。
- 100行目「PHPソースコードのパス」
例えばドメイン直下に PHP ファイルをアップロードした場合は、次のように記します。
- url : ‘https://webllica.com/sendmail.php’,
- url : ‘/sendmail.php’,
- 11行目「$to = ‘xxxx@xxxx.com’;」送信先のメールアドレス
- 13行目「$subject = ‘お問い合わせフォームより’;」メールのタイトル
- 15行目「$domain = ‘xxxx.xxxxxxxx.com’;」ドメイン
タイトルは固定にしているため PHP 上で定義しています。ドメインの定義は WordPress を設置しているトップレベルドメイン、もしくはサブドメインを定義してください。(WordPress の URL の http:// を除いた、次のスラッシュまでの文字列を設定します。)
PHP 上でリファラチェックを実施
PHP ファイルの 35 ~ 39 行目に該当する箇所です。
if(strpos($_SERVER['HTTP_REFERER'], $domain) === false){ // リファラチェック $dispmsg = '<p id="errmsg">【リファラチェックエラー】お問い合わせフォームから入力されなかったため、メール送信できませんでした。</p>'; $errflg = 1; }
メールフォームを設置したページ以外からメールが送られないように制御しています。外部から不正にメール送信プログラムが呼び出されないようにするための処理です。この時チェックに利用しているのが、前項のドメイン変数です。
本来であれば .htaccess の設定で、外部ドメインからメール送信用 PHP ファイルにアクセスできないように制御するのが望ましいです。
PHP 上のアドレスチェックは簡易的なもの
PHP ファイルの 45 ~ 49 行目に該当する箇所です。
else if(!preg_match("/^[.!#%&-_0-9a-zA-Z?/+]+@[!#%&-_0-9a-z]+(.[!#%&-_0-9a-z]+)+$/", $mailval) || count( explode('@',$mailval) ) !=2){ //メールアドレスチェック $dispmsg .= '<p id="errmsg">【エラー】メールアドレスの形式が正しくありません。</p>'; $errflg = 1; }
正規表現を用いて入力チェックをしています。ただし、ここで実装しているものは不完全なチェックです。完璧なチェックをすると、とんでもなく巨大なソースコードになってしまうため、最低限のチェックに留めていることをご了承ください。
送信者は入力された名前を表示
PHP ファイルの 65 ~ 67 行目に該当する箇所です。
$fromName = mb_encode_mimeheader(mb_convert_encoding($nameval,'JIS','UTF-8')); $header ='From: '.$fromName.'<wordpress@'.$domain.'>'."n"; $header.='Reply-To: '.$mailval."n";
受信したメールの送信者の欄には、入力された「名前」の項目を表示します。ただし、送信元のメールアドレスは「wordpress@ドメイン名」となるように設定しています。
勿論、入力されたメールアドレスを利用する方法もあります。しかしメーラー(例えば Gmail)によっては、入力されたアドレスを利用すると自動的に迷惑メールに分類されてしまうケースがあるため、ここでは自身のドメインから送られたように実装しています。
一方で 67 行目の処理にて、返信先には入力されたメールアドレスを設定しているので、メーラーから「返信」する場合は、自動的に画面で入力されたメールアドレスが送信先に設定されます。
メールに出力される情報
このプログラムに従ってメールが送られると、次のようなフォーマットでメールが届きます。(画面は Gmail のものです。)
下部のリファラ URL は、お問い合わせのページを開く前にアクセスしていたページの情報をセットしています。プラグインだと取得できない情報なので、オリジナルの便利機能として実装しました。
非同期による高速処理を実現
冒頭でも説明しましたが、このメールフォームの最大の特徴が非同期による処理です。
Ajax で実装することで、全ての処理が1つの画面内で完結するように仕上がっています。メール送信処理は簡単なプログラムなので、送信ボタンを押してから一瞬で処理結果が表示されます。
一般的なメールフォームでは送信完了画面に遷移するものが多く、画面の再読込が発生します。送信してから完了画面を描画するまで、少なく見積もっても数秒は掛かるので、この非同期メールフォームの速さには驚くかもしれません。
では最後に、このメールフォームを利用する上での注意点をお伝えしておきます。
注意点
- JavaScript が動作する環境が必須になります
- 迷惑メール対策は実装していません
WordPress から送られる迷惑メールは、プラグインを使ったメールフォームを設置しているサイトに多く見られます。全て同じ仕組みなので、外部から大量に送られやすいのデメリットがあります。
自作のフォームであれば余程のことがない限り、連投で迷惑メールが飛んでくることはありません。ただ100%万能とも言い切れないので、将来的には必要に応じて迷惑メール対策の拡張を行っていこうとは考えています。
以上、WordPress でプラグインを利用しない自作メールフォームの紹介でした。