PHPでメールフォーム作成

メールフォームで相互リンクの募集とか、問い合わせを作りたい、そんな人のための記事です。

HTMLには、「mailto:」というのがあって、

<a href="mailto:aaa@aaa.jp">メールはこちらへ</a>

のような形で記述することで、メーラーが自動的に立ち上がり、メールを送る事ができますが、htmlファイルに送信先アドレスが丸見えなので、これがスパムの標的になります。

そのため、メールでの問い合わせは、formとperlやphpのようなスクリプト言語で作られたメールフォームを使用するのがいいようです。

名前
性別
血液型
郵便番号
メールアドレス(送信先)
メールアドレス(あなたの)
件名
内容


htmlファイル内の記述

以下、html内の記述。無駄な項目もありますが、練習に。

<form action="https://nkdesk.com/4.php" method="post">
<dl>
<dt>名前</dt>
<dd><input name="name" id="name" type="text" size="50" /></dd>
<dt>性別</dt>
<dd>
<input name="gender" id="man" type="radio" value="男性" /><label for="man">男性</label><input name="gender" id="woman" type="radio" value="女性" /><label for="woman">女性</label>
</dd>
<dt>血液型</dt>
<dd>
<select name="blood" id="blood">
<option value="A型">A型</option>
<option value="B型">B型</option>
<option value="O型">O型</option>
<option value="AB型">AB型</option>
</select>
</dd>
<dt>郵便番号</dt>
<dd><input name="yubin" id="yubin" type="text" size="50" /></dd>
 
<dt>メールアドレス(送信先)</dt>
<dd><input name="mail" id="mail" type="text" size="50" maxlength="255" /></dd>
 
<dt>件名</dt>
<dd><input name="sub" id="sub" type="text" size="50" maxlength="255" /></dd>
<dt>内容</dt>
<dd><textarea name="naiyou" id="naiyou" cols="50" rows="10"></textarea></dd>
</dl>
<input type="submit" value="送信する" />
</form>

formの説明。全てのinputに共通してsubmitのボタンを押すと、from内のデータが、nameがキー、valueが値として、https://aaa.com/?name=value&?name=valueのようなかたちで、actionで指定したphpファイルに受け渡される。

idは、cssの指定の際や、label for=”id”の形で使用される。

select文のoptionを羅列するのが面倒な場合は、phpの命令を使うのもよい。

//単純な数字の羅列であれば、for文を使うと良い
//10になるまで$iは1ずつ増やして、その値をoption内で使用する。
for($i=1; $i<=10; $i++){
    echo("<option value='".$i."'>".$i."型</option>");
}
//名前に規則性がなければ、配列を作り、foreachで取り出すと良い
//array(配列)のデータを$katasに入れて、katasがtrueであればkataに値をいれて、それを表示、falseで終了
$katas=array("A型","B型","O型","AB型");
foreach($katas as $kata){
    echo("<option value='".$kata."'>".$kata."</option>");
    }

名前、性別、メルアド、題名、本文は特に難しい所はない。性別っている?と言われそうだが、チェックボックスの練習のために入れただけ。アドレスと題名と本文は送られたphpファイルで使用するので出来れば入れたいところだ。

郵便番号は正規表現の練習のための記述。○○○-○○○○の形でなければエラーを返すようにしておく。

phpファイル内の記述

php.iniというファイルを編集して、言語とエンコードを指定しているのであれば、上二行のコードは必要ない。

上のフォームで送信したデータは、POST形式のデータとして、下記のphpファイルに送られ、処理されます。なお送り先のファイルのタイトルタグがencode指定のメタタグよりも前にある場合はutf-8を指定していたとしても強制的にsjisに変換されて文字化けが起こるというバグがあります(IEのみ)。なので、IE対策としてタイトルタグはメタタグよりも後に記述しましょう。

まずは、簡単な条件分岐としてメールアドレスが空(empty)でなければ、受信したデータを変数に格納します。(htmlとして出力するわけでも、SQLとして使うわけでもないので、htmlspecialcharsやescapeは必要ない)

<?php 
//php.iniの編集ができない場合の言語とエンコード指定
mb_language("japanese");
mb_internal_encoding("utf-8");
 
if(!empty($_POST['mail'])){
    $to=$_POST['mail'];
    $subject=$_POST['sub'];
    $naiyou=$_POST['naiyou'];
    $name=$_POST['name'];
    $gender=$_POST['gender'];
    $blood=$_POST['blood'];
    $yubin=$_POST['yubin'];

//郵便番号の型の判定
$yubin=mb_convert_kana($_POST['yubin'],'a','utf-8');
 
if(!preg_match("/\A\d{3}\-\d{4}\z/",$yubin)){
    $yubin="正しい郵便番号を入力してください";
}
//ここまで郵便番号
 
$success=mb_send_mail($to,$sub,"名前:".$name." 性別:".$gender." 血液型:".$blood." 郵便番号:".$yubin." 本文:".$naiyou,"from:".$from);
}
?>
 
 
<?php 
if($success){
    echo('送信しました');
}else{
    echo('送信失敗!!');
}
?>

郵便番号のとこは一旦飛ばし、変数のデータをメールサーバーに飛ばす命令が、mb_send_mail()です。飛ばす他、判定もしてくれる命令です。

mb_send_mail(送信先アドレス,題名,本文,送信元アドレス);

効果判定をするために、mb_send_mailの内容を$success変数に入れて、if文の中でそれを実行し、trueなら「送信しました」、falseなら「送信失敗」とでるようにします。

郵便番号に戻って、mb_convert_kanaは、全角から半角、もしくは半角から全角にする命令で、aは英数字、他n(数字)等がある。

preg_matchは、phpで正規表現を使用する命令で、スラッシュで囲まれた中身を比較する。¥Aは文字列の先頭(^と違って改行に影響しない)、¥zは文字列の最後($と違って改行に影響しない)、¥dが数字([0-9]と同じ)、{}内が文字数、三文字の数字+ハイフン+4文字の数字でなければ、「正しい番号を記入」とでるようにする。(正規表現は全ての言語共通))

$yubin=mb_convert_kana($_POST['yubin'],'a','utf-8');
 
if(!preg_match("/\A\d{3}\-\d{4}\z/",$yubin)){
    $yubin="正しい郵便番号を入力してください";
}

これで、メールを送るときちんと届くはずだが、届いたメールの送り主が自サーバーのアドレスになっていると思う。送り主のアドレスを表示させたいなら、フォームで送り主のアドレス欄を作っておこう。

入力してもらった送り主のアドレスから送られたデータ(例ではmail)を変数に入れて、その変数と、名前の変数を加工して、別の変数fromに入れています。

メールは一律JISでエンコードなので、差出人の名前の日本語部分を、mb_convert_encodingでutf-8からjisに直して、mb_encode_mimeheaderでMIMEヘッダに変換して、アドレス部分と結合しています。

$mail=$_POST['mail'];    
$from=mb_encode_mimeheader(mb_convert_encoding($name,"jis","utf-8"))."<".$mail.">";
 
$success=mb_send_mail($to,$sub,"名前:".$name." 性別:".$gender." 血液型:".$blood." 郵便番号:".$yubin." 本文:".$naiyou,"from:".$from);

これで、メールが届いた時に、送信者の名前も表示されるようになったはずです。

このやり方で差出人名や内容が日本語文字だった場合に、送られてきたメールの本文にて文字化けを起こすことがあります(tunderbird、gmail確認)。この例では、$nameと$naiyouのどちらかの文字が文字化けします。

調べようかと思いましたが、すぐにわからなそうだったので、下記のように適当に対処。なんだか4番目の引数にFrom:とするとメーラーの差出人のアドレスにきちんと表示されてるし。

<?php 
header("Content-Type:text/html; charset=UTF-8");
mb_language("japanese");
mb_internal_encoding("utf-8");
 
if(!empty($_POST['name'])&&($_POST['naiyou'])&&($_POST['sub'])){
    $name=$_POST['name'];
    $mail=$_POST['mail'];
    $sub=$_POST['sub'];
    $naiyou=$_POST['naiyou'];
    $mymail="aaa@nkdesk.com";
 
$naiyouall="ハンドルネーム:".$name."\n内容:\n".$naiyou;
$success=mb_send_mail($mymail,$sub,$naiyouall,"From:".$mail);
}
 
if($success){
    echo("送信しました\n\n");
    echo("<a href='prof.php'>戻る</a>");
    
}else{
    echo("送信失敗。必須事項を入力してください。");
}  
?>

ファイルの送信

Facebookの画像のように、ファイルのアップロード、そして表示であれば、簡単ですが、添付ファイルとして送信する形のファイル送信は一筋縄ではいかないようです。

<form action="https://nkdesk.com/4.php" method="post" enctype="multipart/form-data">
<dl>
<dt>ファイル</dt>
<dd><input name="pic" id="pic" type="file" size="50" /></dd>
</dl>
<input type="submit" value="送信する" />
</form>

formで送信されたデータは、phpファイルないでは、$_FILESという変数で取り出すことができます。この変数は連想配列になっており、下記の5つ(name,type,tmp_name,error,size)のキーで値を取り出すことができます。

これで終わりでもいいんですが、スパム防止のために、substr()命令で、最後3文字を切り出し、それがgifまたはjpgなら、その画像をアップロードするフォルダのURLを変数に入れて、move_uploaded_file()で一時保存されているフォルダから、指定フォルダへコピーします。

この時点で、サーバーの指定フォルダに画像が移動しているので、img srcで表示させればOKです。

&&はand、||はorの論理演算子。

スパムで送信されるのがやなのでスクリプトのみ。

<?php
//phpのファイル
$file = $_FILES['pic'];
 
echo($file['name']);
echo($file['type']);
echo($file['tmp_name']);
echo($file['error']);
echo($file['size']);
 
$ext=substr($file['name'],-3);
if($ext=='gif'||$ext=='jpg'){
    $filepath = './user_img/' . $file['name'];
    move_uploaded_file($file['tmp_name'],$filepath);
    echo("<img src='".$filepath."' />");
}else{
    echo("ファイルなし");
}
?>
 
<?php 
if($success){
    echo('送信しました');
}else{
    echo('送信失敗!!');
}
?>

添付ファイルを使用する方法については、面倒な上、使う機会が少なそうなので、別サイト(添付ファイルを送信)を参照。ライブラリを使用するようです。

コメントor補足情報orご指摘あればをお願いします。

(件名or本文内でキーワード検索できます)



  • << 前のページ
  • 次のページ >>
ページトップへ