Hi everyone, I'm totally new to PHP and I am trying to create a script that allows users to upload a picture which will then be emailed to me along with their details. When debugging, I keep receiving the message Parse error: syntax error, unexpected $end in C:\Users\Admin\Web\php-form-action.php on line 85.

Any help would be greatly appreciated.
Thanks in advance!

<?php 

//Settings 
$max_allowed_file_size = 5000; // size in KB 
$allowed_extensions = array("jpg", "jpeg", "gif", "bmp");
$upload_folder = './uploads/'; 
$your_email = 'myemailaddress';//
$errors ='';

if(isset($_POST['submit']))
{
	//Get the uploaded file information
	$name_of_uploaded_file =  basename($_FILES['uploaded_file']['name']);
	
	//get the file extension of the file
	$type_of_uploaded_file = substr($name_of_uploaded_file, 
							strrpos($name_of_uploaded_file, '.') + 1);
	
	$size_of_uploaded_file = $_FILES["uploaded_file"]["size"]/1024;
	
	///------------Do Validations-------------
	if(empty($_POST['name'])||empty($_POST['email']))
	{
		$errors .= "\n Name and Email are required fields. ";	
	}
	if(IsInjected($visitor_email))
	{
		$errors .= "\n Bad email value!";
	}
	
	if($size_of_uploaded_file > $max_allowed_file_size ) 
	{
		$errors .= "\n Size of file should be less than $max_allowed_file_size";
	}
	
	//------ Validate the file extension -----
	$allowed_ext = false;
	for($i=0; $i<sizeof($allowed_extensions); $i++) 
	{ 
		if(strcasecmp($allowed_extensions[$i],$type_of_uploaded_file) == 0)
		{
			$allowed_ext = true;		
		}
	}
	
	if(!$allowed_ext)
	{
		$errors .= "\n The uploaded file is not supported file type. ".
		" Only the following file types are supported: ".implode(',',$allowed_extensions);
	}
	
	//send the email 
	if(empty($errors))
	{
		//copy the temp. uploaded file to uploads folder
		$path_of_uploaded_file = $upload_folder . $name_of_uploaded_file;
		$tmp_path = $_FILES["uploaded_file"]["tmp_name"];
		
		if(is_uploaded_file($tmp_path))
		{
		    if(!copy($tmp_path,$path_of_uploaded_file))
		    {
		    	$errors .= '\n error while copying the uploaded file';
		    }
		}
$to = 'myemailaddress' ;
$subject = 'Subject' ;

$name = $_POST['name'];
$email = $_POST['email'];
$message = $_POST['message'];

$headers = 'From: ' . $_POST [ "from" ] . PHP_EOL ;

$totalmessage = "
		Name:		$name  \n
		Email:		$email  \n
		Message:	$message \n
		Uploaded File:  $_FILES\n";

mail ( $to , $subject , $totalmessage , $headers );
header('location: thankyou.htm');

?>

The opening bracket on line 54 is missing a closing bracket somewhere.

Thanks for your reply, much appreciated. Tried adding another closing bracket after the closing bracket on 65, but I'm still receiving the error, albeit on line 86 rather than 85. Am I placing the closing bracket in the right place? Any ideas?

the opening bracket from line 10, is also missing a closing bracket. along with the one from line 54 as pritaeas pointed out. so you need to add in the closing bracket for both of those statements.

commented: yes +6

Thanks for pointing out the missing brackets. I've ammended the code:

<?php 

//Settings 
$max_allowed_file_size = 5000; // size in KB 
$allowed_extensions = array("jpg", "jpeg", "gif", "bmp");
$upload_folder = './uploads/'; //<-- this folder must be writeable by the script
$your_email = 'myemailaddress';//

$errors ='';

if(isset($_POST['submit']))
{
	//Get the uploaded file information
	$name_of_uploaded_file =  basename($_FILES['uploaded_file']['name']);
	
	//get the file extension of the file
	$type_of_uploaded_file = substr($name_of_uploaded_file, 
							strrpos($name_of_uploaded_file, '.') + 1);
	
	$size_of_uploaded_file = $_FILES["uploaded_file"]["size"]/1024;
	
	///------------Do Validations-------------
	if(empty($_POST['name'])||empty($_POST['email']))
	{
		$errors .= "\n Name and Email are required fields. ";	
	}
	if(IsInjected($visitor_email))
	{
		$errors .= "\n Bad email value!";
	}
	
	if($size_of_uploaded_file > $max_allowed_file_size ) 
	{
		$errors .= "\n Size of file should be less than $max_allowed_file_size";
	}
	
	//------ Validate the file extension -----
	$allowed_ext = false;
	for($i=0; $i<sizeof($allowed_extensions); $i++) 
	{ 
		if(strcasecmp($allowed_extensions[$i],$type_of_uploaded_file) == 0)
		{
			$allowed_ext = true;		
		}
	}
	
	if(!$allowed_ext)
	{
		$errors .= "\n The uploaded file is not supported file type. ".
		" Only the following file types are supported: ".implode(',',$allowed_extensions);
	}
	
	//send the email 
	if(empty($errors))
	{
		//copy the temp. uploaded file to uploads folder
		$path_of_uploaded_file = $upload_folder . $name_of_uploaded_file;
		$tmp_path = $_FILES["uploaded_file"]["tmp_name"];       
    
		
		if(is_uploaded_file($tmp_path))
		{
		    if(!copy($tmp_path,$path_of_uploaded_file))
		    {
		    	$errors .= '\n error while copying the uploaded file';
		    }
		}
    }
}
$to = 'myemailaddress' ;
$subject = 'Subject' ;

$name = $_POST['name'];
$email = $_POST['email'];
$message = $_POST['message'];

$headers = 'From: ' . $_POST [ "from" ] . PHP_EOL ;

$totalmessage = "
		Name:		$name  \n
		Email:		$email  \n
		Message:	$message \n
		Uploaded File:  $_FILES\n";

mail ( $to , $subject , $totalmessage , $headers );
header('location: thankyou.htm');

?>

I'm no longer receiving an error, and I am receiving an email with the user text input, but instead of the uploaded file it just says "Array".

Any ideas on why the uploaded file isn't being attached?

Thanks!

That's because $_FILES is an array. To see the content of an array in your email, you would need to do something like:

$uploadedFileDetails = var_export($_FILES,true);
$totalmessage = "
		Name:		$name  \n
		Email:		$email  \n
		Message:	$message \n
		Uploaded File:  $uploadedFileDetails\n";

To get the actual uploaded file into the email, you would have to attach it to the email as an attachment, or encode it to be included in the email's body, or save it somewhere on your web server and include a link to it in the email.

Have a look at move_uploaded_file() in the manual. You may also find SwiftMailer helpful : http://swiftmailer.org/

EDIT- Sorry Nettsite, I didn't notice the last part of your message. I'll have a read up on that. Thanks!
________________________________________________________________________________________________________________-

Ammended the last part to look like:

$headers = 'From: ' . $_POST [ "from" ] . PHP_EOL ;
$uploadedFileDetails = var_export($_FILES,true);

$totalmessage = "
		Name:		$name  \n
		Email:		$email  \n
		Message:	$message \n
		Uploaded File:  $uploadedFileDetails\n";

mail ( $to , $subject , $totalmessage , $headers );
header('location: thankyou.htm');

?>

And I now receive:

Uploaded File: array('uploaded_file'=>
array(
'name'=>'testimage.jpg',
'type'=>'image/jpeg',
'tmp_name'=>'D:\\Temp\\phpE511.tmp',
'error'=>0,
'size'=>136259,
),
)

This whole thing baffles me- am I passing the image wrong, or?
Thanks for your help!

'This whole thing baffles me- am I passing the image wrong, or?',
no, as nettsite said, $_FILES is an array of data not the actual file itself.
at this point (sending the email) in your code the actual location of your file is being stored in this variable: $path_of_uploaded_file; which should look something like /uploads/name_of_file.jpg
it isn't exactly easy but also is not hard, but you need to 'read' the file and attach it to your email, another class to look at is PHPMailer
http://code.google.com/a/apache-extras.org/p/phpmailer/downloads/detail?name=PHPMailer_5.2.0.zip&can=2&q=
(not used by me, but found when trying to come up with an answer to your question)
and lastly, here is an example of what you would need to do if you do not use a fore-mentioned class and want to do it yourself.
/* Example Code retrieved from the web -- untested, for a word doc not an image */
$mail_boundary = md5(uniqid(time()));
$mail_headers = "MIME-Version: 1.0\r\n";
$mail_headers .= "Content-type: multipart/mixed;boundary=\"$mail_boundary \"";
$mail_headers .= "\r\n\r\n";
$mail_headers .= "This is a multi-part message in MIME format.";

$mail_headers .= "\r\n\r\n";
$userfile = "./myfile.doc";//***** this is where u use $path_of_uploaded_file
$fp = fopen($userfile, "r"); // open the file
$file = fread($fp, filesize($userfile)); // read the file

$file = chunk_split(base64_encode($file)); // splits file so it fits in mail

$mail_body = "--$mail_boundary\n";
$mail_body .= "Content-type: text/plain; charset=euc-kr\r\n"; // this may mess u up
$mail_body .= "Content-transfer-encoding: 8bit\r\n\r\n"; // not sure about this
$mail_body .= " Here goes the project file.\r\n";
$mail_body .= "--$mail_boundary\r\n";
$filename = basename($userfile);

$mail_body .= "Content-type: application/msword; name=$filename\r\n";
// check your content type, if it is an image u need to use a different content type!
$mail_body .= "Content-transfer-encoding:base64\r\n\r\n";
$mail_body .= $file. "\r\n\r\n";

$mail_body .= " --$mail_boundary--";

mail($mail_to, $mail_subject, $mail_body, $mail_headers);

Thanks ddymacek, much appreciated. I've tried to implement what you've said so I now have:

<?php 

//Settings 
$max_allowed_file_size = 5000; // size in KB 
$allowed_extensions = array("jpg", "jpeg", "gif", "bmp");
$upload_folder = '/uploads/'; //<-- this folder must be writeable by the script
$your_email = 'my email address';//<<--  update this to your email address

$errors ='';

if(isset($_POST['submit']))
{
    //Get the uploaded file information
    $name_of_uploaded_file =  basename($_FILES['uploaded_file']['name']);
    
    //get the file extension of the file
    $type_of_uploaded_file = substr($name_of_uploaded_file, 
                            strrpos($name_of_uploaded_file, '.') + 1);
    
    $size_of_uploaded_file = $_FILES["uploaded_file"]["size"]/1024;
    
    ///------------Do Validations-------------
    if(empty($_POST['name'])||empty($_POST['email']))
    {
        $errors .= "\n Name and Email are required fields. ";    
    }
    if(IsInjected($visitor_email))
    {
        $errors .= "\n Bad email value!";
    }
    
    if($size_of_uploaded_file > $max_allowed_file_size ) 
    {
        $errors .= "\n Size of file should be less than $max_allowed_file_size";
    }
    
    //------ Validate the file extension -----
    $allowed_ext = false;
    for($i=0; $i<sizeof($allowed_extensions); $i++) 
    { 
        if(strcasecmp($allowed_extensions[$i],$type_of_uploaded_file) == 0)
        {
            $allowed_ext = true;        
        }
    }
    
    if(!$allowed_ext)
    {
        $errors .= "\n The uploaded file is not supported file type. ".
        " Only the following file types are supported: ".implode(',',$allowed_extensions);
    }
    
    //send the email 
    if(empty($errors))
    {
        //copy the temp. uploaded file to uploads folder
        $path_of_uploaded_file = $upload_folder . $name_of_uploaded_file;
        $tmp_path = $_FILES["uploaded_file"]["tmp_name"];       
    
        
        if(is_uploaded_file($tmp_path))
        {
            if(!copy($tmp_path,$path_of_uploaded_file))
            {
                $errors .= '\n error while copying the uploaded file';
            }
        }
    }
}

$to = 'my email address' ;
$subject = 'Photo Upload' ;

$name = $_POST['name'];
$email = $_POST['email'];
$message = $_POST['message'];

$headers = 'From: ' . $_POST [ "from" ] . PHP_EOL ;
        
        $mail_boundary = md5(uniqid(time()));
$mail_headers = "MIME-Version: 1.0\r\n";
$mail_headers .= "Content-type: multipart/mixed;boundary=\"$mail_boundary \"";
$mail_headers .= "\r\n\r\n";
$mail_headers .= "This is a multi-part message in MIME format.";

$mail_headers .= "\r\n\r\n";
$userfile = "$path_of_uploaded_file";//***** this is where u use $path_of_uploaded_file
$fp = fopen($userfile, "r"); // open the file
$file = fread($fp, filesize($userfile)); // read the file

$file = chunk_split(base64_encode($file)); // splits file so it fits in mail

$mail_body = "--$mail_boundary\n";
$mail_body .= "Content-type: text/plain; charset=euc-kr\r\n"; // this may mess u up
$mail_body .= "Content-transfer-encoding: 8bit\r\n\r\n"; // not sure about this
$mail_body .= " Here goes the project file.\r\n";
$mail_body .= "--$mail_boundary\r\n";
$filename = basename($userfile);

$mail_body .= "Content-type: image/jpeg; name=$name_of_uploaded_file\r\n";
// check your content type, if it is an image u need to use a different content type!
$mail_body .= "Content-transfer-encoding:base64\r\n\r\n";
$mail_body .= $file. "\r\n\r\n";
$mail_body .= " --$mail_boundary--";

$totalmessage = "
        Name:        $name  \n
        Email:        $email  \n
        Message:    $message \n";

mail($to, $subject, $totalmessage, $mail_body, $headers); 
header('location: thankyou.htm');

?>

The script takes a while, then I'm shown the thank you page, but I'm not receiving an email, so I've obviously down something wrong somewhere along the line.

Any suggestions greatly appreciated

You are not handling the upload very well. Try (untested, just typed it here):

// Check if there is somewhere to store the uploaded file:
if (!is_dir("uploads")) {
  if (!mkdir("uploads")) {
    exit("Cannot create uploads folder");
  }
}
// Name the file using the folder and it's original name:
$uploaded_file = "uploads/{$_FILES['uploaded_file']['name']}";
// Place the uploaded file in the uploads folder:
if (!move_uploaded_file($_FILES['uploaded_file']['tmp_name'], $uploaded_file) {
  exit("Error uploading file"); // You could improve on this, check the manual.
}

You can now do stuff with "$uploaded_file" like attach or embed it into an email. Plenty of example code on http://swiftmailer.org/docs/introduction.html.

Thanks everyone for the replies. I decided to start from scratch and simply the whole script, and work up from there. So far I have this:

<?php
  // Where the file is going to be placed 
$target_path = "uploads/";

/* Add the original filename to our target path.  
Result is "/uploads/filename.extension" */
$target_path = $target_path . basename( $_FILES['uploaded_file']['name']); 

if(move_uploaded_file($_FILES['uploaded_file']['tmp_name'], $target_path)) {
    echo "The file ".  basename( $_FILES['uploaded_file']['name']). 
    " has been uploaded";
} else{
    echo "There was an error uploading the file, please try again!";
}
//define the receiver of the email
$to = 'myemailaddress';
//define the subject of the email
$subject = 'File Upload Test';
//create a boundary string. It must be unique
//so we use the MD5 algorithm to generate a random hash
$usermessage = $_POST['message'];
$random_hash = md5(date('r', time()));
//define the headers we want passed. Note that they are separated with \r\n
$headers = 'From: ' . $_POST [ "from" ] . PHP_EOL ;
//add boundary string and mime type specification
$headers .= "\r\nContent-Type: multipart/mixed; boundary=\"PHP-mixed-".$random_hash."\"";
//read the atachment file contents into a string,
//encode it with MIME base64,
//and split it into smaller chunks
$attachment = chunk_split(base64_encode(file_get_contents($target_path)));
//define the body of the message.
ob_start(); //Turn on output buffering
?>
--PHP-mixed-<?php echo $random_hash; ?> 
Content-Type: multipart/alternative; boundary="PHP-alt-<?php echo $random_hash; ?>"

--PHP-alt-<?php echo $random_hash; ?>--

--PHP-mixed-<?php echo $random_hash; ?> 
Content-Type: application/zip; name="attachment.zip" 
Content-Transfer-Encoding: base64 
Content-Disposition: attachment 

<?php echo $attachment; ?>
--PHP-mixed-<?php echo $random_hash; ?>--

<?php
//copy current buffer contents into $message variable and delete current output buffer
$message = ob_get_clean();
//send the email
$mail_sent = @mail( $to, $subject, $message, $usermessage, $headers );
//if the message is sent successfully print "Mail sent". Otherwise print "Mail failed"
echo $mail_sent ? "Mail sent" : "Mail failed"; 
?>

The file is being uploaded to the correct place, and I am receiving a message to tell me that, but I also receive 'Mail Failed' and don't receive an email. I'd read it may be something to do with the header? I have another script that uses the mail function fine, so I know my server allows it.

Anyone have any ideas?
Thanks in advance

I am not sure that the output buffering is going to catch the stuff between lines 33 and 44, I have never tried doing anything like that.

I am also not sure, but it looks like you are putting headers in the message as well.

Hate to be repetitive, but you really are re-inventing the wheel on your email code. You could send the mail in a couple of lines with Swiftmailer, or PHPMailer, etc, and avoid the pain.

I am not sure that the output buffering is going to catch the stuff between lines 33 and 44, I have never tried doing anything like that.

I am also not sure, but it looks like you are putting headers in the message as well.

Hate to be repetitive, but you really are re-inventing the wheel on your email code. You could send the mail in a couple of lines with Swiftmailer, or PHPMailer, etc, and avoid the pain.

Thanks everyone. Sorry I've not commented in a while, been busy and thought leaving it for a while and going back might have given me a fresh burst of insight. So, I've decided to try and use PHPMailer as suggested by Nettsite. Here's what I've got

<?php
// Where the file is going to be placed
$target_path = "uploads/";
 
/* Add the original filename to our target path.
Result is "/uploads/filename.extension" */
$target_path = $target_path . basename( $_FILES['uploaded_file']['name']);
 
if(move_uploaded_file($_FILES['uploaded_file']['tmp_name'], $target_path)) {
echo "The file ". basename( $_FILES['uploaded_file']['name']).
" has been uploaded";
} else{
echo "There was an error uploading the file, please try again!";
}

$name = $_POST['name'];
$email = $_POST['email'];
$telephone = $_POST['telephone'];
$message = $_POST['message'];

$totalmessage = "
        Name:        $name  \n
        Email:        $email  \n
        Telephone:    $telephone  \n
        Message:    $message \n";

require("phpmailer.inc.php");        
$mail = new phpmailer;

$mail->IsSMTP(); // set mailer to use SMTP
$mail->From = $email;
$mail->FromName = "Upload Test";
$mail->Host = "localhost";  // specify main and backup server
$mail->AddAddress("myemail");
$mail->WordWrap = 50;    // set word wrap
$mail->AddAttachment($_FILES['uploaded_file']['tmp_name'], $_FILES['uploaded_file']['name']);  // add attachments


$mail->IsHTML(true);    // set email format to HTML
$mail->Body = $totalmessage;
$mail->Send(); // send message
?>

The file is being uploaded fine, but when I test it online I receive:

"The file academy text.gif has been uploaded

Mailer Error
Description:
Could not find D:\Temp\php5591.tmp file on filesystem"

From what I can see, it looks like it's not looking in the 'uploads' folder for the file, and it's using the temporary name instead of the files actual name.

Anyone have any ideas?
Thanks once again

Member Avatar for diafol

Is it this line?

$mail->AddAttachment($_FILES['uploaded_file']['tmp_name'], $_FILES['uploaded_file']['name']);  // add attachments

$_FILES

You're on localhost? Can phpmailer work for you? Do you have a mailserver (eg. Mercury) ?

Hi, thanks for the response. Yes, it's in that line that I think I'm setting the directory wrong. On the server, the files are stored in uploads/

I've not actually got that far, I assumed that an email wasn't being sent since the file wasn't being attached. I saw 'localhost' being used in another example online and thought I'd try it as I don't know what settings to use in other examples for setting the host. Is there an easy solution to that particular issue?

Member Avatar for diafol

If you want to send an email from your local machine, you need to set up a mail server. If you're using xampp, it comes with the build-in Mercury mail server, but you need to start it.

Ahh okay, i'll look into that. Any idea on why the file can't be found in the upload directory?

After move_uploaded_file() the temporary file is gone, use $target_path instead.

Hi, thanks for that. I changed the line to read:

$mail->AddAttachment($target_path);  // add attachments

and I receive:

"Fatal error: Cannot access empty property in E:\kunden\homepages\19\d345303379\www\phpmailer.inc.php on line 271"

I've also noticed that when I receive a message to say the file has been uploaded, I cannot see the file in Filezilla for a couple of minutes.

Can anyone tell me what I should be changing to add the attachment?

I was sure if this line:

$target_path = $target_path . basename( $_FILES['uploaded_file']['name']);

would redefine $target_path as the file name in the uploads folder.

Am I to use $target_path and the $_FILES array?
Must admit, the attachment line is the main point that I don't understand.

Thanks

Member Avatar for diafol

echo $target_path to see what it gives you.

Thanks for the replies.

I just used echo $target_path and it displayed:
"uploads/test image".gif" so target_path does appear to point to the file.

Any thoughts?

The problem is I can't give an absolute path as it's an upload form and the name of the file is of course going to be different every time. There must be a way to attach an uploaded file, I think I'm just referring to the wrong place, or perhaps it's reading the location as a string and not trying to attach the actual file. Who knows.

If anyone can offer a solution, I'd be extremely grateful.

Member Avatar for diafol

The problem is I can't give an absolute path as it's an upload form and the name of the file is of course going to be different every time. There must be a way to attach an uploaded file

You can give an absolute path. You can get the full path with

$_SERVER['DOCUMENT_ROOT'] . "/uploads/" . $_FILES['file']['name'];

This is obviously wrong: "uploads/test image".gif"

Until you get sensible output, you're not going to get it to work.

@Pritaeas - when you say absolute - like I've done or just straightforward

"/uploads/" . $_FILES['file']['name'];

?

Should be your first example, with document root. Your second path is incorrect, as most absolute paths usually start with /home/username/public_html/ or something like it.

I think you can best try with a static file first, you'll know it's path and that it's there. Once it works, begin making it dynamic.

Okay, so I've changed the line to:

$mail->AddAttachment($_SERVER['DOCUMENT_ROOT'] . "/uploads/Copy.jpg");  // add attachments

The file Copy.jpg is already sitting in the uploads folder in the main directory. I receive this error now:

Fatal error: Cannot access empty property in E:\kunden\homepages\19\d345303379\www\phpmailer.inc.php on line 271

Just checked the PHPMailer script for that line, and this is the surrounding code (line 271 in bold):

// Assembles and returns the message header
	function create_header() {
		$header = array();
		$header[] = sprintf("From: %s <%s>\n", $this->FromName, trim($this->From));
		$header[] = $from;
		$header[] = $this->addr_append("To", $this->to);
		if(count($this->cc) > 0)
			$header[] = $this->addr_append("cc", $this->cc);
		if(count($this->bcc) > 0)
			$header[] = $this->addr_append("bcc", $this->bcc);
		if(count($this->ReplyTo) > 0)
			$header[] = $this->addr_append("Reply-to", $this->ReplyTo);
		$header[] = sprintf("Subject: %s\n", trim($this->Subject));
		$header[] = sprintf("Return-Path: %s\n", trim($this->From));
		$header[] = sprintf("X-Priority: %d\n", $this->Priority);
		$header[] = sprintf("X-Mailer: phpmailer [version .9]\n");
		[B]$header[] = sprintf("Content-Transfer-Encoding: %s\n", $this->$Encoding);[/B]
		// $header[] = sprintf("Content-Length: %d\n", (strlen($this->Body) * 7));

Any ideas what the problem is now?
Thanks

Member Avatar for diafol

the AddAttachment() thingy, does it need an extra parameter?

The script is looking for $Encoding - sounds like it doesn't exist, i.e. you haven't set it somewhere.

Your original code showed this:

$mail->AddAttachment($_FILES['uploaded_file']['tmp_name'], $_FILES['uploaded_file']['name']);

showing 2 parameters.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.