PHP Mailer send an mysql blob object - php

I am storing a pdf or text file in mysql blob object, and I am trying to send that as a attachment in the mail using php mailer.
I am sending the mail like .
$mail->AddAddress($pr_email);
$mail->Subject = "Meeting Invitation -$meeting_name";
$mail->AddStringAttachment($data);
$mail->IsHTML(true);
$mail->Body =$message;
if(!$mail->Send())
{
$message= "Error sending: " . $mail->ErrorInfo;
header("Location:userprofile.php?Message={$message}");
}
Where $data came from
$tmpName = $_FILES['image']['tmp_name'];
$fp = fopen($tmpName, 'r');
$data = fread($fp, filesize($tmpName));
$data = addslashes($data);
fclose($fp);
$query = "UPDATE demo_meeting SET attachment='$data' where meetingID='$mtngid'";
$results = mysql_query($query);
Now I am receiving the mail as an attachment but content is not there, it is only showing 0K.
Please tell me what I might be doing wrong.

As I can see here in StackOverflow, you have ot pass additional parameters to AddStringAttachment: the mime type and the file name.
$filename="test.png";
$encoding = "base64";
$type = "image/png";
$mail->AddStringAttachment(base64_decode($data), $filename, $encoding, $type);
Also, NEVER use addslashes to "secure" a mysql field, you have to use mysql_real_escape_string instead (or, use PDO_MySQL driver which won't be marked obsolete anytime soon)

Related

PHPMailer, attachment settings can't access file (csv fiile)

I'm running a PHP script that runs a sequence of SQL queries, writes the results to CSV, and saves it. It also mails the report to a recipient.
The CSV portion of the code works perfectly, and the PHPMailer portion sends the test email with no problem. However, when I un-comment the attachment portion of PHPMailer and run the script it says "File could not be accessed". When I replace the comment, it writes the file and sends the test email again just fine.
The line in question, which I comment/uncomment accordingly, is: $mail->addAttachment($fp);
So, the two pieces are working, but this being my first time using PHPMailer, I'm not sure the best way to go about fixing this. As far as I can tell, I'm using the addAttachment code properly and I'm closing the CSV at the very end.
Any help is much appreciated.
The script:
if (!$result) die('Couldn\'t fetch records');
$num_fields = mysqli_num_fields($result);
$headers = array();
while ($fieldinfo = mysqli_fetch_field($result)) {
$headers[] = $fieldinfo->name;
}
$fp = fopen('dailyReportTestPHP.csv', 'w');
if ($fp && $result) {
fputcsv($fp, $headers);
while ($row = $result->fetch_array(MYSQLI_NUM)) {
fputcsv($fp, array_values($row));
}
}
$mail = new PHPMailer(true);
$address = "hnorman#jacksonfurnind.com";
try{
$mail->setFrom("hnorman#jacksonfurnind.com");
$mail->addAddress($address);
$mail->addAttachment($fp);
$mail->isHTML(true);
$mail->Subject = "Test";
$mail->Body = "Test";
$mail->Send();
echo 'message sent';
} catch (Exception $e){
echo 'message failed';
echo 'mail error:' . $mail->ErrorInfo;
}
fclose($fp);
It's because $fp is an open file handle; PHPMailer is expecting a string containing the path to the file to be passed to addAttachment(). So, move the fclose call to before you create the PHPMailer instance, and then do this:
$mail->addAttachment('dailyReportTestPHP.csv');

convert $_POST values to CSV

Updated Situation:
I have managed to create a registration form that outputs the data to a new CSV file for use into a separate database. However the code that sends the attachment doesn't work, but the system stores the file into a separate folder (I must stress this is while I am testing).
My question is, can I both create the CSV file and send it via email? If so, what do I need to do?
I am also aware that there are security risks: One suggestion has been to store the CSV files outside to root directory. is this foolproof and if not, could anyone make any recommendations?
My code is:
<?php
$_POST['password'] = md5($_POST['password']);
$headers=array_keys($_POST);
$file = "csv/" . $_POST['username'].date('Ymdhis').".csv"; //filename
$file = fopen($file, 'a');
fputcsv($file, $headers);
fputcsv($file, $_POST);
fclose($file);
require_once('email/PHPMailerAutoload.php');
$m = new PHPMailer;
$m->isSMTP();
$m->SMTPAuth = true;
$m->SMTPDebug = 0;
$m->Host = 'mymail.com';
$m->Username = 'me#mymail.com';
$m->Password = 'mypass';
$m->SMTPSecure = 'SSL';
$m->Port = 26;
$m->From = 'me#mymail.com';
$m->FromName = 'My name';
$m->addReplyTo('me#mymail.com', 'Reply Address');
$m->AddAddress('me#mymail.com', 'My name');
$m->isHTML(true);
$m->addAttachment('csv/data.csv', 'data.csv');
$m->Subject = 'New feed ';
$m->Body = '<p>This is an email just sent from our website</p><p><strong>Please import into your database.</strong></p>';
$m->AltBody = 'This is the body. Please import into the database';
if($m->send()) {
echo '<h1>Thank you</h1> <p>We have received your Registration and will send you confirmation details shortly.</p>';
} else {
echo $m->ErrorInfo;
}
I also have a checkbox field that needs to be written with the commas separating the values, for example 1,2,3. How can I write this?
Any assistance/advice will as always be gratefully received.
Many thanks in advance.
$_POST['id']="101"; //example data
$_POST['username']="kraysak"; //example data
$_POST['password']="grumpycat"; //example data
$_POST['usergroup']="admin"; //example data
$_POST['lastaccess']="14-10-2014 00:01"; //example data,
$_POST['password'] = md5($_POST['password']);
$headers=array_keys($_POST);
$file = $_POST['username'].date('Ymdhis').".csv"; //filename
$file = fopen($file, 'a');
fputcsv($file, $headers ); //write headers (key of the $_POST array (id,username,password,etc)
fputcsv($file, $_POST );
fclose($file);
this create a file named kraysak20141014010253.csv with the next information:
id,username,password,usergroup,lastaccess
101,kraysak,5557981401e83c1963412f19c7487965,amdin,"14-10-2014 00:01"
is hard for me to explain, (my english isn't good enought) but fputcsv funtion write the content of an array in the file, and $_POST is an array... so, you dont need to create new variables, you only need to use md5() function in one variable.
fputcsv consists of two parameters; location and content. So;
fputcsv(location, content);
or
$fileNameVariable = 'blah';
$fileName = $fileNameVariable . date('Ymdhis') . '.csv';
$fp = fopen('/exampleDirectoryName/' . $fileName, 'w');
$headers = array ('info1', 'info2', 'info3');
fputcsv($fp, $headers);
You can adapt this exmaple for your situation pretty easily.
Try:
$csvname=md5(rand());
$fp = fopen("csv/$csvname.csv", "w");
$savearray = [ $name, $email, $password, $usergroup, $lastsid, $fname, $lname, $lastaccess, $company, $phone, $addone, $addtwo, $city, $stateprov, $country, $postalcode, $rescom, $addbook, $subscriptions, $affilid, $affilcommpct, $affilsalestodate, $affilcommearned, $affilcommowed, $affilcommpaid, $whlsalepct, $show_currency, $loyaltypoints ];
fputcsv($fp, $savearray);
fclose($fp);
Use array() on $savearray instead of [] for older php versions.

Save email attachment from piped email

I am using pipe to program to send emails to a script. Using this script, I can sucessfully save the entire email as a .txt file on my server. The only thing left to do, is figure out how to save any attachment that the email comes in with. (This email address is only given to one trusted source, so security is not an issue)
Working code that saves entire email as .txt file:
$fd = fopen("php://stdin", "r");
$email = ""; // This will be the variable holding the data.
while (!feof($fd)) {
$email .= fread($fd, 1024);
}
fclose($fd);
/* Saves the data into a file */
$fdw = fopen("/home/lmshost22/public_html/pipemail.txt", "w+");
fwrite($fdw, $email);
fclose($fdw);
Can anyone help me with code that simply extracts the attachment (will ALWAYS be a .csv file) and saves it on my server?
Here is the code that the .txt file shows for the attachment:
------=_NextPart_000_0133_01CE0E98.061E7400
Content-Type: application/vnd.ms-excel;
name="leads.csv"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="leads.csv"
ApplicationDetailId,DateCreated,VehicleInfoId,FirstName,MiddleName,LastNa=
me,Suffix,Street,City,State,ZipCode,Email,HomePhoneArea,HomePhonePrefix,H=
omePhoneSuffix,CellArea,CellPrefix,CellSuffix,WorkPhoneArea,WorkPhonePreF=
ix,WorkPhoneSuffix,AmountBorrow,IsVehiclePaidOff,IsVehicleSalvaged,OweAmo=
unt,TitleOwnership,IsInBankruptcy,IsInCreditCounseling,HearOfUs,VehicleIn=
foId,Year,Make,Model,Trim,Miles,Engine,DriveTrain,Transmission,Options,Bo=
ok,ClassCode,Door,FuelType,BodyStyle
4523,2/18/2013 2:56:33 PM,4524,James,,Pruitt,,7900 =
Carmelita,Atascadero,CA,93422,,702,=3D"353",=3D"9760",=3D"",=3D"",=3D"",=3D=
"",=3D"",=3D"",=3D"2500.0000",True,False,0.0000,No =
one,False,False,Google,4524,2001,=3D"Toyota",Tacoma =
Xtracab,PreRunner,200000,V6 3.4 =
Liter,2WD,Automatic,199443~199448~199471~199480~199508~4234190~,0.0000,1,=
0,Gas,Pickup
------=_NextPart_000_0133_01CE0E98.061E7400--
Attachments imply that the message is MIME/Multipart and has a boundary header set which will delimit the various message parts. eg:
Content-Type: multipart/mixed;
boundary="b1_bb1b331cd6dafa1dc6a19e3b2e090b07"
So you want to find that first via something like:
preg_match('/boundary="(.*)"/', $message, $matches);
The message is divided by -- concatenated with the boundary, followed by headers specific to that part, a blank line, and then the data. eg:
--b1_bb1b331cd6dafa1dc6a19e3b2e090b07
Content-Type: application/pdf; name="Invoice-37272.pdf"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="Invoice-37272.pdf"
// base64 data here //
And the message is terminated with '--' . $boundary . '--', eg: --b1_bb1b331cd6dafa1dc6a19e3b2e090b07--
So you can use those two bits of info to break up your messages into their constituent parts and find/save the attachment.
here is my entire PHP file to extract a csv file(email with .csv attachment is piped to this script). The key is you have to decode the text that makes up the file, it is between the boundaries mentioned above.
<?
$home_path = '/home/USERNAME/public_html/DIRECTORY/';
$filename = "FILENAME.TXT"; // TO SAVE THE CONTENTS OF CSV FILE AS TEXT
$sock = fopen ("php://stdin", 'r');
$email = '';
while (!feof($sock)) {
$email .= fread($sock, 10240);
}
fclose($sock);
$encoding1 = explode ("------=_", $email);
$encoding2 = explode ("------=_", $encoding1[2]);
$encoding3 = $encoding2[0];
$encoding4 = explode (".csv", $encoding3);
$encoding5 = explode ("\n\n", $encoding4[2]);
$encoding = base64_decode($encoding5[1]);
$encoding = $encoding . "---" . strlen($encoding);
$fdw = fopen($home_path . $filename . ".txt", "w+");
fwrite($fdw, $encoding);
fclose($fdw);
?>

PHP email interception not sending email with attachments

I have set email interception on my server.
following is my email forwarder set on server
testemail#my.server.com,"/home/server/php_pipe_mail.php"
following is my code for php_pipe_mail.php
#!/usr/bin/php -q
<?php
require_once('mimeDecode.php');
include('sql-connect.php');
error_reporting(E_ALL);
ob_start();
$raw_email = '';
if (!$stdin = fopen("php://stdin", "R"))
{
echo "ERROR: UNABLE TO OPEN php://stdin \n";
}
// ABLE TO READ THE MAIL
else
{
while (!feof($stdin))
{
$raw_email .= fread($stdin, 4096);
}
fclose($stdin);
}
$raw_email = preg_replace('/ +/', ' ', $raw_email);
var_dump($raw_email);
$buf = ob_get_contents();
$params['include_bodies'] = true;
$params['decode_bodies'] = true;
$params['decode_headers'] = true;
$params['input'] = $buf;
$params['crlf'] = "\r\n";
//Creating temp file on server
$myFile = "amail.txt";
$fh = fopen($myFile, 'w') or die("can't open file");
fwrite($fh, $buf);
fclose($fh);
//Generating mail structure in object format
$structure = Mail_mimeDecode::decode($params);
$attachment = array();
$mail_date= date( 'Y-m-d H:i:s', strtotime($structure->headers['date']) );
$from = $structure->headers['from'];
$to = $structure->headers['to'];
$subject = htmlentities($structure->headers['subject'],ENT_QUOTES);
if($structure->ctype_primary == "multipart")
{
$body_text = $structure->parts[0]->parts[0]->body;
$body_html = $structure->parts[0]->parts[1]->body;
$x = 0;
//fetch attachment
foreach ($structure->parts as $part) {
// only save if an attachment
if (isset($part->disposition) and ($part->disposition=='attachment')) {
$attachment[$x]["filename"] = $part->d_parameters['filename'];
$attachment[$x]["content_type"] = $part->ctype_primary . "/" . $part->ctype_secondary;
$attachment[$x]["body"] = addslashes($part->body);
$x++;
}
}
}
else
{
$body_text = $structure->parts[0]->body;
$body_html = $structure->parts[1]->body;
}
$qry1 = "insert into mail_buffer(mail_date,mail_from, mail_to,mail_subject,mail_text_body,mail_html_body) Values('". $mail_date ."','".$from."','".$to."','".$subject."','".$body_text."','".$body_html."')";
mysql_query($qry1) or die(mysql_error($con));
$last_id = mysql_insert_id();
if(count($attachment) > 0)
{
for($i=0; $i < count($attachment); $i++)
{
$qry = "insert into mail_attachment(email_id,content_type, file_name,body) Values('". $last_id ."','".$attachment[$i]['content_type']."','".$attachment[$i]['filename']."','".$attachment[$i]['body']."')";
mysql_query($qry) or die(mysql_error($con));
}
}
mysql_close($con);
ob_end_clean();
?>
Now above script works perfectly fine.
I am able to fetch message header, body and attachments and can store them in database without any problems.
When email without attachments come everything works fine and email is delivered to email address I am intercepting.
But following is not working.
When email with attachments comes than email content is being stored in database but email is not delivering to email address I am intercepting and I am getting following error message in bounce back email.
A message that you sent could not be delivered to one or more of its
recipients. This is a permanent error. The following address(es) failed:
pipe to |/home/server/php_pipe_mail.php
generated by testemail#my.server.com
Can anyone help me regarding the matter.
Thanks.
Could it be that, when an attachment is present, your script is echoing something? I have had problems piping emails before, and seen failure messages returned to senders, and they have been due to the piping script producing some kind of output. Maybe your error_reporting(E_ALL); is allowing the script to produce an output - try error_reporting(0);

CSV file_get_contents sending PHP

I'm trying to send a .CSV file with PHP. The file is written to disk before it's sent but when I try to attach the file with file_get_contents(); the structure of the .CSV isn't preseved yet when try and send the file that's created before it's sent I get a resource id (#183) so how can i attach a file which the user can open as a .CSV file? I've made sure the mime type and headers are correct
EDIT
if(!file_exists(_PS_ORDERS_DIR_.$orderDate.'/'.$file_name.'.csv'))
{
if($file = fopen (_PS_ORDERS_DIR_.$orderDate.'/'.$file_name.'.csv', 'x+'))
{
foreach ($list as $fields)
{
fputcsv($file, $fields);
}
$attachment['mime'] = 'application/vnd.ms-excel';
$attachment['content'] = file_get_contents(_PS_ORDERS_DIR_.$orderDate.'/'.$file_name.'.csv');
$attachment['name'] = $order.'order';
Mail::Send(1, 'order_conf', 'Order CSV Attachment', $success, 'dan.farr#gmail.com', CakeToppers, NULL, NULL, $attachment);
return true;
}
If you are using Swift Mailer, there is no need for file_get_contents(), you can just attach the file directly.
From the Swift Mailer documentation:
//Create the attachment
// * Note that you can technically leave the content-type parameter out
$attachment = Swift_Attachment::fromPath('/path/to/image.jpg', 'image/jpeg');
//Attach it to the message
$message->attach($attachment);
So for you that would be:
$attachment = Swift_Attachment::fromPath(_PS_ORDERS_DIR_.$orderDate.'/'.$file_name.'.csv', 'application/vnd.ms-excel');
//Attach it to the message
$message->attach($attachment);

Categories