Fopen, Fread error on attachment script

hi

I have a form in which the “ADD attachment” field is optional.

I m sending this form information to email with file attachment as optional

if i dont upload/ attach any file then i get these below errors

vineet


Warning: fopen() [function.fopen]: Filename cannot be empty

Warning: fread() expects parameter 1 to be resource, boolean given

Warning: fclose() expects parameter 1 to be resource, boolean given

this is the script


<?php

 if(isset ($_POST["send"]))
 {
    $upload_name=$_FILES["upload"]["name"];
    $upload_type=$_FILES["upload"]["type"];
    $upload_size=$_FILES["upload"]["size"];
    $upload_temp=$_FILES["upload"]["tmp_name"];
	$name=$_POST["name"];
    $message=$_POST["msg"];
    $subject = $_POST["subject"];
    $to="me@gmail.com";

    if($message==""||$subject==""||$name=="")
    {
        echo '<font style="font-family:Verdana, Arial; font-size:11px; color:#F3363F; font-weight:bold">Please fill name,subject,message</font>';
    }
    else
    {
    $fp = fopen($upload_temp, "rb");
    $file = fread($fp, $upload_size);
    $file = chunk_split(base64_encode($file));
    $num = md5(time());

        // Attachment headers

    	$headers  .= "Content-Type:".$upload_type." ";
       $headers  .= "name=\\"".$upload_name."\\"r\
";
       $headers  .= "Content-Transfer-Encoding: base64\\r\
";
       $headers  .= "Content-Disposition: attachment; ";
       $headers  .= "filename=\\"".$upload_name."\\"\\r\
\
";
       $headers  .= "".$file."\\r\
";
       $headers  .= "--".$num."--";

    // SEND MAIL
       @mail($to, $subject, $message, $headers);
     fclose($fp);
    echo '<font style="font-family:Verdana, Arial; font-size:11px; color:#333333; font-weight:bold">Mail sent please check inbox and spam both <br /></font>';
 }
 }
?>
<form id="attach" name="attach" method="post" action="<?php echo $_SERVER["PHP_SELF"]; ?>" enctype="multipart/form-data">
Name : <input type="text" name="name" id="name"><br>
Subject : <input type="text" name="subject" id="subject"><br>
Message : <input type="text" name="msg" id="msg"><br>
File Attach : <input type="file" name="upload" id="upload"> (Optional)<br>
               <input type="submit" value="Submit" id="send" name="send">
                </form>

All you need to do is some simple variable tracking to see if the file input has been used, see the below. Also I strongly recommend you steer clear of using the suppressor @ character as you should be catching errors instead of suppressing them.

if (isset($_POST['send'])) {
    $headers = '';
    $name    = $_POST['name'];
    $message = $_POST['msg'];
    $subject = $_POST['subject'];
    $to      = 'me@gmail.com';

    if ($message === '' || $subject === '' || $name === '') { 
        echo '<font style="font-family:Verdana, Arial; font-size:11px; color:#F3363F; font-weight:bold">Please fill name,subject,message</font>';
    } else {
        if (isset($_FILES['upload'])) {
            $upload_name = $_FILES['upload']['name'];
            $upload_type = $_FILES['upload']['type'];
            $upload_size = $_FILES['upload']['size'];
            $upload_temp = $_FILES['upload']['tmp_name'];
            $fp          = fopen($upload_temp, "rb");
            $file        = fread($fp, $upload_size);
            $file        = chunk_split(base64_encode($file));
            $num         = md5(time());

            // Attachment headers
            $headers .= "Content-Type: " . $upload_type . " name=\\"" . $upload_name . "\\"r\
";
            $headers .= "Content-Transfer-Encoding: base64\\r\
";
            $headers .= "Content-Disposition: attachment;";
            $headers .= "filename=\\"" . $upload_name . "\\"\\r\
\
";
            $headers .= "" . $file . "\\r\
";
            $headers .= "--" . $num . "--";

            fclose($fp);
        }

        echo '<font style="font-family:Verdana, Arial;font-size:11px; color:#333333; font-weight:bold">';

        // Send mail
        try {
            mail($to, $subject, $message, $headers);
            echo 'Mail sent please check inbox and spam both';
        } catch(Exception $e) {
            echo 'An error occurred while trying to send the email: ' . $e->getMessage();
        }

        echo '<br /></font>';
    }
}

You can’t do this in PHP, the mail function doesn’t raise an exception, this is like most of the procedural functions in PHP. Instead, @ error suppression should be used combined with the result of the function:


    $success = @mail($to, $subject, $message, $headers);

    if ($success) {
        echo 'Mail sent please check inbox and spam both';
    } else {
        echo 'An error occurred while trying to send the email';
    }

How very true, I’ve been working in C# for too long. In any case though you should never suppress errors as on production servers they should be invisible to users anyway hence on development machines you should see them.

hi Chris

thanks for the reply.

I tried your code but i am getting the same 3 errors again

vineet

Try the following, instead of fopen it uses file_get_contents which should always work.

if (isset($_POST['send'])) {
    $headers = '';
    $name    = $_POST['name'];
    $message = $_POST['msg'];
    $subject = $_POST['subject'];
    $to      = 'me@gmail.com';

    if ($message === '' || $subject === '' || $name === '') { 
        echo '<font style="font-family:Verdana, Arial; font-size:11px; color:#F3363F; font-weight:bold">Please fill name,subject,message</font>';
    } else {
        if (isset($_FILES['upload'])) {
            $upload_name = $_FILES['upload']['name'];
            $upload_type = $_FILES['upload']['type'];
            $upload_size = $_FILES['upload']['size'];
            $upload_temp = $_FILES['upload']['tmp_name'];

            // Get the file contents
            $file = chunk_split(base64_encode(file_get_contents($upload_temp)));
            $num  = md5(uniqid(time()));

            // Attachment headers
            $headers .= "Content-Type: application/octet-stream; name=\\"" . $upload_name . "\\"\\r\
";
            $headers .= "Content-Transfer-Encoding: base64\\r\
";
            $headers .= "Content-Disposition: attachment; filename=\\"" . $upload_name . "\\"\\r\
\\r\
";
            $headers .= $file . "\\r\
";
            $headers .= "--" . $num . "--";
        }

        $email_success = mail($to, $subject, $message, $headers);

        echo '<font style="font-family:Verdana, Arial;font-size:11px; color:#333333; font-weight:bold">';

        if ($email_success) {
            echo 'Mail sent please check inbox and spam both';
        } else {
            echo 'An error occurred while trying to send the email';
        }

        echo '<br /></font>';
    }
}

hi

thanks for the reply.

With your new code, This time i m getting this below error

Warning: file_get_contents() [function.file-get-contents]: Filename cannot be empty

vineet

Ok, try changing the following

if (isset($_FILES['upload'])) {

to

if (isset($_FILES['upload']) && !empty($_FILES['upload']['name'])) {

hi Chris

Thanks for the reply

This solution worked PERFECTLY FINE with both options “fopen” and “file_get_contents”.

But can you suggest me which one is better and which one should i use.

“fopen” OR “file_get_contents”

thanks
vineet

As far as execution is concerned there really isn’t a different in how they operate as they are both stream readers, however in saying that fopen() allows for more control over the stream as you can control how many bytes of data are transferred at any given time whereas file_get_contents() only gives you the ability to receive content for the file you specified.

In my personal opinion file_get_contents() is good for those times when you need to collect content from small files such as 100MB and less compared to fopen() which allows for greater control as I said over the amount of data your pulling in which makes it great for processing large files.