Why is PHPmailer not sending the attachment? - php

Ive been working on create a file upload form using PHPmailer to send as attachments.
Ive finally got it to send the email, but its not sending the attachment. Here's my HTML form:
<input type="file" class="fileupload" name="images[]" size="80" />
And here's my php processor code:
<?php
require("css/class.phpmailer.php");
//Variables Declaration
$name = "the Submitter";
$email_subject = "Images Attachment";
$Email_msg ="A visitor submitted the following :\n";
$Email_to = "jonahkatz#yahoo.com"; // the one that recieves the email
$email_from = "someone#someone.net";
$attachments = array();
//
//
//------Check TYPE------\\
uploadFile();
//
//==============upload File Function============\\
//
function uploadFile() {
global $attachments;
foreach($_FILES['images']['name'] as $key => $value)
{
//
if(!empty($value))
{
$filename = $value;
//the Array will be used later to attach the files and then remove them from ser
ver ! array_push($attachments, $filename);
$dir = "uploads/$filename";
$success = copy($_FILES['images']['tmp_name'][$key], $dir);
}
//
}
$dir ="uploads/$filename";
if ($success) {
echo " Files Uploaded Successfully<BR>";
SendIt();
//
}else {
exit("Sorry the server was unable to upload the files...");
}
//
}
//
//==== PHP Mailer With Attachment Func ====\\
//
function SendIt() {
//
global $attachments,$name,$Email_to,$Email_msg,$email_subject,$email_from;
//
$mail = new PHPMailer();
$mail->IsQmail();// send via SMTP
$mail->From = $email_from;
$mail->FromName = $name;
$mail->AddAddress($Email_to);
$mail->AddReplyTo($email_from);
$mail->WordWrap = 50;// set word wrap
//now Attach all files submitted
foreach($attachments as $key => $value) { //loop the Attachments to be added ...
$mail->AddAttachment("uploads"."/".$value);
}
$mail->Body = $Email_msg."Name : ".$name"\n";
//
$mail->IsHTML(false);// send as HTML
$mail->Subject = $email_subject;
if(!$mail->Send())
{
echo "Message was not sent <p>";
echo "Mailer Error: " . $mail->ErrorInfo;
exit;
}
//
echo "Message has been sent";
// after mail is sent with attachments , delete the images on server ...
foreach($attachments as $key => $value) {//remove the uploaded files ..
unlink("uploads"."/".$value);
}
//
}
//
?>
Ive checked, and the file IS being saved in the directory "uploads". Here are the errors im receiving:
Files Uploaded Successfully
Message was not sent
Notice: Undefined property: phpmailer::$ErrorInfo in /usr/home/jak2234/public_html/new_form/phpmailerprocess.php on line 69
Mailer Error:
If anyone can spot the errors or provide some input how to this that would be so helpful! Thanks in advanced!
Jonah
Ive replaced
foreach($attachments as $key => $value) { //loop the Attachments to be added ...
$mail->AddAttachment("uploads"."/".$value);
With
foreach(array_keys($_FILES['files']['name']) as $key) {
$source = $_FILES['files']['tmp_name'][$key]; // location of PHP's temporary file for this.
$filename = $_FILES['files']['name'][$key]; // original filename from the client
$mail->AddAttachment($source, $filename);
}
And now here are my new errors:
Notice: Undefined index: files in /usr/home/jak2234/public_html/new_form/phpmailerprocess.php on line 58
Warning: array_keys() expects parameter 1 to be array, null given in /usr/home/jak2234/public_html/new_form/phpmailerprocess.php on line 58
Warning: Invalid argument supplied for foreach() in /usr/home/jak2234/public_html/new_form/phpmailerprocess.php on line 58
Strict Standards: Creating default object from empty value in /usr/home/jak2234/public_html/new_form/phpmailerprocess.php on line 68
Fatal error: Call to undefined method stdClass::IsHTML() in /usr/home/jak2234/public_html/new_form/phpmailerprocess.php on line 70

As I said in your other question, the first warning is due to you using $filename in line 10 of your script, without having assigned a value to it first:
$dir ="uploads/$filename"; // $filename has NOT been defined at this point.
As well, for your attachments, why not simply do:
foreach(array_keys($_FILES['files']['name']) as $key) {
$source = $_FILES['files']['tmp_name'][$key]; // location of PHP's temporary file for this.
$filename = $_FILES['files']['name'][$key]; // original filename from the client
$mail->AddAttachment($source, $filename);
}
There's no need to do all the file copying, building your own paths, etc... Just directly attach the temporary file PHP creates for you, and name it with whatever the original filename was.
Your script is far more complicated than it needs to be.

Related

php file size validation

I would like to create in php file size validation for every single file. I used for loop to add attachments, and then created condition to check file, but it's not working. There's no error, but it send mail with oversized attachment, instead of stop. Without the size validation part, it sends mail without any problems.
For sending I used php mailer.
<?php
//Import PHPMailer classes into the global namespace
//These must be at the top of your script, not inside a function
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
//Load Composer's autoloader
require 'autoload.php';
//Create an instance; passing `true` enables exceptions
$mail = new PHPMailer(true);
$honeypot = $_POST['honey'];
$user_name = $_POST['name'];
$user_email = $_POST['email'];
$user_message = $_POST['message'];
$user_phone = $_POST['phone'];
$honeypot = trim($_POST["honey"]);
$max_size = 2 * 1024 * 1204; //2mb
$attachment = $_FILES['uploaded-file'];
if ($_SERVER["REQUEST_METHOD"] == "POST") {
if(!empty($honeypot)) {
echo "NO SPAM!";
exit;
} else {
$mail = new PHPMailer; //From email address and name
$mail->isMail();
$mail->From = $user_email;
$mail->addAddress("jaroslaw.mor#gmail.com");
$mail->isHTML(true);
$mail->Subject = "Zapytanie ze strony www";
$mail->Body = "Telefon:$user_phone<br><br>Treść wiadomośći:<br>$user_message";
$mail->AltBody = "Telefon:$user_phone\n$content";
if(isset($attachment)) {
for ($i = 0; $i < count($_FILES['uploaded-file']['name']); $i++) {
if ($_FILES['uploaded-file']['error'] !== UPLOAD_ERR_OK) continue;
$file_TmpName = $_FILES['uploaded-file']["tmp_name"][$i];
$file_name = $_FILES['uploaded-file']["name"][$i];
if($_FILES['uploaded-file']["name"][$i]; > $max_size) {
echo "file is too big";
die();
}
else{
move_uploaded_file($fileTmpName, "uploads/" . $filename);
$mail-> AddAttachment("uploads/". $filename);
}
}//for
}//isset
if(!$mail->send()) {
echo "Mailer Error: " . $mail->ErrorInfo;
exit();
}
else {
header("Location: sent.html");
exit();
}//if send else
}//honey else end
}//post end
I have rebuilt my code a bit, and also complied with comments/clues.
But there's still the same problem.
This is a copy paste error
$_FILES['uploaded-file']["name"]['size'][$i]
According to the PHP documentation, size is under $_FILES['uploaded-file'] and not $_FILES['uploaded-file']['name']. See #yuxufabio's comment.
And the if (isset($attachments)) check is a bit weird. It'll always return an array (meaning true) even if it's empty. What you probably mean is if the form variable itself is set or not
if (isset($_FILES['uploaded-file'])) {
for ($i = 0; $i < count($_FILES['uploaded-file']['name']); $i++) {
Lastly, you should be checking if there's an error, as the upload is not garuanteed to work at the fault of the client, such as an empty file or a network error
if ($_FILES['uploaded-file']['error'][$i] !== UPLOAD_ERR_OK) continue;
...
if ($_FILES['uploaded-file']['size'][$i] > $maxsize) {
...
What I can see here is that you used the "move_upload_file" way earlier before you checked for the file size. And that means the file will be uploaded before checking to see if it's bigger or not. It should be something like this;
if( $_FILES['uploaded-file']["name"]['size'][$i] > $maxsize ) {
echo "file is too big";
die();
}else{
move_uploaded_file($fileTmpName, "uploads/" . $filename);
$mail-> AddAttachment("uploads/". $filename);
}

PHPMailer sanitizing multiple attachments

I am trying to limit the file size and type of attachments processed by phpmailer. The answer in this post does not solve the multiple attachments issue. The issue seems to be the form's input name with [] which converts form input to array. I am not able to write its correct syntax.
HTML is:
<input type="file" multiple="multiple" name="attach_file[]" />
PHP is:
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require 'src/Exception.php';
require 'src/PHPMailer.php';
$name = $_POST['name'];
$mail = new PHPMailer(true);
try {
$mail->setFrom('abc#abc.org', 'abc');
$mail->addAddress('xyz#xyz.com', 'xyz');
// Attachments
foreach(array_keys($_FILES['attach_file']['name']) as $key) {
$source = $_FILES['attach_file']['tmp_name'][$key];
$filename = $_FILES['attach_file']['name'][$key];
$mail->AddAttachment($source, $filename);
}
$mail->isHTML(true);
$mail->Subject = 'Case History';
$mail->Body = $name;
$mail->send();
echo 'Message has been sent';
}
catch (Exception $e) {
echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
}
If in foreach loop I use this:
$maxsize = 2 * 1024 * 1024; // 2 MB
$types = array('image/png', 'image/jpeg', 'image/gif'); // allowed mime-types
if(filesize($filename) < $maxsize && in_array(mime_content_type($filename),$types)){
$mail->AddAttachment($source, $filename);
}
I get these errors :
filesize(): stat failed
mime_content_type(): failed to open stream.
No such file or directory
What is the correct way of writing the IF condition when input name is for multiple attachments. Thanks.
You should note that $filename is just the original name of the file that has been uploaded (e.g. photo.jpg) - but the filesystem pathname of the uploaded file is actually $source (always some random filename, sitting in the OS temp folder).

How to send multiple attachments to email

I have the following simple form that is ment to send multiple files to email:
<form method="post" enctype="multipart/form-data">
<input id="upload-file" class="upload-file" type="file" name="my_file[]" multiple>
<input type="submit" value="Send">
</form>
I am using the following php code to do the actual sending:
if (isset($_FILES['my_file'])) {
$to = 'my-email#maybe-gmail.com';
$subject = 'Files moar files';
$message = 'Message Body';
$headers = 'Some random email header';
$attachments = array();
$myFile = $_FILES['my_file'];
$fileCount = count($myFile["name"]);
for ($i = 0; $i < $fileCount; $i++) {
$attachments[$i] = $_FILES['my_file']['tmp_name'][$i];
}
wp_mail($to, $subject, $message, $headers, $attachments);
}
I am using wp_mail() method, because this is in a Wordpress website(it is the same as the php mail() function).
My problem is, that I receive an email with the attachments, but the name of the file is messed up, and there is no extension, so it's hard to open it. What am I doing wrong here, and how can I fix it?
When you upload files in PHP, they are uploaded to a temporary directory and given a random name. This is what is stored in the 'tmp_name' key for each of the files. It also explains why each file does not have an extension when sent via email, as they are simply stored as files in the temporary directory. The original file name is stored in the 'name' key.
The easiest way to deal with this issue is to rename the files to their appropriate file names and then send them, because it doesn't seem that WordPress supports a second field to provide the file name for each file.
$uploaddir = '/var/www/uploads/'; //Or some other temporary location
$myFile = $_FILES['my_file'];
$fileCount = count($myFile["name"]);
for ($i = 0; $i < $fileCount; $i++) {
$uploadfile = $uploaddir . basename($_FILES['my_file']['name'][$i]);
if (!move_uploaded_file($_FILES['my_file']['tmp_name'][$i], $uploadfile)) {
//If there is a potential file attack, stop processing files.
break;
}
$attachments[$i] = $uploadfile;
}
wp_mail($to, $subject, $message, $headers, $attachments);
//clean up your temp files after sending
foreach($attachments as $att) {
#unlink($att);
}
When dealing with files it's also a good practice to validate MIME types and restrict the types of files that you support.
WordPress wp_mail: https://developer.wordpress.org/reference/functions/wp_mail/
PHP POST Uploads: http://php.net/manual/en/features.file-upload.post-method.php
$attachments = array();
array_push($attachments, WP_CONTENT_DIR .
'/uploads/my-document.pdf' ); array_push($attachments,
WP_CONTENT_DIR . '/uploads/my-file.zip' );
It's work good for me for multiple files !
Good luck

PHP - PHPMailer - how to add file as attachment with correct extension

I am building a website and have a form wherein the user can enter some fields, i.e. name, email, etc. but then also has the option to upload a file. I am using PHPMailer to construct an email that has the user's data as the email fields, and then sends it to me, so I can look at it. All works fine until the file upload. I am relatively new to PHP so it might be something little, but its driving me crazy. In the code below, I generate a new name for the uploaded file, and then append the file extension. Then I move it to a temp folder and try to attach it to the email via $mail->addAttachment. The email sends and everything, but the attached file has no extension--and when I manually download and add the appropriate extension, it works, but for some reason the file wont attach as the proper type.
// if one of the fields is set they all will be, i.e. the form has been submitted
if (isset($_POST['firstName']))
{
// array to hold possible runtime errors
$errors = array();
// if statement to see if user failed to enter one of the required fields
if (empty($_POST['firstName']) || empty($_POST['lastName']) || empty($_POST['email']) || empty($_POST['subject'])
|| empty($_POST['message']) || empty($_POST['phone']))
{
array_push($errors, 'Please enter all required fields');
}
// var to keep track of whether or not we have a file
$have_file = ($_FILES['inputFile']['error'] != UPLOAD_ERR_NO_FILE);
//checks for file upload as well
if ($have_file)
{
// here a file has been uploaded, so we make sure its an acceptable type
$ext_whitelist = array('dwg', 'asm', 'acp', '3dxml', 'cgr', 'dft', 'dxf', 'iam', 'idw', 'ipt', 'ipn', 'par', 'prt',
'skp', 'rvt', 'rfa',' sldasm', 'slddrw', 'sldprt', 'step', 'stl');
// var to store file array
$file = $_FILES['inputFile'];
// file properties stored for easier readability
$file_name = $file['name'];
$file_tmp = $file['tmp_name'];
$file_size = $file['size'];
$file_error = $file['error'];
// get file extension
$file_ext = explode('.', $file_name);
$file_ext = strtolower(end($file_ext));
if (!in_array($file_ext, $ext_whitelist))
{
if ($ext == 'php')
{
array_push($errors, 'Nice try');;
}
else
{
array_push($errors, 'Please enter a valid file type');
}
}
// checks file size
if ($file_size > 64000000)
{
array_push($errors, 'File too large, please call for further information');
}
}
// if we have an error, we just output that, or those, otherwise, we proceed
// with mailer
if (!empty($errors))
{
foreach ($errors as $err) { ?>
<p class="text-center" style="margin-top:20px;font-size:16px;">
<?php echo $err; ?>
</p>
<?php
}
}
// if here, there have been no errors
else
{
require 'PHPMailer/PHPMailerAutoload.php';
$mail = new PHPMailer;
//mail server setup
$mail->isSMTP(); // Set mailer to use SMTP
$mail->Host = 'smtp.gmail.com'; // Specify main and backup SMTP servers
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = ''; // SMTP username
$mail->Password = ''; // SMTP password
$mail->SMTPSecure = 'tls'; // Enable TLS encryption, `ssl` also accepted
$mail->Port = 587; // TCP port to connect to
//add To and From fields
$mail->From = '';
$mail->FromName = 'Mailer';
$mail->addAddress('');
$mail->isHTML(true); // Set email format to HTML
//add message contents
$mail->Subject = $_POST['subject'];
$mail->Body = $_POST['message'] . '<br><br>' . $_POST['firstName'] . ' ' . $_POST['lastName'] . '<br>' . $_POST['phone'];
// adds organization if its there
if (!empty($_POST['organization']))
{
$mail->Body .= '<br>' . $_POST['organization'];
}
// uploads/attaches file if there was one
if($have_file)
{
// give file unique name and set its destination as a temporary folder
$file_name_new = uniqid('', true) . '.' . $file_ext;
$file_destination = sys_get_temp_dir() . '\\' . $file_name_new;
if (move_uploaded_file($file_tmp, $file_destination))
{
echo $file_destination;
$mail->addAttachment($file_destination, 'Uploaded file');
}
else
{
?>
<p class="text-center" style="margin-top:20px;font-size:16px;">Error sending message, please call and let us know</p>
<?php
}
}
//send the message
if (!$mail->send())
{
?>
<p class="text-center" style="margin-top:20px;font-size:16px;">Error sending message, please call and let us know</p>
<?php
}
else
{
?>
<p class="text-center" style="margin-top:20px;font-size:16px;">Message sent! Thank you for visiting us today</p>
<?php
}
Any help would be greatly appreciated. I have left certain fields empty to prevent showing my info. i.e. $mail->From
#Hanoncs I managed to get it I think. The line:
$mail->addAttachment($file_destination, 'Uploaded file');
was renaming the file upon attachment to 'Uploaded file', literally. So, obviously, in the email there was no file extension on the file, because of the name. So all I had to do was change 'Uploaded file' to something with the extension, e.g. 'uploadedfile.ext' and it seemed to work. A silly, but enormously frustrating mistake, since all of the file upload handling seemed to work rather well. So the block now looks like this:
// uploads/attaches file if there was one
if($have_file)
{
// give file unique name and set its destination as a temporary folder
$file_name_new = uniqid('', true) . '.' . $file_ext;
$file_destination = sys_get_temp_dir() . '\\' . $file_name_new;
if (move_uploaded_file($file_tmp, $file_destination))
{
echo $file_destination;
$mail->addAttachment($file_destination, 'uploadedFile.dwg');
}
else
{
?>
<p class="text-center" style="margin-top:20px;font-size:16px;">Error sending message, please call and let us know</p>
<?php
}
}
Anyway, thanks for all your help, especially about the IDE, going to work on setting that up now.
First I would say you need to debug and check the file_ext at the time its appended and make sure its not empty.
To get the file extension use:
$file_ext = pathinfo($file_name, PATHINFO_EXTENSION);
Let me know your result and I can assist further.

Moving Attachments To Folder And Attaching Them With Email

I have a simple page, which is sending an Email message and multiple attachments, through phpmailer.
I have to attach the multiple attachments to the Email message to send, and also upload these files o server at same time, For which i m using the following loop:
$MyUploads = array();
foreach(array_keys($_FILES['attach']['name']) as $key)
{ $Location="uploads/";
$name=$_FILES['attach']['name'][$key];
$filePath = $Location . $name;
$source = $_FILES['attach']['tmp_name'][$key]; // location of PHP's temporary file for
$tmp=$_FILES['attach']['tmp_name'][$key];
if($mail->AddAttachment($source, $name))
{if(move_uploaded_file($tmp, $filePath)){
$MyUploads[] = $filePath;}
else
{$MyUploads[]='';
echo "not uploaded";}
}
}
The problem is, when i use the function move_uploaded_file(), the files are uploaded to the server folder, but are not sent with the attachments. As i comment out this function the attachments are sended.
Can;t find out, why these two dnt work together. Please any body help
Here is the loop that sends Attachments, And move them to a target path, for further use. I hope any one else can be helped by this:
$MyUploads = array();
$numFiles = count(array_filter($_FILES['attach']['name']));
for ($i = 0; $i < $numFiles; ++$i) {
$target_path = 'uploads/' . basename($_FILES['attach']['name'][$i]);
if(move_uploaded_file($_FILES['attach']['tmp_name'][$i], $target_path)) {
echo "the file ".basename($_FILES['attach']['name'][$i])." has been uploaded<br />";
$MyUploads[] = $target_path;
echo $MyUploads;
$mail->AddAttachment($target_path);
}
}

Categories