質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.65%

添付機能付きメールフォームの作成

解決済

回答 6

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 2,200

slboy18

score 9

前提・実現したいこと

PHPでメールフォームの機能を
作っています。
添付機能を新たに追加したいのですがなかなか
上手くいきません。
解決策や実装方法などありましたら教えてください。
現在アップロードしたファイルを添付して送信する
という処理を行っているのですが、送信メールに
送信されません。

発生している問題・エラーメッセージ

Content-Type: text/plain; charset="ISO-2022-JP"

Content-Type: image/jpeg; name=""
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=""

こんな感じになります。

該当のソースコード

<form id="testform" method="post" action="mail.php" enctype="multipart/form-data">
<input type="file" name="uploadfile[]"><br>
<input type="file" name="uploadfile[]"><br>
<input type="file" name="uploadfile[]"><br>
</form>
$dir ='img/upload/';
const MAX_SIZE =2048000;

if(! checkPostMaxSize()){
    echo 'ファイルサイズは2MB以下にしてください<br><br>';
}

if(isset($_FILES['uploadfile'])){
    for($i = 0; $i <count($_FILES['uploadfile']['name']); $i++){

        list($result, $ext, $error_msg) = checkFile($i);
        if($result){
            $name = $_FILES['uploadfile']['name'][$i];
            $tmp_name = $_FILES['uploadfile']['tmp_name'][$i];
            $move_to = $dir.$name;
            if(move_uploaded_file($tmp_name,$move_to)){
                echo h($move_to) . '<br>';
                echo '<img src="' . h($move_to). '" alt="アップロードされた画像"><br>';
            }else{
                $error_msg[] = '画像のアップロードに失敗しました';
            }
        }
        $handle = fopen($move_to, 'r');
        $attachFile = fread($handle, filesize($tmp_name));
        fclose($handle);
        $attachEncode = base64_encode($attachFile);
        if(count($error_msg) > 0){
            foreach($error_msg as $msg){
                echo h($msg). '<br>';
            }
        }
        }
    }

function checkFile($i)
{
    $error_msg = array();
    $ext    ='';

    $size        =$_FILES['uploadfile']['size'][$i];
    $error        =$_FILES['uploadfile']['error'][$i];
    $img_type    =$_FILES['uploadfile']['type'][$i];
    $tmp_name    =$_FILES['uploadfile']['tmp_name'][$i];
    if($error != UPLOAD_ERR_OK){
        if($error == UPLOAD_ERR_NO_FILE){
        }elseif ($error == UPLOAD_ERR_INT_SIZE ||
                $error == UPLOAD_ERR_FORM_SIZE){
            $error_msg[] ='ファイルサイズは100KB以下にしてください';
                }else{
                    $error_msg[] = 'アップロードエラーです';
                }
                return array(false, $ext, $error_msg);
        }else{
        if($img_type == 'image/gif'){
            $ext ='gif';
        } elseif ($img_type == 'image/jpeg' || $img_type == 'image/pjpeg'){
            $ext = 'jpg';
        } elseif ($img_type == 'image/png' || $img_type == 'image/x-png'){
            $ext = 'png';
        }

    $finfo = new finfo(FILEINFO_MIME_TYPE);
    $finfoType = $finfo->file($tmp_name);

    if($size == 0){
        $error_msg[] ='ファイルが存在しないか空のファイルです。';
    }elseif ($size > MAX_SIZE){
        $error_msg[] ='ファイルサイズは100KB以下にしてください';
    }elseif ($img_type != $finfoType){
        $error_msg[] ='MIMEタイプが一致しません';
    }elseif ($ext != 'gif' && $ext !='jpg' && $ext != 'png'){
        $error_msg[] ='アップロード可能なファイルはgif、jpg、pngのみです';
    }else{
        return array(true, $ext, $error_msg);
    }
}
    return array(false, $ext, $error_msg);
}

function checkPostMaxSize()
{
    $max_size = ini_get('post_max_size');

    $multiple= 1;
    $unit = substr($max_size, -1);
    if($unit == 'M'){
        $multiple= 1024*1024;
    } elseif ($unit == 'K'){
        $multiple =1024;
    } elseif ($unit == 'G'){
        $multiple =1024*1024*1024;
    }
    $max_size = substr($max_size, 0, strlen($max_size) - 1)* $multiple;

    if ($_SERVER['REQUEST_METHOD'] == 'POST' &&
        $_SERVER['CONTENT_LENGTH'] > $max_size){
            return false;
        }else{
            return true;
        }
}
function adminHeader($userMail,$post_mail,$BccMail,$to){
    $header = '';
    if($userMail == 1 && !empty($post_mail)) {
        $header="From: $post_mail\n";
        if($BccMail != '') {
          $header.="Bcc: $BccMail\n";
        }
        $header.="Reply-To: ".$post_mail."\n";
    }else {
        if($BccMail != '') {
          $header="Bcc: $BccMail\n";
        }
        $header.="Reply-To: ".$to."\n";
    }
        $header.="Content-Type:text/plain;charset=iso-2022-jp\nX-Mailer: PHP/".phpversion();
        return $header;
        $header .= "MIME-Version: 1.0\n";
        $header .= "Content-Type:  multipart/mixed; boundary=\"__PHPRECIPE__\"";
}

function mailToAdmin($arr,$subject,$mailFooterDsp,$mailSignature,$encode,$confirmDsp){
    $adminBody="「".$subject."」フォームから送信されました\n\n";
    $adminBody .="Content-Type: text/plain; charset=\"ISO-2022-JP\"\r\n";
    $adminBody .="\r\n";
    $move_to = mb_encode_mimeheader($move_to, "ISO-2022-JP", "B");
    $adminBody .="Content-Type: image/jpeg; name=\"$name\"\r\n";
    $adminBody .="Content-Transfer-Encoding: base64\r\n";
    $adminBody .="Content-Disposition: attachment; filename=\"$name\"\r\n";
    $adminBody .="\r\n";
    $adminBody .= chunk_split($attachEncode) . "\r\n";
    $adminBody .="===========================\n\n";
    $adminBody.= postToMail($arr);//POSTデータを関数からセット
    $adminBody.="\n===========================\n";
    $adminBody.="送信された日時:".date( "Y/m/d (D) H:i:s", time() )."\n";
    $adminBody.="送信者のIPアドレス:".@$_SERVER["REMOTE_ADDR"]."\n";
    $adminBody.="送信者のホスト名:".getHostByAddr(getenv('REMOTE_ADDR'))."\n";
    if($confirmDsp != 1){
        $adminBody.="問い合わせのページURL:".@$_SERVER['HTTP_REFERER']."\n";
    }else{
        $adminBody.="問い合わせのページURL:".@$arr['httpReferer']."\n";
    }
    if($mailFooterDsp == 1) $adminBody.= $mailSignature;
    return mb_convert_encoding($adminBody,"JIS",$encode);
}

試したこと

課題に対してアプローチしたことを記載してください
一度添付ファイルをサーバーにアップロードして
そこから読みとって添付しようとしましたが
ファイル名まで読み取れず失敗しました。
$filename=$_FILES["uploadfile"]等
もやってみましたができませんでした。

補足情報(言語/FW/ツール等のバージョンなど)

より詳細な情報

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • kei344

    2016/06/23 17:51

    コードはコードブロックで囲んでいただけませんか? ```(バッククオート3つ)で囲み、前後に改行をいれるか、コードを選択して「</>」ボタンを押すとコードブロックになります。

    キャンセル

  • slboy18

    2016/06/23 18:33

    ご指摘ありがとうございます。

    キャンセル

回答 6

checkベストアンサー

+1

$_FILES['uploadfile'] の配列数をカウントで取得してforでループします。

$_FILES['uploadfile'][カウンター変数]['tmp_name']
で取得でしょうかね

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/24 10:10

    if(isset($_FILES['uploadfile'])){
    for($i = 0; $i < count($_FILES['uploadfile']['name']); $i++){
    $name = $_FILES['uploadfile']['name'][$i];
    $filename = $_FILES['uploadfile']['tmp_name'][$i];
    }
    foreach($filename as $key => $value){
    $handle[$key] = fopen($value, 'r');
    $attachFile =fread($handle, filesize($filename));
    fclose($handle);
    $attachEncode = base64_encode($attachFile);
    }
    }
    修正おねがいいします。

    キャンセル

  • 2016/06/24 11:27

    $fileMoveDir = "../dir/tmp/"; // ファイル格納ディレクトリ(例)
    $moveFileName[0] = "test0.xls";
    $moveFileName[1] = "test1.xls";
    $moveFileName[2] = "test2.xls";
    if(isset($_FILES['uploadfile'])){
    for($i = 0; $i < count($_FILES['uploadfile']); $i++){
    $name = $_FILES['uploadfile'][$i]['name']; // 配列[i] の ファイル名
    $filename = $_FILES['uploadfile'][$i]['tmp_name']; // 配列[i] の テンポラリファイル名

    move_uploaded_file( $_FILES["uploadfile"]["tmp_name"], $fileMoveDir.$moveFileName[$i]); // アップロードテンポラリファイル => ファイル格納パスへコピー

    $handle[$key] = fopen($fileMoveDir.$moveFileName[$i], 'r'); // ファイルオープン[読み取り専用]
    $attachFile = fread($handle, filesize($filename)); // ファイルサイズを指定
    fclose($handle); // ファイルクローズ
    $attachEncode = base64_encode($attachFile); // エンコーディング
    }
    }

    キャンセル

  • 2016/06/24 11:28

    修正 : [$key]は要りません。

    $handle = fopen($fileMoveDir.$moveFileName[$i], 'r'); // ファイルオープン[読み取り専用]
    ですかね

    キャンセル

  • 2016/06/27 09:37

    返信が遅くなってすみません。test0.xlsのところはこの名前で格納されるという感じですか?無知ですみません

    キャンセル

+1

$_FILES('uploadfile')が配列になっているので、foreachで回す。

$filename = $_FILES('uploadfile');
foreach($filename as $key => $value){
  $handle[$key] = fopen($value, 'r');
}


配列$handleにファイルポインタが入る。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/23 18:12

    yuyaさん回答ありがとうございます。
    今度は Invalid argument supplied for foreach()がでてしまいました。

    キャンセル

  • 2016/06/24 11:08

    $POST_('uploadfile')が空の場合そうなってしまいますね。
    foreach($filename as $key => $value)

    foreach((array)$filename as $key => $value)
    これで$filenameがNULLでもエラーでなくて済みそうです。

    キャンセル

+1

$filename = $_POST['uploadfile'];


$POST_ ではなく $_POST ではありませんか。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/23 18:32

    ご指摘ありがとうございます。$filename = $_POST['uploadfile'];に修正しましたが、やはり Invalid argument supplied for foreach() inがでてしまいます。

    キャンセル

  • 2016/06/23 18:45 編集

    ああ、すみません。
    思い出しました。

    $_POST でもなくて $_FILES['uploadfile'] です。

    キャンセル

+1

phpのファイルアップロードの情報自体は$_FILESに入るのはずなので、まずはvar_dump($_FILES)でリクエスト時にどういう情報がきているかを確認してはどうでしょう。

$_POSTもhtml側で'inputval[]' で渡すと、$_POST['inputval'][0]でアクセスできるので、
同じように$_FILES['uploadfile'][0]で一つ目のアップロードファイルにアクセスできるかもしれないです。

以下、「もしかしたらこんな感じで動くんじゃないかな」というコードを載せるだけ載せてみます

foreach ($_FILES['uploadfile'] as $_file) {
    $handle = fopen($_file['tmp_name'], 'r');
    $attachFile = fread($handle, $_file['size']); 
    fclose($handle); 
    $attachEncode = base64_encode($attachFile);

    // 略
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

$filename = $_POST['uploadfile']; ポストの書き方あってると思います
foreach((array)$filename as $key => $value){
$handle[$key] = fopen($value, 'r');
このなかで、fread,fwrite,fclose
もやらないといけないと思いますよ!
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/23 18:55

    ```php
    $filename = $_POST['uploadfile'];

    foreach($filename as $key => $value){
    $handle[$key] = fopen($value, 'r');
    $attachFile =fread($handle, filesize($filename));
    fclose($handle);
    $attachEncode = base64_encode($attachFile);
    }
    ```
    これであってますか?

    キャンセル

  • 2016/06/23 19:00 編集

    $_POST['uploadfile'] ✖︎
    すいません。
    $_FILE['uploadfile'] が正解です。

    キャンセル

  • 2016/06/23 19:12

    $_FILES['uploadfile']に直しました。
    エラーが増えました,,,

    キャンセル

  • 2016/06/23 21:31

    $_FILES['uploadfile'] の配列数をカウントで取得してforでループします。

    $_FILES['uploadfile'][カウンター変数]['tmp_name']
    で取得でしょうかね

    キャンセル

+1

PHPMailer を利用したラッパークラスの例

require_once('PHPMailer/class.phpmailer.php');

/**
 * Mail.class.php
 */
class Mail
{

    /**
     * メールを送信する
     * @param string $strRecipient 宛先
     * @param string $strSubject 題名
     * @param string $strBody 本文
     * @param string $binAttachment 添付ファイルへのパス
     * @throws \Exception
     */
    public static function send($strRecipient, $strSubject, $strBody, $binAttachment = null)
    {
        mb_language('japanese');
        mb_internal_encoding('utf-8');

        $from = 'sender@example.com';
        $fromname = '送信者名';

        $mail = new \PHPMailer();

        $mail->IsSMTP();
        $mail->SMTPAuth = TRUE;
        $mail->Host = 'ホスト名';
        $mail->Port = 'ポート';
        $mail->Username = 'SMTPユーザー名';
        $mail->Password = 'SMTPパスワード';

        $mail->CharSet = "iso-2022-jp";
        $mail->Encoding = "7bit";

        $mail->AddAddress($strRecipient);
        $mail->From = $from;
        $mail->FromName = mb_encode_mimeheader(
            mb_convert_encoding(
                $fromname
                , "JIS"
                , 'utf-8'
            )
        );
        $mail->Subject = mb_encode_mimeheader($strSubject);
        $mail->Body = mb_convert_encoding(
            $strBody
            , "JIS"
            , 'utf-8'
        );

        if (!is_null($binAttachment) && file_exists($binAttachment)) {
            $mail->AddAttachment($binAttachment);
        }

        if (!$mail->Send()) {
            throw new \Exception($mail->ErrorInfo);
        }
    }

}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/24 10:14

    PHPMailerを使った場合添付機能だけ追加する場合を記述すればできるということでしょうか?
    if (!is_null($binAttachment) && file_exists($binAttachment)) {
    $mail->AddAttachment($binAttachment);
    }

    if (!$mail->Send()) {
    throw new \Exception($mail->ErrorInfo);

    キャンセル

  • 2016/06/24 14:16

    このソースを丸ごと使えば利用できますよ。

    キャンセル

  • 2016/06/27 09:27

    もともとある機能に追加するという形での使用は可能ですか?

    キャンセル

  • 2016/06/27 11:57

    元々ある機能がどんなものなのか私は知りませんので、判断しかねます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.65%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる