Ownedmedia ウェブ制作に役立つコンテンツを発信中!

PHP 2020.03.05

PHPでフォームからのファイルアップロードとメールでの添付送信を実装する

Tags: ,

今回はPHPでフォームからローカルのファイルをメールで送信できる機能を実装してみたいと思います。お問い合わせフォームなどでもファイル添付の機能が備わっているケースもありますね。お問い合わせフォームについては過去の記事でも紹介していますのでご参考に。

(参考記事)
PHPで自動返信メール機能付きのコンタクトフォームを作成する(入力画面)
PHPで自動返信メール機能付きのコンタクトフォームを作成する(確認画面)
PHPで自動返信メール機能付きのコンタクトフォームを作成する(送信画面)
PHPでサーバーサイドのフォームバリデーションを実装する

 

フォームからファイルを添付したメールを送信するには、一度サーバー上にファイルをアップロードする必要があるようです。ですので、ファイルのアップロード機能も合わせて実装することになります。今回は上記の過去記事で紹介しているメールフォームに合わせて、入力画面、確認画面、完了画面の3ページ遷移する形で作成していきます。なお、実用においてはこれ以外にも十分なセキュリティ対策が必要となるので、あらかじめご注意ください。

 

今回まとめているファイル・フォルダの構成は以下のようになります。入力・確認・送信画面用のphpファイルと、「attachment」と名付けているアップロード先フォルダをメールフォーム用のphpプログラムと同階層に用意しておきます。

┳ form.php
┣ check.php
┣ thanks.php
┗ attachment

 

 

添付ファイルの選択を行う入力画面

最初に入力画面からのコードを見ていきます。今回はわかりやすいように必要最低限の表記にしています。まずはformタグを用意し、その中にファイルを使うinput要素を設置します。合わせて送信ボタンも並べておきます。

【form.php】※一部抜粋

<form method="post" action="./check.php" enctype="multipart/form-data">
 <input type="file" name="input_file" value="">
 <input type="submit" value="確認画面へ">
</form>

 

この時に注意するのはformタグの中に「enctype属性」を忘れないようにします。値には「multipart/form-data」を指定することでファイルの送信ができるようになります。

 

バリデーションとサーバーへのアップロードを行う確認画面

続いて確認画面です。入力画面でサブミットされるとこのページが表示されます。それではコードを見ていきます。まずは処理部分のソースコードです、最初にセットされたファイルのバリデーションを行います。ここでチェックするのは「ファイルサイズの容量が制限内か?」「ファイルの形式が問題ないか?」の2つをチェックしていきます。

 

入力画面から確認画面へ送信されたファイルの情報は「$_FILES」というスーパーグローバル変数を参照することで確認できるようになります。後述のバリデーションやファイルアップロードもこの中に含まれている情報を使う形となります。

 

まずはバリデーションの関数を用意していきます。1つめは添付ファイルのサイズをチェックします。ファイルのサイズを参照し、指定した値より低いかをtrueもしくはfalseで返すようにしておきます。2つめは添付ファイルの形式をチェックします。許可するファイル形式のMINEタイプファイルの形式をMIMEタイプで指定し、配列としてまとめておきます。そしてファイルのタイプを参照し「in_array()」で配列内に指定したファイル形式が含まれるかを見ていきます。これらの関数には引数に対象となるファイルが入れるようにしておきます。

【check.php(処理部分)】※一部抜粋

<?php
 //添付ファイルバリデーション 
 function fileValidatorSize($data) {
  //ファイルサイズの上限をMB単位で指定
  $allowMaxSize = 2;
  if($data['size'] < $allowMaxSize * 1000000) {
   return false;
  } else {
   return true;
  }
 }
 function fileValidatorType($data) {
  //許可するファイルのMIMEタイプを指定
  $allowFileType = array(
   'image/jpeg',
   'image/png',
   'image/gif',
   'text/plain',
   'text/csv',
   'application/pdf',
   'application/zip'
  );
  if(in_array($data['type'], $allowFileType)) {
   return false;
  } else {
   return true;
  }
 }
 $isErrorFileSize = fileValidatorSize($_FILES['input_file']);
 $isErrorFileType = fileValidatorType($_FILES['input_file']);

 //添付ファイルアップロード
 $fileTempName = $_FILES['input_file']['tmp_name'];
 $fileName = $_FILES['input_file']['name'];
 $attachedFile = "";
 $fileType = "";
 if(!$isErrorFileSize && !$isErrorFileType) {
  if(!empty($fileTempName)) {
   $isUploaded = move_uploaded_file($fileTempName, 'attachment/'.$fileName);
   if($isUploaded) {
    $attachedFile = $fileName;
    if(strpos($_FILES['input_file']['type'], 'image') !== false) {
     $fileType = 'image';
    } else {
     $fileType = 'other';
   }
    $uploadError = false;
   } else {
    $uploadError = true;
   } 
  }
 } else {
  $uploadError = true;
 }

 //SESSIONへ受け渡し
 if(!$uploadError) {
  $_SESSION['input_file'] = $attachedFile;
 }
?>

 

後半はファイルのアップロードの処理が書かれています。ファイルのアップロードは「move_uploaded_file()」という関数で実装できます。第一引数にはファイルのtmp_nameを指定します、そして第二引数にはファイルアップロード先のディレクトリを指定します。また上記ではアップロード完了後にファイルタイプが画像か、画像以外かを判断できるようにしています。合わせて、送信失敗した場合には、送信失敗を示す状態を値で出力しておきます。最後に$_SESSIONに値を入れられるようにしておきます。実際にサーバー上にあるアップロード用フォルダを確認してみると、セットしたファイルがアップロードされているのが確認できます。

 

そして、入力内容確認の部分では添付ファイルの情報を表示させていきます。ここでは添付ファイルの形式が画像だった場合にプレビューできるようimg要素を用意しています。そしてイメージ要素のsrc属性にアップロード先を指定することで、アップロード完了後にページ上でプレビュー画像として確認できるようになります。

 

【check.php(表示部分)】※一部抜粋

<form method="post" action="./thanks.php">
 <?php if(!$uploadError && $fileType === 'image'): ?>
  <img src="./attachment/<?php echo $attachedFile; ?>" alt="<?php echo $attachedFile; ?>">
  <span><?php echo $attachedFile; ?></span>
 <?php else: ?>
  <span><?php echo $attachedFile; ?></span>
 <?php endif; ?>
 <input type="submit" value="送信する">
</form>

 

実際に画面上でこのように表示されます。プレビュー画像などの添付ファイルの情報はアップロードの結果で表示が変えられるようにしておくと良いですね。

 

 

メールへのファイル添付とメール送信を行う完了画面

最後の完了画面ではファイルをメールへ添付する処理などを書いていきます。コードを見ていくとまずはメール送信設定に関する記述が並びます。この時にメールヘッダ設定でContent-Typeの項目が通常のメールフォームと異なるので注意します。

 

その次には自動返信メールなどの内容を指定していきます。ファイルのメール添付は、基本的にbase64のエンコードを行い、本文内に追記する形で添付されます。なので、この部分に添付する処理も含まれることになります。変数に格納された本文に続けて「chunk_split(base64_encode(file_get_contents());」とあり、ここで添付ファイルが指定されています。

【thanks.php(処理部分)】※一部抜粋

<?php
 //セッション開始
 session_start();

 //メール差出人
 $sender = "メール差出人";

 //メール送信元
 $mailFrom = "info@example.com";

 //メール送信先
 $mailTo = "user@example.com";

 //メール返信先
 $replyTo = "info@example.com";

 //管理者メールアドレス
 $adminEmail = "info@example.com";

 //メールヘッダ設定
 $addHeader = "MIME-Version: 1.0n";
 $addHeader .= "Content-Type: multipart/mixed; boundary="__BOUNDARY__"n";
 $addHeader .="From:".mb_encode_mimeheader($sender)."<".$mailFrom.">n";
 $addHeader .= "Reply-to: ".$replyTo."n";
 $addHeader .= "X-Mailer: PHP/". phpversion();

 // 迷惑メール対策
 $addOption = '-f'.$mailFrom;

 //データの変数化
 $file = htmlspecialchars($_SESSION['input_file'], ENT_QUOTES, 'UTF-8');

 //自動返信メール本文
 $messageUser = "--__BOUNDARY__n";
 $messageUser .= "Content-Type: text/plain; charset="ISO-2022-JP"nn";
 $messageUser .= <<< EOD
下記の添付ファイルを送信しました

----------------------------------------------------

【添付ファイル】{$file}

----------------------------------------------------

EOD;
 $messageUser .= "--__BOUNDARY__n";

 //管理者確認用メール本文
 $messageAdmin = "--__BOUNDARY__n";
 $messageAdmin .= "Content-Type: text/plain; charset="ISO-2022-JP"nn";
 $messageAdmin .= <<< EOD
ウェブサイトより下記の内容でファイルが送信されました

----------------------------------------------------

【添付ファイル】{$file}

----------------------------------------------------

EOD;
 $messageAdmin .= "--__BOUNDARY__n";

 //メール共通送信設定
 mb_language("ja");
 mb_internal_encoding("UTF-8");

 //ファイルデータ添付
 if(!empty($_SESSION['input_file'])) { 
  $messageUser .= "Content-Type: application/octet-stream; name="{$file}"n"; 
  $messageUser .= "Content-Disposition: attachment; filename="{$file}"n";
  $messageUser .= "Content-Transfer-Encoding: base64n";
  $messageUser .= "n";
  $messageUser .= chunk_split(base64_encode(file_get_contents('attachment/'.$file)));
  $messageUser .= "--__BOUNDARY__n";

  $messageAdmin .= "Content-Type: application/octet-stream; name="{$file}"n"; 
  $messageAdmin .= "Content-Disposition: attachment; filename="{$file}"n";
  $messageAdmin .= "Content-Transfer-Encoding: base64n";
  $messageAdmin .= "n";
  $messageAdmin .= chunk_split(base64_encode(file_get_contents('attachment/'.$file)));
  $messageAdmin .= "--__BOUNDARY__n";
 }

 if(!empty($mailTo)) {
  //自動返信メール送信設定
  mb_send_mail($mailTo,"ファイルを送信しました",$messageUser,$addHeader,$addOption);
  // 管理者確認用メール送信設定
  mb_send_mail($adminEmail,"ファイルを受信しました",$messageAdmin,$addHeader,$addOption); 
  $isSend = true;
 } else {
  $isSend = false;
 }

 //セッション終了
 session_destroy();
?>

 

あとは「mb_send_mail()」で本文と一緒にメールで送信するとファイルが添付された状態でメールが送信されます。この時に送信結果のステータスも出力できるようにしておきます。そして結果表示に使うHTML側では送信結果に合わせて表示するメッセージを切り替えられるようにします。

【thanks.php(結果表示部分)】※一部抜粋

<h1>ファイルデータ送信完了</h1>
<?php if($isSend): ?>
 <p>ファイルがフォームより送信されました。
 </p>
<?php else: ?>
 <p>送信エラー:フォームからの送信に失敗しました。お手数ですが再度お試しください。
 </p>
<?php endif; ?>

 

これで実際に送信されたメールを確認すると、問題なくファイルが添付されているのが確認できました。

 


 

今回はフォームでのファイルアップロードとメール添付の機能を実装してみました。お問い合わせ用のフォームなどでもファイルが添付できるようになるとユーザビリティも向上し、親切なフォームになります。過去記事でも紹介しているメールフォームと併用すると、ファイル添付機能がついたコンタクトフォームが完成しますので、ぜひ試してみてはいかがでしょうか?

 

(関連記事)
PHPで自動返信メール機能付きのコンタクトフォームを作成する(入力画面)
PHPで自動返信メール機能付きのコンタクトフォームを作成する(確認画面)
PHPで自動返信メール機能付きのコンタクトフォームを作成する(送信画面)
PHPでサーバーサイドのフォームバリデーションを実装する

 

(参考にさせて頂いたサイト)
アップロードしたファイルをメールに添付する

この記事を書いた人

オガワ シンヤ

DesignSupply.代表 / ディレクター・ウェブデザイナー・フロントエンドエンジニアをやっています。「ウェブとデザインでヒト・モノ・サービスを繋げ新しい価値を生み出す」をコンセプトに日々奮闘中!制作中はチョコレートが欠かせない三十路Webクリエイター。

  • Twitter

コメントフォーム

記事に関するご質問やご意見などありましたら下記のコメントフォームよりお気軽に投稿ください。なおメールアドレスは公開されませんのでご安心ください。

内容に問題なければ、お名前・ハンドルネームとメールアドレスを入力いただき、下記の「コメントを送信」ボタンを押してください。

CAPTCHA


この記事もよく読まれています

Scroll to Top
ご質問・ご相談はありませんか ?