ファイル添付フォームメール
既にKOMONETの方では公開・配布しているんですが、なかなかこちらで解説ページをアップする暇がなくてごめんなさい。ようやくコード内容を解説する機会ができました。どうぞご覧下さい。
通常のメーラーなどでは、ファイルを添付してメールを送信することが結構あると思います。画像ファイルやワードファイルなと、何でも添付して相手に送れます。とっても便利ですね。
*注意…このスクリプトはPHP4.2.0以降のスーパーグローバル変数に対応したものになっています。
ファイル構成
このスクリプトは通常のHTMLページからフォームメール・スクリプトを呼び出して、一旦確認画面を表示後メールを送信するタイプです。ファイル構成は以下の通りです。
komomail.htm・・・メール送信用HTMLページ
komomail.php・・・メール送信用PHPスクリプト
ここでは、メール送信用PHPスクリプトの内容のみを解説します。HTMLページについてはブラウザ上で下のサンプルページのソースを表示してご覧下さい。
[注意]このスクリプトは、文字コード変換に関してはPHPの自動変換機能に任せていますので、Turbolinux以外のLinuxディストリビューションの場合(特に基本文字コードがeucJPでない場合)、送信メールの内容に文字化けの可能性があります。その場合は、送信前の文字コード変換処理が必要です。ご注意下さい。
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=x-sjis">
<TITLE>KOMOメール</TITLE>
<STYLE TYPE="text/css">
<!--
:link {
Color : blue ;
Text-Decoration : None
}
:active {
Color : blue ;
Text-Decoration : None
}
:visited {
Color : blue ;
Text-Decoration : None
}
A:hover {
Color : blue ;
Text-Decoration : Underline
}
-->
</STYLE>
</HEAD>
<BODY BGCOLOR="#FFFBF0">
<CENTER>
<P><IMG SRC="title.gif" WIDTH="244" HEIGHT="69" ALIGN="BOTTOM" BORDER="0"></P>通常のHTMLによるページの先頭部分です。解説は要りませんね(^^ゞ <?php
//=====================初期設定======================
$to = "komochan@komonet.ne.jp";
$subject = "From Komomail Sample Script";
$boundary = md5(uniqid(rand())); //バウンダリー文字(パートの境界)
//===================================================定番の初期設定部分です。
変数$boundaryはメールの記事部分と添付ファイル部分との境界を示す文字列です。
★string md5 ( string str )関数・・・文字列のmd5ハッシュ値を計算します。
★string uniqid ( string prefix [ , boolean lcg ] )関数・・・ユニークなIDを生成します。uniqid( )は、ミリ秒単位の現在時刻に基づき、引数prefix で指定された文字列を先頭に付けたユニークなIDを返します。
★int rand ( [ int min [ , int max ] ] )関数・・・乱数を生成します。オプションの引数min, max を省略してコールした場合、rand( )は0とRAND_MAXの間の擬似乱数を返します。使用する前にsrand( )により乱数生成器を初期化する必要があります。
「md5(uniqid(rand( )))」の組み合わせにより、推測が困難でより優れたユニークなIDを生成します。$php_v = PHP_VERSION; //PHPバージョンの取得
if($php_v > "4.1.0"){ //スーパーグローバル変数対応なら
$PHP_SELF = $_SERVER["PHP_SELF"];
//フォームデータの取得
$action = $_POST['action'];
$name = $_POST['name'];
$email = $_POST['email'];
$hp = $_POST['hp'];
$area = $_POST['area'];
$tel = $_POST['tel'];
$comment = $_POST['comment'];
$upfile = $_FILES['upfile']['tmp_name'];
$upfile_name = $_FILES['upfile']['name'];
$upfile_type = $_FILES['upfile']['type'];
}PHPのバージョン情報を取得し、スーパーグローバル変数対応なら、各変数の値を取得します。 //確認画面を生成
if($action == "post"){
if($name && $email){
//ここから書き込みデータの調整
$name = htmlspecialchars($name); //特殊文字のHTMLエントリへの変換
$email = htmlspecialchars($email);
$hp = htmlspecialchars($hp);
$comment = htmlspecialchars($comment);
$comment = nl2br($comment); //HTML改行文字の挿入
$comment = str_replace("\r", "", $comment);
$comment = str_replace("\n", "", $comment);
//確認ページを生成
echo "▼メッセージ確認(送信先: $to )▼<br>\n";
echo "<TABLE BORDER=1 CELLSPACING=0 WIDTH=80%>\n";
echo "<FORM ACTION=$PHP_SELF METHOD=POST ENCTYPE=multipart/form-data>\n";
echo "<INPUT TYPE=HIDDEN NAME=action VALUE=send>\n";
echo "<TR><TD WIDTH=30%>お名前</TD><TD WIDTH=70%>$name</TD></TR>\n";
echo "<INPUT TYPE=HIDDEN NAME=name VALUE=\"$name\">\n";
echo "<TR><TD WIDTH=30%>E-mail</TD><TD WIDTH=70%>$email</TD></TR>\n";
echo "<INPUT TYPE=HIDDEN NAME=email VALUE=\"$email\">\n";
if($hp){
echo "<TR><TD WIDTH=30%>HomePage</TD><TD WIDTH=70%>$hp</TD></TR>\n";
echo "<INPUT TYPE=HIDDEN NAME=hp VALUE=\"$hp\">\n";
}
echo "<TR><TD WIDTH=30%>住んでる地域</TD><TD WIDTH=70%>$area</TD></TR>\n";
echo "<INPUT TYPE=HIDDEN NAME=area VALUE=$area>\n";
if($tel){
echo "<TR><TD WIDTH=30%>お電話</TD><TD WIDTH=70%>$tel</TD></TR>\n";
echo "<INPUT TYPE=HIDDEN NAME=tel VALUE=\"$tel\">\n";
}
if($comment){
echo "<TR><TD WIDTH=30%>ご意見</TD><TD WIDTH=70%>$comment</TD></TR>\n";
echo "<INPUT TYPE=HIDDEN NAME=comment VALUE=\"$comment\">\n";
}
echo "<TR><TD WIDTH=30%>添付ファイル</TD><TD WIDTH=70%><INPUT TYPE=file NAME=upfile SIZE=35 VALUE=\"$upfile\"></TD></TR>\n";
echo "</TABLE><br>\n";
echo "<INPUT TYPE=SUBMIT NAME=Submit VALUE=送信する></FORM>\n";
}else{
echo "必須項目が書き込まれていません。やり直して下さい_(._.)_<br><br>\n";
echo "<INPUT type=button name=close value=閉じる onclick=window.close()>\n";
}HTMLページから送信されたデータを受けて、一旦確認ページを表示します。
最初に書き込みデータの調整をしていますが、これは掲示板などでお馴染みの処理ですね(^.^)
後は通常のフォーム生成ですが、注意しなくてはいけないのは、ファイルをアップロードしなくてはいけないので、フォームのENCTYPEは「multipart/form-data」となります。}elseif($action == "send"){
//メッセージ送信
$msg = "";
$from = $email;
$header = "From: $from\n";
$header .= "Reply-To: $from\n";
$header .= "X-Mailer: PHP/".phpversion()."\n";
$header .= "MIME-version: 1.0\n";
if(file_exists($upfile)){ //アップファイルがあれば
$header .= "Content-Type: multipart/mixed;\n";
$header .= "\tboundary=\"$boundary\"\n";
$msg .= "This is a multi-part message in MIME format.\n\n";
$msg .= "--$boundary\n";
$msg .= "Content-Type: text/plain; charset=ISO-2022-JP\n";
$msg .= "Content-Transfer-Encoding: 7bit\n\n";
}else{
$header .= "Content-Type: text/plain; charset=ISO-2022-JP\n";
$header .= "Content-Transfer-Encoding: 7bit\n";
}
$msg .= "お名前 = $name\n";
$msg .= "E-mail = $email\n";
if($hp){ $msg .= "HomePage = $hp\n"; }
if($area){ $msg .= "住んでる地域 = $area\n"; }
if($tel){ $msg .= "お電話 = $tel\n"; }
if($comment){
$comment = str_replace("<br />", "\n", $comment);
$msg .= "ご意見 = $comment\n";
}
if(file_exists($upfile)){
$fp = fopen($upfile, "r") or die("error"); //ファイルの読み込み
$contents = fread($fp, filesize($upfile));
fclose($fp);
$f_encoded = chunk_split(base64_encode($contents)); //エンコードして分割
$msg .= "\n\n--$boundary\n";
$msg .= "Content-Type: " . $upfile_type . ";\n";
$msg .= "\tname=\"$upfile_name\"\n";
$msg .= "Content-Transfer-Encoding: base64\n";
$msg .= "Content-Disposition: attachment;\n";
$msg .= "\tfilename=\"$upfile_name\"\n\n";
$msg .= "$f_encoded\n";
$msg .= "--$boundary--";
}
if(mail($to, $subject, $msg, $header)){ //ファイル添付に対応
echo "メールが正常に送信されました(^o^)丿<br><br>\n";
echo "<INPUT type=button name=close value=閉じる onclick=window.close()>\n";
}else{
echo "メールの送信に失敗しました(>_<)もう一度やり直して下さい。<br><br>\n";
echo "<INPUT type=button name=close value=閉じる onclick=window.close()>\n";
}
}
?>メッセージの送信処理です。
添付ファイルがある場合とない場合とで、コード処理を分けています。
添付ファイルがある場合は、記事と添付ファイルとの間に、パートの境界となるバウンダリー文字列を挿入します。
ファイル添付タイプなので、メール送信にはマルチバイト文字対応のmb_send_mail( )関数は使えませんので、mail( )関数を使っています。
★void die ( string message )関数・・・引数message で渡したメッセージを出力し、スクリプトの処理を終了します。この関数の戻り値はありません。
★string chunk_split ( string string [ , int chunklen [ , string end ] ] )関数・・・文字列をより小さな部分に分割する際に使用されます。引数chunklen (デフォルトは76)文字ごとに文字列end (デフォルトは"\r\n")を挿入します。変換前の元の文字列はそのままとし、変換後の新しい文字列を返します。
★string base64_encode ( string data )関数・・・base64_encode( )は、data をBase64方式でエンコードします。Base64でエンコードされたデータは、エンコード前のデータに比べて33%よけいに記憶容量を必要とします。
[Base64]
電子メールに画像などのバイナリデータを添付する際に、中身を文字列(テキスト)データに置換(エンコード)する方式の一つ。メールにはテキストデータしか載せられない為、画像や音声、ワープロ文書などのバイナリファイルは、そのままでは送受信できない。この為、送信時に一定のルールに従ってデータを文字に置換し、受信後に元のデータに復元(デコード)するという手法が取られるようになった。この置換ルールの1つがBASE64である。インターネット上の電子メールでは、このBASE64を用いるのが標準的である。
[エンコード]
データを一定の規則に基づいて符号化すること。エンコードを行なうソフトウェアをエンコーダという。データの圧縮や暗号化などがこれにあたる。エンコードされたデータを元に戻すことをデコードという。</CENTER>
</BODY>
</HTML>ページの終了部分です。 添付ファイルの数を2つ以上にしたい場合は、KOMONETサイトで無料配布しているスクリプトのソースをご参照下さい。
*上の内容をこのまま複写しても動きません。何故なら、表示を見やすくする為コード中に全角スペースが入っているからです。実際にお使いになる時は、この点を修正してからサーバにアップして下さい。