PHP Order Form - Email with Attachment - php

I am trying to create an order form which when complete, passes you on to the order.php page (sends the email), where you are then passed on to paypal. Everything was working fine until i tried to add attachments, when i added the code for attachment, the email is no longer sent.
<?php
$to = 'hidden' ;
$from = $_REQUEST['email'] ;
$name = $_REQUEST['name'] ;
$headers = "From: $from";
$subject = "Distinctive Writers - Contact Form";
$tprice = $_REQUEST['tprice'] ;
$fields = array();
$fields{"name"} = "name";
$fields{"email"} = "email";
$fields{"number"} = "number";
$fields{"subject"} = "subject";
$fields{"doctype"} = "doctype";
$fields{"spec"} = "spec";
$fields{"grade"} = "grade";
$fields{"days"} = "days";
$fields{"due"} = "due";
$fields{"pages"} = "pages";
$fields{"price"} = "price";
$mime_boundary="==Multipart_Boundary_x".md5(mt_rand())."x";
$tmp_name = $_FILES['filename']['tmp_name'];
$type = $_FILES['filename']['type'];
$file_name = $_FILES['filename']['name'];
$size = $_FILES['filename']['size'];
if (file_exists($tmp_name)){
// Check to make sure that it is an uploaded file and not a system file
if(is_uploaded_file($tmp_name)){
// Now Open the file for a binary read
$file = fopen($tmp_name,'rb');
// Now read the file content into a variable
$data = fread($file,filesize($tmp_name));
// close the file
fclose($file);
// Now we need to encode it and split it into acceptable length lines
$data = chunk_split(base64_encode($data));
}
// Now we'll build the message headers
$headers = "From: $from\r\n" .
"MIME-Version: 1.0\r\n" .
"Content-Type: multipart/mixed;\r\n" .
" boundary=\"{$mime_boundary}\"";
// Now we'll insert a boundary to indicate we're starting the attachment we have to specify the content type, file name, and disposition as an attachment, then add the file content and set another boundary to indicate that the end of the file has been reached
$message .= "--{$mime_boundary}\n" .
"Content-Type: {$type};\n" .
" name=\"{$file_name}\"\n" .
//"Content-Disposition: attachment;\n" .
//" filename=\"{$fileatt_name}\"\n" .
"Content-Transfer-Encoding: base64\n\n" .
$data . "\n\n" .
"--{$mime_boundary}--\n";
$body = "We have received the following information:\n\n"; foreach($fields as $a => $b){ $body .= sprintf("%20s: %s\n",$b,$_REQUEST[$a]); }
$headers2 = "From: noreply#YourCompany.com";
$subject2 = "Thank you for contacting us";
$autoreply = "Thank you for contacting us. Somebody will get back to you as soon as possible, usualy within 48 hours. If you have any more questions, please consult our website at www.oursite.com";
if($from == '') {print "You have not entered an email, please go back and try again";}
else {
if($name == '') {print "You have not entered a name, please go back and try again";}
else {
$send = mail($to, $subject, $body, $headers, $message);
$send2 = mail($from, $subject2, $autoreply, $headers2);
}
}
if(!mail($to, $subject, $body, $headers, $message)){
print "ERROR!!";
}
}
?>

I recommend PHPMailer too as mentioned by pc-shooter
then you can use
$mail = new PHPMailer();
then you can utilize either one of these two
$mail->AddStringAttachment($string,$filename)
$mail->AddAttachment($path);
Something to keep in mind, something else might be blocking the email. if the mail function returns TRUE then the mail was dispatched.

Related

mail() is Incorrectly Sending Emails to cPanel Default Account

I purchased a domain from GoDaddy and linked it to Office 365 (via MX records). This means I have several email accounts in Outlook that are #mydomain.com.
Example Outlook accounts:
sales#mydomain.com
contact#mydomain.com
matt#mydomain.com
I can send/receive emails through those accounts.
My website is hosted on basic web hosting with a cPanel installation, which means I was given a "default" email account. For example: default#mydomain.com. I wrote a PHP script on my website (contact form) that sends emails via mail() to contact#mydomain.com.
However all the emails are sent to the default cPanel account default#mydomain.com instead of the Outlook account contact#mydomain.com.
To test, I tried sending the emails to my personal account that is not hosted on mydomain and it works as expected. Emails are sent instantly.
How come my website incorrectly send emails to the Outlook accounts? Thanks for your time.
EDIT:
The script was requested:
<?php
$uploadedFile = $statusMsg = '';
if (isset($_POST['submit']))
{
$first_name = $_POST['first_name'];
$last_name = $_POST['last_name'];
$email = $_POST['email'];
$phone = $_POST['phone'];
$message = $_POST['message'];
if(!empty($first_name) && !empty($last_name) && !empty($message))
{
if(filter_var($email, FILTER_VALIDATE_EMAIL))
{
$uploadStatus = 1;
if(!empty($_FILES["attach"]["name"]))
{
$targetDir = "uploads/";
$fileName = basename($_FILES["attach"]["name"]);
$targetFilePath = $targetDir . $fileName;
$fileType = pathinfo($targetFilePath,PATHINFO_EXTENSION);
if(move_uploaded_file($_FILES["attach"]["tmp_name"], $targetFilePath))
{
$uploadedFile = $targetFilePath;
}
else
{
$uploadStatus = 0;
$statusMsg = "Sorry, there was an error uploading your file.";
}
}
if($uploadStatus == 1)
{
$name = $first_name.' '.$last_name;
$mailTo = "contact#mydomain.com";//changed to my real outlook account
$htmlContent = '<h2>Contact Request Submitted</h2>
<p><b>Name:</b> '.$name.'</p>
<p><b>Email:</b> '.$email.'</p>
<p><b>Phone:</b> '.$phone.'</p>
<p><b>Message:</b><br/>'.$message.'</p>';
// Header for sender info
$headers = "From: $name"." <".$email.">";
if(!empty($uploadedFile) && file_exists($uploadedFile))
{
// Boundary
$semi_rand = md5(time());
$mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";
// Headers for attachment
$headers .= "\nMIME-Version: 1.0\n" . "Content-Type: multipart/mixed;\n" . " boundary=\"{$mime_boundary}\"";
// Multipart boundary
$message = "--{$mime_boundary}\n" . "Content-Type: text/html; charset=\"UTF-8\"\n" .
"Content-Transfer-Encoding: 7bit\n\n" . $htmlContent . "\n\n";
// Preparing attachment
if(is_file($uploadedFile)){
$message .= "--{$mime_boundary}\n";
$fp = #fopen($uploadedFile,"rb");
$data = #fread($fp,filesize($uploadedFile));
#fclose($fp);
$data = chunk_split(base64_encode($data));
$message .= "Content-Type: application/octet-stream; name=\"".basename($uploadedFile)."\"\n" .
"Content-Description: ".basename($uploadedFile)."\n" .
"Content-Disposition: attachment;\n" . " filename=\"".basename($uploadedFile)."\"; size=".filesize($uploadedFile).";\n" .
"Content-Transfer-Encoding: base64\n\n" . $data . "\n\n";
}
$message .= "--{$mime_boundary}--";
$returnpath = "-f" . $email;
// Send email
$mail = mail($mailTo, "Contact Form Submission from ".$name, $message, $headers, $returnpath);
// Delete attachment file from the server
#unlink($uploadedFile);
}
else
{
// Set content-type header for sending HTML email
$headers .= "\r\n". "MIME-Version: 1.0";
$headers .= "\r\n". "Content-type:text/html;charset=UTF-8";
// Send email
$mail = mail($mailTo, 'Contact Form Submission from '.$name, $htmlContent, $headers);
}
// If mail sent
if($mail)
{
$statusMsg = "Your message has been sent. Thanks!";
}
else
{
$statusMsg = 'Your contact request submission failed, please try again.';
}
}
}
else
{
$statusMsg = 'Please enter a valid email address.';
}
}
else
{
$statusMsg = "Please fill out the required information.";
}
}
?>
The solution was to change my cPanel "Email Routing" option to "Remote" in order for all local emails to first check with the MX records.

Php mail not working with more than one recipient

How come this piece of php code doesn't work with multiple recipient ?
It only works if $to has only one adress, like:
$to = 'aa#bb.com';
Edit
It works if email adresses are on the same domain.. For instance, if the website is www.example.com, emails such as xxx#example.com will work but yyy#other.com won't.
Solution
PHPMailer. It gives an easy way to configure SMTP.
Here is the initial code
<?php
//define the receiver of the email
$to = 'aa#bb.com, cc#dd.com, ee#ff.com';
// array with filenames to be sent as attachment
$files = array("a.zip","b.c","a.html");
// email fields: to, from, subject, and so on
$from = "mail#mail.com";
$subject ="My subject";
$message = "My message";
// boundary
$semi_rand = md5(time());
$mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";
// headers for attachment
$headers = "From: $from";
$headers .= "\nMIME-Version: 1.0\n" . "Content-Type: multipart/mixed;\n" . " boundary=\"{$mime_boundary}\"";
// multipart boundary
$message = "This is a multi-part message in MIME format.\n\n" . "--{$mime_boundary}\n" . "Content-Type: text/plain; charset=\"iso-8859-1\"\n" . "Content-Transfer-Encoding: 7bit\n\n" . $message . "\n\n";
$message .= "--{$mime_boundary}\n";
// preparing attachments
for($x=0;$x<count($files);$x++){
$file = fopen($files[$x],"rb");
$data = fread($file,filesize($files[$x]));
fclose($file);
$data = chunk_split(base64_encode($data));
$message .= "Content-Type: {\"application/octet-stream\"};\n" . " name=\"$files[$x]\"\n" .
"Content-Disposition: attachment;\n" . " filename=\"$files[$x]\"\n" .
"Content-Transfer-Encoding: base64\n\n" . $data . "\n\n";
$message .= "--{$mime_boundary}\n";
}
// send
$ok = #mail($to, $subject, $message, $headers);
if ($ok) {
echo "<p>mail sent to $to!</p>";
} else {
echo "<p>mail could not be sent!</p>";
}
?>
Here is the final code
// PHPMailer
$mail = new PHPMailer;
// setting up PHPMailer
$mail->isSMTP();
$mail->Host = 'host.com';
$mail->SMTPAuth = false;
$mail->Port = xx;
$mail->setFrom($_POST['email'], $_POST['name']);
$mail->Subject = $_POST['subject'];
$mail->msgHTML($_POST['message']);
foreach($contacts as $contact)
$mail->addAddress($contact['email']);
// If the user has attached some files
foreach ($_FILES as $file)
$mail->addAttachment($file['tmp_name'], basename($file['name']));
$response = array("status" => $mail->send() ? "sent" : "error");
echo json_encode($response);
You need use proper RFC 2822 formating.
Don't use # because you don't know what is the error. If you format mails in format "user#example.com, anotheruser#example.com" it's correct and you need search problem elsewhere.
You can also see example #4 on http://php.net/manual/en/function.mail.php#example-3493 page.
although this is not a direct response to your issue, you could potentially save yourself trouble by using a pre-existing email sending library like either:
phpmailer
https://github.com/PHPMailer/PHPMailer
or simplesmtp
https://bitbucket.org/ghorwood/simplesmtp/

Attachment uploads but how do I email it?

I have the php code working up to the point where I need the image to get attached to a variable and i gets emailed with the rest of my form. I get 2 errors. One error is telling me that $messageImage in undefined on line 75? and the other is: Call to a member function addAttachment() on a non-object on line 75.
can someone explain the proper way of declaring the variable and making sure it is an object so that addAttachment works. Thank You
//copy the temp. uploaded file to uploads folder
$upload_folder = 'uploads/';
$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 = "example#gmail.com"; // this is your Email address
$from = filter_var($_POST['email'], FILTER_SANITIZE_EMAIL); // this is the sender's Email address
$first_name = filter_var($_POST['first_name'], FILTER_SANITIZE_STRING);
$story = filter_var($_POST['message'], FILTER_SANITIZE_STRING);
$subject = "subject";
$subject2 = "Thank You for submitting";
$messageImage->addAttachment($path_of_uploaded_file);
$message = $first_name . " wrote the following:" . "\n\n" . $story;
$message2 = "Here is a copy of your story " . $first_name . "\n\n" . $story;
$headers = "From:" . $from;
$headers2 = "From:" . $to;
mail($to,$subject,$message,$messageImage,$headers);
mail($from,$subject2,$message2,$headers2); // sends a copy of the message to the sender
'$messageImage' is an object in your code and it is not define.
You can check this with simple if check like below,
if ($messageImage) {
// do something
}
Following code can work for you,
//copy the temp. uploaded file to uploads folder
$upload_folder = 'uploads/';
$to = "example#gmail.com"; // this is your Email address
$from = filter_var($_POST['email'], FILTER_SANITIZE_EMAIL); // this is the sender's Email address
$first_name = filter_var($_POST['first_name'], FILTER_SANITIZE_STRING);
$story = filter_var($_POST['message'], FILTER_SANITIZE_STRING);
$subject = "subject";
$subject2 = "Thank You for submitting";
$message = $first_name . " wrote the following:" . "\n\n" . $story;
$message2 = "Here is a copy of your story " . $first_name . "\n\n" . $story;
$headers = "From: $from";
// boundary
$semi_rand = md5(time());
$mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";
// headers for attachment
$headers .= "\nMIME-Version: 1.0\n" . "Content-Type: multipart/mixed;\n" . " boundary=\"{$mime_boundary}\"";
// multipart boundary
$message = "This is a multi-part message in MIME format.\n\n" . "--{$mime_boundary}\n" . "Content-Type: text/plain; charset=\"iso-8859-1\"\n" . "Content-Transfer-Encoding: 7bit\n\n" . $message . "\n\n";
$message .= "--{$mime_boundary}\n";
$content = '';
$tmp_path = $_FILES["uploaded_file"]["tmp_name"];
if($tmp_path) {
$filename = $_FILES["uploaded_file"]["name"];
$path_of_uploaded_file = $upload_folder . $filename;
if(!copy($tmp_path, $path_of_uploaded_file))
{
$errors = '\n error while copying the uploaded file';
}
$file_size = filesize($path_of_uploaded_file);
$handle = fopen($path_of_uploaded_file, "rb");
$content = fread($handle, $file_size);
fclose($handle);
$content = chunk_split(base64_encode($content));
}
// if attachment
if ($content) {
$message .= "Content-Type: {\"application/octet-stream\"};\n" . " name=\"{$filename}\"\n" .
"Content-Disposition: attachment;\n" . " filename=\"{$filename}\"\n" .
"Content-Transfer-Encoding: base64\n\n" . $content . "\n\n";
$message .= "--{$mime_boundary}\n";
}
$headers2 = "From:" . $to;
mail($to, $subject, $message, $headers);
mail($from, $subject2, $message2, $headers2); // sends a copy of the message to the sender
In your code, $messageImage is not being set. Since it is not set, it is NULL, causing the next error, you are trying to refer to the method of an object, but it is null.
To send a message with attachments, you need to set email headers, and the image is base64 encoded in the message. I would look at this other StackOverflow answer:
https://stackoverflow.com/a/17371739/2832264
To make a simple object:
$obj = new stdClass();
Otherwise, you would create a class, make sure it is included in your script, and create a new instance of that:
$obj = new Person();
I would read the official PHP documentation on classes.

multiple files as attachment from a form and send a email

Following is the code I am using to send multiple files as attachment in a mail, tested it in local environment, the attachments were reaching the mail box but as empty files, and in live environment, result is mail could not be sent, though files get saved in the upload folder on the server...a newbie in php so please can anyone help what am I doing wrong..??
In local environment i was using this code $server_file = "/localhost:81/xyz/uploads/$path_parts[basename]"; in place what is mentioned down there under move this file to the server
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
//did files get sent
if(isset($_FILES) && (bool) $_FILES) {
//define allowed extensions
$allowedExtensions = array("pdf","doc","docx","gif","jpeg","jpg","png","rtf","txt");
$files = array();
$username=$_POST['username'];
$email=$_POST['email'];
//loop through all the files
foreach($_FILES as $name=>$file){
//define some variables
$file_name= $file['name'];
$temp_name= $file['tmp_name'];
//check if this file type is allowed
$path_parts = pathinfo($file_name);
$ext = $path_parts['extension'];
if(!in_array($ext,$allowedExtensions)) {
die("extension not allowed");
}
//move this file to the server
$server_file = "/home/public_html/xyz.com/uploads/$path_parts[basename]";
move_uploaded_file($temp_name,$server_file);
//add this file to array of files
array_push($files,$server_file);
}
//define some mail variables
$to = "info#xyz.com";
$from = "From: $username<$email>\r\nReturn-path: $email";
$subject = "Photo attachment of . $name .";
$msg = "Images of $username, $email";
$headers = "From: $from";
//define our boundary
$semi_rand = md5(time());
$mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";
//tell the header about the boundary
$headers .= "nMIME-Version:1.0\n";
$headers .= "Content-Type: multipart/mixed;\n";
$headers .= " boundary=\"{$mime_boundary}\"";
//part1: define the plain text email
$message = "\n\n--{$mime_boundary}\n";
$message .="Content-Type: text/plain; charset=\"iso-8859-1\"\n";
$message .="Content-Transfer-Encoding: 7bit\n\n". $msg ."\n\n";
$message .="--{$mime_boundary}\n";
//part2: loop and define mail attachments
foreach($files as $file){
$aFile = fopen($file,"rb");
$data = fread($aFile,filesize($file));
fclose($aFile);
$data = chunk_split(base64_encode($data));
$message .="Content-Type: {\"application/octet-stream\"};\n";
$message .= " name=\"$files\"\n";
$message .= "Content-Disposition: attachment;\n";
$message .= " filename=\"$files\"\n";
$message .= "Content-Transfer-Encoding: base64\n\n" . $data . "\n\n";
$message .= "--{$mime_boundary}\n";
}
//send the email
$ok = mail($to, $subject, $message, $headers, $from);
if($ok){
header("Location: thank-your.php");
}
else{
echo"<p>mail could not be sent!</p>";
}
die();
}
?>

test PHP mail()

I have a mail submission script that is working exactly as expected on both a dev environment and live with one exception. I am getting conflicting results from the mail() test conditional on the live environment vs the dev environment.
On my dev environment it redirects to $ThanksURL on success. On the live server even through the mail is successfully the script proceeds to the else statement and redirects back to the form page.
This has been driving me crazy so any ideas as to why would be most welcome.
Snippet of the issue:
$ok = #mail($to, $subject, $message, $headers, $returnpath);
if($ok){ header("Location: $ThanksURL");
exit;
}else{ $_SESSION['error'] .= " There has been a problems submitting your details. <br />";
header("Location: $form");
exit;
}// end if ok
Script in full:
<?php
session_start();
$form = 'index.php';
$_SESSION['error'] = "The following errors have occured: ";
if(isset($_POST['submitted'])) {
// email fields: to, from, subject, and so on
// Here
$from = "Form Feedback <******#gmail.com>";
$to = "******#gmail.com";
$subject = "Competition";
$ThanksURL = "thankyou.html";
$headers = "From: $from";
$returnpath = "-f" . $from;
$attachment = 0; // is there an attachement
//form fields
$emailAddress = stripslashes($_POST['email']);
$phone = stripslashes($_POST['phone']);
$comments = stripslashes($_POST['comments']);
//basic message info
$message = "Info submitted:\n\nEmail address: " .$emailAddress ."\n\nPhone number: " .$phone."\n\nComments:\n ".$comments. "\n\n";
if($_FILES['attachment']['error'] == 4) {
$message .="No attachement included";
}else{
// test file type and size for submission
$allowedExts = array("doc", "docx", "pdf", "txt");
$extension = end(explode(".", $_FILES['attachment']["name"]));
if ((($_FILES['attachment']["type"] == "application/msword")
|| ($_FILES['attachment']["type"] == "application/vnd.openxmlformats-officedocument.wordprocessingml.document")//docx mime
|| ($_FILES['attachment']["type"] == "application/pdf")
|| ($_FILES['attachment']["type"] == "application/plain")
|| ($_FILES['attachment']["type"] == "text/plain"))
&& ($_FILES['attachment']["size"] < 2097152 )
&& in_array($extension, $allowedExts)){
// boundary
$semi_rand = md5(time());
$mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";
// headers for attachment
$headers .= "\nMIME-Version: 1.0\n" . "Content-Type: multipart/mixed;\n" . " boundary=\"{$mime_boundary}\"";
// multipart boundary
$message = "--{$mime_boundary}\n" . "Content-Type: text/plain; charset=\"iso-8859-1\"\n"."Content-Transfer-Encoding: 7bit\n\n" . $message . "\n\n";
// prepare the files uplaod
$message .= "--{$mime_boundary}\n";
$fp = #fopen($_FILES['attachment']['tmp_name'],"rb");
$data = #fread($fp,filesize($_FILES['attachment']['tmp_name']));
#fclose($fp);
$data = chunk_split(base64_encode($data));
$message .= "Content-Type: application/octet-stream; name=\"".$_FILES['attachment']['name']."\"\n"."Content-Description: ".$_FILES['attachment']['name']."\n" ."Content-Disposition: attachment;\n" . " filename=\"".$_FILES['attachment']['name']."\";size=".$_FILES['attachment']['size'].";\n"."Content-Transfer-Encoding: base64\n\n" . $data . "\n\n";
$message .= "--{$mime_boundary}--";
}else{
$_SESSION['error'] .= "Error: " . $_FILES["attachment"]["name"] . " is not a doc, docx, pdf or txt file or is larger than 2mb. Please resubmit <br />";
header("Location: $form");
exit;
}
}//file conditional
//prepare mail
$ok = #mail($to, $subject, $message, $headers, $returnpath);
if($ok){
header("Location: $ThanksURL");
exit;
}else{
$_SESSION['error'] .= " There has been a problems submitting your details. <br />";
header("Location: $form");
exit;
}// end if ok
}// end sub
?>
Sorry to say this, but php mail can return something else on success than true or false, like mentioned in the php manual comment. Also, it is known to return false on success on some situations, too.
PHP mail() is a kludgy function from many different angles, and personally I would advise against using it in production systems. There are quite a few alternatives, such as swift mailer, PHP mailer, Zend_Mail etc.
However, if you want to use it, you should definitely log the actions and in this case, return values, and not have # to hide your return values.
As a summary, in this case mail() returned an empty string, and not true or false.

Categories