phpな休日 BBS sitemap
1. ファイル添付メールフォームの概要

ファイルを添付出来るメールフォームです。
テキストメールですと mb_send_mail 関数が全てうまくやってくれるのですが、添付ファイルがある場合は対応出来ないので、mail 関数を使用します。
その場合、文字コードの変換から header の書き出しまで手動になります。

機能は最小限にとどめましたが、[送信者の名前]・[送信者のメールアドレス]・[タイトル]・[文面] の全てに入力がないと送信出来ないようにしました。
入力漏れがあった場合入力画面に戻すわけですが、その際すでに入力したものがPOSTされていればそちらから引っ張っています。

無事に送信が完了した場合、送信した内容を表示するようにしました。(添付はファイル名とファイルサイズのみ表示)

2. バウンダリー文字

メールにファイルを添付する場合、添付ファイルを“文字”に変換して送るわけですが、その際メール本文と添付ファイルの境界を明らかにするためにバウンダリー文字を使用します。
マニュアルに習って md5(uniqid(rand(),1)) としました。その部分だけ実行してみます。

$boundary = md5(uniqid(rand(),1)); //境界バウンダリー文字生成
print $boundary;

 

実行
2. 送信(前)処理

POSTの受け取り処理は特に目新しいところはありませんが、送信後にブラウザで表示するために $viewname = $name などで、UTFの文字列を確保しています。
メールアドレスに関しては、形式がメールアドレスであるかを正規表現にてチェックしています。
送信前のメールヘッダの処理などはマニュアルの丸写しですが、メールの文字コードはJIS(charset=ISO-2022-JP)、添付ファイルは base64 というエンコードを使用する、ということらしいです。

なお、メールの添付ファイルの容量は受け取り側のサーバー(プロパイダ)の制限がありますので、フォームでメール送信が完了しても添付ファイルが付いていかない場合があります。(ここのサーバーは2MBまで、添付ファイルはエンコードで膨張(33%くらい)するので実際に送れる添付ファイルは1.5MBくらいと思っていたほうが良いでしょう)

3. スクリプト(pmail.php)

スクリプトは pmail.php 1つだけです。ファイル名を変更する場合は、スクリプト中の pmail.php も書きかえてください。
2012年8月10日、よこよこ様のご指摘で82行目修正しました。

<?php
mb_language("ja");
mb_internal_encoding("UTF-8");
$boundary = md5(uniqid(rand(),1)); //境界バウンダリー文字生成
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<title>p-ho AttachMailForm</title>
</head>
<body>
<?php
if(isset($_POST["name"])){ $name = $_POST["name"]; //POSTに値があれば処理
if( get_magic_quotes_gpc() ) { $name = stripslashes("$name"); } //クォートをエスケープする
$name = htmlspecialchars ($name); //HTMLタグ禁止
$viewname = $name; //送信後のHTML表示用
}
if(isset($_POST["email"])){ $email = $_POST["email"]; //POSTに値があれば処理
if (!preg_match('/^[a-zA-Z0-9_¥.¥-]+?@[A-Za-z0-9_¥.¥-]+$/',$email)) { //メールアドレスでなければ
$email = ""; //変数 $email を空にする
}
}
if(isset($_POST["title"])){ $title = $_POST["title"]; //POSTに値があれば処理
if( get_magic_quotes_gpc() ) { $title = stripslashes("$title"); } //クォートをエスケープする
$title = htmlspecialchars ($title); //HTMLタグ禁止
$viewtitle = $title; //送信後のHTML表示用
}
if(isset($_POST["comment"])){ $comment = $_POST["comment"]; //POSTに値があれば処理
if( get_magic_quotes_gpc() ) { $comment = stripslashes("$comment"); } //クォートをエスケープする
$comment = str_replace("¥r¥n", "¥r", $comment); //Windowsの改行コードを置き換え
$comment = str_replace("¥r", "¥n", $comment); //Machintoshの改行コードを置き換え
$comment = htmlspecialchars ($comment); //HTMLタグ禁止
$viewcomment = str_replace("¥n", "<br>", $comment); //¥nを<br>に変換(表示用)
}
if ($_FILES["attach"]["name"]) { //添付ファイルがあれば
$attach = $_FILES["attach"]["tmp_name"];
$attachname = $_FILES["attach"]["name"];
$viewattachname = $attachname; //送信後のHTML表示用
$attachtype = $_FILES["attach"]["type"];
$attachsize = $_FILES["attach"]["size"];
}
$time = date("Y/n/j G:i"); //日時の取得
$ip = getenv("REMOTE_ADDR"); //IPアドレス取得
$host = gethostbyaddr(getenv("REMOTE_ADDR")); //HOST取得
$iphost = ($host . "/" . $ip);
if(($_POST["name"] != "") && ($_POST["email"] != "") && ($_POST["title"] != "") && ($_POST["comment"] != "")&& ($email != "")) { //全てに入力があってメールアドレスが正しい形式なら
$body = "";
$header = "From: $email¥n";
$header .= "X-Mailer: PHP/".phpversion()."¥n";
$header .= "MIME-version: 1.0¥n";
if (file_exists($attach)) { //添付がある場合
$header .= "Content-Type: multipart/mixed;¥n";
$header .= "¥tboundary=¥"$boundary¥"¥n";
$body .= "This is a multi-part message in MIME format.¥n¥n";
$body .= "--$boundary¥n";
$body .= "Content-Type: text/plain; charset=ISO-2022-JP¥n";
$body .= "Content-Transfer-Encoding: 7bit¥n¥n";
}
else{ //添付がない場合
$header .= "Content-Type: text/plain; charset=ISO-2022-JP¥n";
$header .= "Content-Transfer-Encoding: 7bit¥n";
}
$name = mb_convert_encoding($name, "JIS", "UTF-8"); //JISに変換
$body .= $name . "¥n";
$body .= $email . "¥n¥n";
$title = mb_convert_encoding($title, "JIS", "UTF-8"); //JISに変換
$body .= "*" . $title . "¥n¥n";
$comment = mb_convert_encoding($comment, "JIS", "UTF-8"); //JISに変換
$body .= $comment . "¥n¥n";
$body .= $iphost . "¥n";
$body .= $time . "¥n";
$attachname = mb_convert_encoding($attachname, "JIS", "UTF-8"); //JISに変換
$body .= $attachname . "¥n";
$body .= $attachsize . "byte¥n";
if(file_exists($attach)){
$fp = fopen($attach, "r"); //添付ファイルの読み込み
$attachcon = fread($fp, filesize($attach));
fclose($fp);
$attachenco = chunk_split(base64_encode($attachcon)); //エンコードして分割
$body .= "¥n¥n--$boundary¥n";
$body .= "Content-Type: " . $attachtype . ";¥n";
$body .= "¥tname=¥"$attachname¥"¥n";
$body .= "Content-Transfer-Encoding: base64¥n";
$body .= "Content-Disposition: attachment;¥n";
$body .= "¥tfilename=¥"$attachname¥"¥n¥n";
$body .= "$attachenco¥n";
$body .= "--$boundary--";
}
if (mail('hoge@hoge.co.jp', 'p-ho AttachMailForm', $body, $header)) {
print "以下の内容で送信しました<br /><br />¥n";
print "【宛先】PHPな休日管理人(haku)<br />¥n";
print "【件名】p-ho AttachMailForm<br />¥n";
print "【お名前】&nbsp;" . $viewname . "<br />¥n";
print "【E-mail】&nbsp;" . $email . "<br />¥n";
print "【タイトル】&nbsp;" . $viewtitle . "<br />¥n";
print "【コメント】&nbsp;<br />¥n";
print $viewcomment . "<br /><br />¥n";
print $iphost . "<br />¥n";
print $time . "<br />¥n";
print "【添付】&nbsp;<br />¥n";
print $viewattachname . "<br />¥n";
print $attachsize . "byte<br /><br />¥n";
print "※送信完了したメールでも、添付ファイルが(容量制限で)付いて行かない場合があります。<br />¥n";
print "※多重送信防止対策はしていませんので [再読込] はしないでください。<br />¥n";
}
}
else { //入力漏れの場合
print "<b>p-ho 添付 MailForm</b><br />¥n";
print "<font size='2' color='#808080'> ※全ての項目に入力必要</font><br />¥n";
print "<form action='./pmail.php' method='POST' enctype='multipart/form-data'>¥n";
print "お名前<br />¥n";
if ($_POST["name"] != "") {
print "<input name='name' value='" . $name . "'><br />¥n";
}
else {
print "<input name='name'><br />¥n";
}
print "E-mail<br />¥n";
if ($_POST["email"] != "") {
print "<input name='email' value='" . $email . "'><br />¥n";
}
else {
print "<input name='email'><br />¥n";
}
print "タイトル<br />¥n";
if ($_POST["title"] != "") {
print "<input name='title' value='" . $title . "'><br />¥n";
}
else {
print "<input name='title'><br />¥n";
}
print "コメント<br />¥n";
if ($_POST["comment"] != "") {
print "<textarea name='comment'>" . $comment . "</textarea><br />¥n";
}
else {
print "<textarea name='comment'></textarea><br />¥n";
}
print "<font size='2' color='#808080'> ※添付ファイル名は半角英数で<br />※添付容量は1.5MB以内で</font><br />¥n";
print "<input type='file' name='attach'><br />¥n";
print "<input type='submit' value='送信'></form>¥n";
}
?>
</body>
</html>

 

サブウインドウで実行 //実際にはメール送信されません。

この添付メールフォームを こちら からzip形式でダウンロードできるようにしました。 お役立てください。

2014.2.4 last edit

Produced by haku