PHP Mail xlsx-file created with PHPExcel as attachment - php

So I'm trying to generate and save an Excel-file to the server. This works flawlessly with PHPExcel. The next step is to read the file, e-mail it as an attachment and then delete it.
For some reason, PHP does not recognize xlsx as a proper file:
/* excel is generated before here */
$filename = "/results/excel/export-" . $today . ".xlsx";
$writer = new PHPExcel_Writer_Excel2007($exc);
$writer->save($filename);
/* so far so good; the file is created and exists on the server */
$to = "someone#domain.com";
$sendermail = "no-reply#domain.com";
$from = "Sender <" . $sendermail . ">";
$subject = "Email with attachment";
$message = "Here you go";
$file = $filename;
$semi_rand = md5(time());
$mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";
$headers = "From: $from";
$headers .= "\nMIME-Version: 1.0\n" . "Content-Type: multipart/mixed;\n" . " boundary=\" {$mime_boundary}\"";
$message = "--{$mime_boundary}\n" . "Content-Type: text/plain; charset=\"iso-8859-1\"\n" .
"Content-Transfer-Encoding: 7bit\n\n" . $message . "\n\n";
if(is_file($file)) {
$message .= "--{$mime_boundary}\n";
$fp = #fopen($file, "rb");
$data = #fread($fp, filesize($file));
#fclose($fp);
$data = chunk_split(base64_encode($data));
$message .= "Content-Type: application/octet-stream; name=\"" . basename($file). ";\n" . "Content-Transfer-Encoding: base64\n\n" . $data . "\n\n";
$message .= "--{$mime_boundary}--";
$returnpath = "-f" . $sendermail;
mail($to, $subject, $message, $headers, $returnpath);
} else {
echo("This is not a file: " . $file);
}
Which always gives me "This is not a file...". How do I read the XLSX-file?

here's a tip to prompt the excel and also send the file as an attachment without saving the file on server:
$objWriter = PHPExcel_IOFactory::createWriter ($objPHPExcel, 'Excel2007');
$objWriter->save('php://output');
$data = ob_get_contents();
$sendmail=new ExcelMail($data); //this is your mail class; if you use zend mail use addattachement($data); and Zend_Mime

The outputted message means is_file() is failing . This can happen for a number of reasons, but as far as I know not because the file format. As such, I would recommend looking into the following things:
Is the file actually there? You say you have the file saved, but you have to make sure it actually is.
Is the file path the xslx file is using correct?
Is the file path to the xslx file to the actual xml file and not to a symlink to it?
Are the permissions of the xslx file set so that the php script is allowed to acces them?
I believe it has to be one of those problems...

Okay, I found out what it was. $filename was actually a direct (http://...) link to the file, not a relative link. Changed it to be relative and it worked :).

Related

Can't open pdf files created with mpdf in mail

I am trying to create a pdf document using mpdf and in the first step I tried to save it in my downloads folder and then I tried to open it and it worked perfect. I can see what I need in the pdf document.
In the next step I tried to send the pdf as an attachment and the email was sent successfully with the pdf attachment but when I tried to open it from the mail its returning me an error something as "Adobe cannot open the pdf document because it is neither a supported file type or the file is damaged.......".
I searched for different questions in stackoverflow and I tried their valuable answers too but none of them helped me.
The below is the same question but the answer posted there too didn't helped me.
Stackoverflow questions related to my post
Few Links Which I followed
Here's my code:
$mpdf=new mPDF( );
$mpdf->SetDisplayMode('fullpage');
$mpdf->list_indent_first_level = 0;
$mpdf->WriteHTML($html,2);
ob_clean(); // **Tried this from Stackoverflow answers**
$mpdf->Output($filename.'.pdf', 'I');
$mailto = $row['Email1'].",".$row['Email5'];
$path = 'C:\\Users\\Downloads\\';
$file = $path."/".$filename;
$subject = 'Test Email';
$message = 'Test <br> Case';
$content = file_get_contents($file);
$content = chunk_split(base64_encode($content));
$separator = md5(time());
$eol = PHP_EOL;
$headers = "From: John <john.xxxxx#gmail.com>".$eol;
$headers .= "MIME-Version: 1.0".$eol;
$headers .= "Content-Type: multipart/mixed; boundary=\"" . $separator . "\"".$eol.$eol;
// message
$body .= "Content-Transfer-Encoding: 7bit".$eol;
$body .= "This is a MIME encoded message.".$eol;
$body = "--" . $separator.$eol;
$body .= "Content-Type: text/html; charset=\"UTF-8\"".$eol;
$body .= "Content-Transfer-Encoding: 8bit".$eol.$eol;
$body .= $message.$eol;
// attachment
$body .= "--" . $separator.$eol;
$body .= "Content-Type: application/octet-stream; name=\"" . $filename . '.pdf' . "\"".$eol;
$body .= "Content-Transfer-Encoding: base64".$eol;
$body .= "Content-Disposition: attachment".$eol.$eol ;
$body .= $content.$eol;
$body .= "--" . $separator . "--";
//SEND Mail
if (mail($mailto, $subject, $body, $headers)) {
//echo "mail send ... OK"; // or use booleans here
}
Have you tried changing the mime-type you set for the attachment?
The standard mime-type for pdf files is:
application/pdf
I noticed you are trying to load a file from local file system. Does the script run on the same machine? Or on a webserver?
If it runs on a webserver you might need to upload the file to the webserver first. You'll need to change the $path and $file variables once uploaded.
$path = 'www/images/[some-path]';
$file = '/'.$filename;
If it runs on the same machine as where the file is located, you might need to update the $file variable so it uses a backslash \ instead of the forward slash.
$path = 'C:\\Users\\Downloads\\';
$file = $path.'\\'.$filename;
Another error in your script: You never set the mpdf contents as the content for the email attachment. Try something like:
$content = chunk_split(base64_encode($mpdf->Output($filename.'.pdf', 'I')));
You'll have to check if the I in the Output() function of mpdf is correct for this use. I'm not sure of that.
EDIT
// First save it to the server somewhere
$mpdf->Output($filename.'.pdf', 'F'); // Make sure the path is valid and writing permissions are set correctly to prevent writing errors.
// Then get the contents from the PDF
$content = chunk_split(base64_encode($mpdf->Output($filename.'.pdf', 'S')));

Unable to attach pdf to email in php

I've tried to follow the examples given in this forum, like the example given by freestate here - Error with PHP mail(): .
Below is my code copied from his revised example. It emails fine. And an attachment is shown in the email when received. However it cannot be opened and is always 125k in size.
I have verified that a file size is returned with "$file_size = filesize($file);". Also that the "fopen" does open the stream. In fact before I added the Multipart to the header, I could see the content in the body of the text (albeit not readable).
I'm only trying to attach a basic pdf file, on a window's platform (windows 10), Apache 2.4, PHP 5.6.16.0.
What would cause the attachment to fail to attach properly?
emailer('//serverName/path/', 'documentName.pdf');
function eMailer($path, $filename)
{
$eol = PHP_EOL;
$to = "xxxx#yyyyyyyy.com";
$subject = "File Name: ".$filename;
$body = "The this the written content of the body";
$file = $path.$filename;
$file_size = filesize($file);
$handle = fopen($file, "r");
$content = fread($handle, $file_size);
fclose($handle);
$content = chunk_split(base64_encode($content));
$uid = md5(uniqid(time()));
$header = "From: NameOfPerson <their#emailAddress.com>".$eol.
"MIME-Version: 1.0\r\n".
"Content-Type: multipart/mixed; boundary=\"".$uid."\"";
$message = "--".$uid.$eol.
"Content-Type: text/html; charset=ISO-8859-1".$eol.
"Content-Transfer-Encoding: 8bit".$eol.$eol.
$body.$eol.
"--".$uid.$eol.
"Content-Type: application/pdf; name=\"".$filename."\"".$eol.
"Content-Transfer-Encoding: base64".$eol.
"Content-Disposition: attachment; filename=\"".$filename."\"".$eol.
$content.$eol.
"--".$uid."--";
echo (mail($to, $subject, $message, $header))?'success':'failure';
}
So after spending considerable time trying to solve the attachment problem by myself, I decided to use one of the two common packages out there PHPMailer and Swiftmailer. Both seemed pretty good. I work on just one enterprise project and I do not have Composer installed. So I wanted something easy to download and plug into my project manually. After reading the installation instructions for swiftmailer, I decided this would be easy for me to install and use.
These are the steps I took
I downloaded the Swiftmailer zip file from Github
From the unzipped file I copied the "lib" folder right into my project "C:\myproject\lib"
Then I read the usage instructions in the online manual
To use it in my project all I needed to do was include it in my code like this:
function eMailer($path, $filename, $mailto, $subject, $message, $user)
{
$file = $path.$filename;
require_once 'C:\myProject\lib\swift_required.php';
// Create the SMTP configuration
$transport = Swift_SmtpTransport::newInstance("mymail_server_address ie: 192.111.22.33", 25);
$transport->setUsername($user['email']);
$transport->setPassword($user['password']);
// Create the mail transport configuration
$transport = Swift_MailTransport::newInstance();
// Create the message
$message = Swift_Message::newInstance();
$message->setTo(array(
$mailto['email']=> $mailto['name']
));
$message->setSubject($subject);
$message->setBody($message);
$message->setFrom($user['email'], $user['name']);
$message->attach(Swift_Attachment::fromPath($file));
// Send the email
$mailer = Swift_Mailer::newInstance($transport);
$mailer->send($message);
}
This obviously has much more capabilities than I need right now, but if in the future I need a mailer function in another part of my project it's there ready for me to use.
Try below code:
$name = "Name";
$email = "Email Address";
$to = "$name <$email>";
$from = "XYZ";
$subject = "TEST SUBJECT";
$mainMessage = "Hi, here's the file.";
$fileatt = "./test.pdf";
$fileatttype = "application/pdf";
$fileattname = "newname.pdf";
$headers = "From: $from";
// File
$file = fopen ( $fileatt, 'rb' );
$data = fread ( $file, filesize ( $fileatt ) );
fclose ( $file );
// Attach the file
$semi_rand = md5 ( time () );
$mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";
$headers .= "\nMIME-Version: 1.0\n" . "Content-Type: multipart/mixed;\n" . " boundary=\"{$mime_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" . $mainMessage . "\n\n";
$data = chunk_split ( base64_encode ( $data ) );
$message .= "--{$mime_boundary}\n" . "Content-Type: {$fileatttype};\n" . " name=\"{$fileattname}\"\n" . "Content-Disposition: attachment;\n" . " filename=\"{$fileattname}\"\n" . "Content-Transfer-Encoding: base64\n\n" . $data . "\n\n" . "-{$mime_boundary}-\n";
// Send Email
if (mail ( $to, $subject, $message, $headers )) {
echo "The email was sent.";
} else {
echo "There was an error sending the mail.";
}

php email attachment sends an empty file

I'm trying to send an attachment via email but, even though the right file is saved in the server, the one attached to the email is empty (0 kb).
I'm using gmail to send the emails.
Here is the relevant part of my code:
if (empty($error)) {
//boundary
$semi_rand = md5(time());
$mime_boundary = "==Multipart_Boundary_x$semi_randx";
//tell the headers about the boundary
$header .= "\nMIME-Version: 1.0\n" . "Content-Type: multipart/mixed;\n" . " boundary=\"$mime_boundary\"";
//define the first part of the email, which is the text part
$message = "\r\n" . "--$mime_boundary\n" . "Content-Type: text/plain; charset=\"iso-8859-1\"\n" . "Content-Transfer-Encoding: 7bit\r\n" ;
//build the body of the 1st part of the email
$content_body = "
Email del formulario de contacto en ".home_url().": <br />
//whatever
";
$message .= $content_body . "\r\n";
$message .= "--$mime_boundary\n";
//define the second part of the email, which is the atachments
//if a file has been uploaded
if (!empty($_FILES['cv']['name'])){
// Open the file for a binary read
$file = fopen($temp_name,'rb');
// Read the file content into a variable
$data = fread($file,filesize($temp_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));
// Actually build the second part of the email
$message .= "Content-Type: \"application/octet-stream\";\r\n name=\"" . $file_name . "\"\n";
$message .= "Content-Transfer-Encoding: base64\n";
$message .= "Content-Disposition: attachment;\r\n filename=\"" . $file . "\"\r\n\r\n";
$message .= $data; //The base64 encoded message
$message .= "\n";
$message .= "--$mime_boundary--\n";
}
//send th email
mail( $receive_email, "Email del formulario de contacto en web", $message, $header);
$msg = $succesful_text;
}
My guess is that I'm doing something wrong here:
$message .= "Content-Type: \"application/octet-stream\";\r\n name=\"" . $file_name . "\"\n";
$message .= "Content-Transfer-Encoding: base64\n";
$message .= "Content-Disposition: attachment;\r\n filename=\"" . $file . "\"\r\n\r\n";
$message .= $data; //The base64 encoded message
$message .= "\n";
$message .= "--$mime_boundary--\n";
But I have no idea what it can be.
I know I can use a library, but I would like to see what is wrong with my code just for the sake of learning.
Any help will be highly appreciated.
Sonia
Thanks Cherry and miken32 for your replies.
Finally I figured it out.
This is what happened, in case it can help somebody else in a future.
As there was no base64 encoded data in the text message, I thought the problem might no be in the $message text but in the actual handling of the file.
// Open the file for a binary read
$file = fopen($temp_name,'rb');
// Read the file content into a variable
$data = fread($file,filesize($temp_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));
I realized the temp file was not being opened. I couldn't see why but I solved it by handling directly the file from the uploads folder.
Here is the fixed code:
// Open the file for a binary read
$file = fopen($server_file,'rb');
// Read the file content into a variable
$flsz=filesize($server_file);
$data = fread($file,$flsz);
// close the file
fclose($file);
// Now we need to encode it and split it into acceptable length lines
$data = chunk_split(base64_encode($data));
I also had to modify the filename in the $message text, using $file_name instead of $file because $file.
$message .= "Content-Disposition: attachment;\r\n filename=\"" . $file_name . "\"\r\n\r\n";

Renaming Files after a move

I'm trying to rename a file while it is being moved into an "old" folder using a .cmd file and a .php file. This file is being e-mailed in a batch job and then moved into the old folder with the previous month and current year at the end of the report. Right now: The files are being e-mail correctly, and moved into the old folder, however the file name is not being renamed when it enters the "old" folder. Can anyone make any suggestions to my code? I can't seem to find out where the error is. Thanks
My code for .CMD file:
REM Email the 2 monthly stats files regarding gtwinapps
REM The report is sent at 9:20 AM every first monday of every month
REM in C:\Smurf_Reports\gtwinapps\Monthly_Stats
"c:\Program Files\xampp\php\php.exe" d:\batch\monthly_smurfreport_gtwinapps.php
move C:\Smurf_Reports\gtwinapps\Monthly_Stats\gtwinapps_statsmonthly.csv C:\Smurf_Reports\gtwinapps\Monthly_Stats\old
My code for .PHP file:
/*This application pickups up *.csv files from Monthly_Stats folder and then sends email to ops Support at ops.support#scotiabank.com.
The command file associated with this php file moves the .csv file into the "OLD" folder in the same directory
*/
$dirpath = "C:/Smurf_Reports/gtwinapps/Monthly_Stats/";
/* Renaming the batch job file to display the previous month and year once it is moved into the "OLD" folder for clarity purposes */
rename ("C:\Smurf_Reports\gtwinsapps\Monthly_Stats\gtwinapps_statsmonthly.csv", "C:\Smurf_Reports\ gtwinapps\Monthly_Stats\old\monthly_gtwinapps_" . date("F_Y", strtotime("-1 month")) . ".csv");
rename ("C:\Smurf_Reports\gtwinsapps\Monthly_Stats\monthly.csv", "C:\Smurf_Reports\gtwinapps\Month ly_Stats\old\gtwinapps_statsmonthly_" . date("F_Y", strtotime("-1 month")) . ".csv");
if ($handle = opendir($dirpath ))
{
$semi_rand = md5(time());
$mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";
$headers .= "\nMIME-Version: 1.0\n" .
"Content-Type: multipart/mixed;\n" .
" boundary=\"{$mime_boundary}\"";
$email_message = "This is a multi-part message in MIME format.\n\n" .
"--{$mime_boundary}\n" .
"Content-Type:text/html; charset=\"iso-8859-1\"\n" .
"Content-Transfer-Encoding: 8bit\n\n" .
$message_text . "\n\n";
$email_message .= "--{$mime_boundary}\n";
/* This is the correct way to loop over the directory. */
while (false !== ($entry = readdir($handle)))
{
if (strpos($entry, '.csv',1))
{
$filepath = "";
$filesize = 0;
$filepath = $dirpath."".$entry;
$filesize = filesize ($filepath);
if (file_exists($filepath) && $filesize > 1)
{
$fileatt = $filepath;
$fileatt_name = $entry;
$fileatt_type = "application/octet-stream";
$message_text .= "<P>Hi</P>";
$file = fopen($fileatt,'rb');
$data = fread($file,filesize($fileatt));
fclose($file);
$data = chunk_split(base64_encode($data));
$email_message .= "Content-Type: {$fileatt_type};\n" .
" name=\"{$fileatt_name}\"\n" .
"Content-Disposition: attachment;\n" .
//" filename=\"{$fileatt_name}\"\n" .
"Content-Transfer-Encoding: base64\n\n" .
$data . "\n\n";
$email_message .= "--{$mime_boundary}\n";
}
$email_from = "ops.support#yahoo.com";
// $email_to = "ops.support#yahoo.com";
$email_to = "k.j#yahoo.com,g.h#yahoo.com";
$lastMonth = date('F-Y',strtotime('last month'));
$email_subject = "($lastMonth) Monthly Smurf Report for GTWINAPPS.";
$headers .= "From: ".$email_from."\r\n";
echo $filepath."</br>";
}
}
closedir($handle);
$ok = #mail($email_to, $email_subject, $email_message, $headers);
}
In your rename function, you need to either (A) escape your backslashes (\\), or (B) use forward slashes for directory separators

Attach file from the server into email

can anyone give me some idea how to attach a file from the server and send it as attachment through email??
i have the following code:
<?php
// Read POST request params into global vars
$to = $_POST['to'];
$from = $_POST['from'];
$subject = $_POST['subject'];
$message = $_POST['message'];
// Obtain file upload vars
$fileatt = $_FILES['fileatt']['tmp_name'];
$fileatt_type = $_FILES['fileatt']['type'];
$fileatt_name = $_FILES['fileatt']['name'];
$headers = "From: $from";
if (is_uploaded_file($fileatt)) {
// Read the file to be attached ('rb' = read binary)
$file = fopen($fileatt,'rb');
$data = fread($file,filesize($fileatt));
fclose($file);
// Generate a boundary string
$semi_rand = md5(time());
$mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";
// Add the headers for a file attachment
$headers .= "\nMIME-Version: 1.0\n" .
"Content-Type: multipart/mixed;\n" .
" boundary=\"{$mime_boundary}\"";
// Add a multipart boundary above the plain message
$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";
// Base64 encode the file data
// Add file attachment to the message
$message .= "--{$mime_boundary}\n" .
"Content-Type: {$fileatt_type};\n" .
" name=\"{$fileatt_name}\"\n" .
//"Content-Disposition: attachment;\n" .
//" filename=\"{$fileatt_name}\"\n" .
"Content-Transfer-Encoding: base64\n\n" .
$data . "\n\n" . "--{$mime_boundary}--\n";
}
// Send the message
$ok = #mail($to, $subject, $message, $headers);
if ($ok) {
echo "<p>Mail sent! Yay PHP!</p>";
} else {
echo "<p>Mail could not be sent. Sorry!</p>";
}
?>
but this code does not attach file from the server.
please help me out.. thanks in advance..!!
One question: Do you want to send e-mails with attachment or do you want to improve your PHP skills with this problem?
If you only want to send mails, have a look at PHPMailer which is very good and easily to handle. For myself I'm using this for years without problems.
For improving your skills: You say that the attachment is encoded in base64, but I cannot find the line where you do something like $data = base64_encode($data); You add the $data of your attachment in plain to the mail.

Categories