PHPMailer sanitizing multiple attachments - php

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).

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);
}

Allowed extension phpmailer

how could i change my code to only accept some extensions.
look my code :
<?php
ob_start();
$_SESSION['nomecomp'] = $_POST['nomecomp'];
$email_env = $_POST['email_env'];
if (isset($email_env)) {
//variaveis vindas da pagina
$varcritico = $_POST['varcritico'];
$nomecomp = $_POST['nomecomp'];
$chapa = $_POST['chapa'];
$funcao = $_POST['funcao'];
$setor = $_POST['setor'];
$unidade = $_POST['unidade'];
$deschelp = $_POST['deschelp'];
//variveis do modal
//$email_env = $_POST['email_env'];
//$senha_env = $_POST['senha_env'];
<td>$deschelp</td>
</tr>
</table>'";
/**
* PHPMailer multiple files upload and send example
*/
$msg = '';
//if (array_key_exists('userfile', $_FILES)) {
// Create a message
// This should be somewhere in your include_path
include ("lib/PHPMailerAutoload.php");
$mail = new PHPMailer();
i have tried add some codes , but dont made sucess , for example , could i try push the array and see if the extension are inside some array ?
thanks.
Presuming you want to check the uploaded file types before moving them:
$AllowedFileTypes = array("pdf","txt"); // build array
$FileName = $_FILES['userfile']['name']; // get filename of file input
$FileType = end((explode(".", $FileName))); // get file type/extension
if(in_array($FileType, $AllowedFileTypes)){ // check to see if file type is allowed
// perform copy/move file
}
else{
// ignore/alert/whatever
}
Note: You may have to amend the variables to suit your requirements.
If you wish to validate the file type/extension before submitting the form, take a look at jQuery validation for file input: https://stackoverflow.com/a/20929391/715105

CodeIgniter Send Multiple Attachment Maximum File Size

What is the maximum file size in sending an email with attachment in codeigniter?
When i test my website it will only accept 24MB file attachment but i have more than 24MB. What is the best solution for this matter? THANKS!
$id = 17;
$email = "stephencabalida80#gmail.com";
$this->load->library('email');
$attach = $this->m_admin->getAttachment($id);
$this->email->from('office#escaperoomfactory.net', 'Escaperoom Factory');
$this->email->to(urldecode($email));
$this->email->subject('Escaperoom Files');
$this->email->message('Hi, Thank you for purchasing our game/s. Have Fun!');
$path = 'upload/'.$id;
foreach ($attach as $row) {
$this->email->attach("".$path.'/'.$row->name."");
}
$this->email->send();`

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.

Why is PHPmailer not sending the attachment?

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.

Categories