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');
Related
I have PHPMailer setup to use our Outlook365 server to send emails with attachments. It works great until the script, using imap_append, attempts to add the message to our "sent" folder. What I have discovered is that if the attachment is more than 7KB in size, it fails. Less than 7KB, it works. The recipient receives the attachment either way.
Any idea where this limitation is coming from and how I can increase it?
Here's the code block for saving the messages to the sent folder.
function save_mail($mail) {
global $config;
$MailHost = "{".$config->MailHost."/imap/ssl/novalidate-cert}Sent Items";
$path = $MailHost;
if ($conn = imap_open($path, $config->MailUsername, $config->MailPassword)) {
if (imap_append($conn, $path, $mail->getSentMIMEMessage())) {
$result = true;
} else {
error_log("ERROR: Unable to save mail to 'Sent Items' folder.\n - " . imap_last_error());
$result = false;
}
imap_close($conn);
return $result;
} else {
error_log("ERROR: Unable to connect to IMAP server.");
return false;
}
}
From my testing today, if sending to an Exchange based IMAP server with an attachment or embedded image greater than 7kb, you will need to change the line returns from unix format to windows format. I simply did a string replace on '\n' and replaced with '\r\n' to get this done.
$content = str_replace("\n", "\r\n", $mail->getSentMIMEMessage());
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.
I have a problem with batch file
if I access: http://localhost:8080/cron/cron.php
I got email sent with message Yeah, message send via Gmail
this my cron.php
<?php
require_once 'simplehtmldom\simple_html_dom.php';
require_once 'sites.php';
require_once 'send_mail.php';
ini_set('display_errors','on');
foreach ($site_list as $name => $link){
$command = "C:\\Python27\\python C:\\webcheck\\webcheck.py -o C:\\wamp\\www\\cron\\reports\\$name $link";
$output = shell_exec($command);
$log_file = "C:\\wamp\\www\\cron\\log.txt";
$fh = fopen($log_file,'w') or die('can not open file');
fwrite($fh, $output);
fclose($fh);
}
/*Scan folder for reporting */
$path = 'C:\\wamp\\www\cron\\reports\\';
$msg = '';
foreach (new DirectoryIterator($path) as $fileInfo) {
if($fileInfo->isDir() && !$fileInfo->isDot()) {
// Do whatever
$webcheck = $fileInfo->getFilename() ;
$html = file_get_html($path.$webcheck.'\\badlinks.html');
$es = $html->find('div[class="content"]', 0);
$msg .="<h2>BADLINKS $webcheck</h2>";
$msg .= $es->innertext; // Some Content
}
}
$subj = $_subj;
$to = $_to;
$from = $_from;
$name = $_name;
if (smtpmailer($to, $from, $name, $subj, $msg)) {
echo 'Yeah, message send via Gmail';
} else {
if (!smtpmailer($to, $from, $name, $subj, $msg, false)) {
if (!empty($error)) echo $error;
} else {
echo 'Yep, the message is send (after doing some hard work)';
}
}
?>
But with this cron.bat
C:\wamp\bin\php\php5.3.5\php C:\wamp\www\cron\cron.php
I go to cmdand type cron.bat
I got messsage Mail error: SMTP Connect() failed.
Do you have any idea?
Thanks
Remember that cron jobs will be using the PHP CLI. And the PHP CLI uses a different php.ini file to Apache.
Make sure you have all the required extension activated within this other php.ini file.
I would imagine the php_smtp extension is not activated.
Ahh I see you are using WAMP so the PHP CLI version of the php.ini file will be in c:\wamp\bin\php\php5.x.y\php.ini.
Where as the Apache version is in c:\wamp\bin\apache\apache2.x.y\bin\php.ini if you need to compare which extension you have activated in Apache PHP to those not activated in the PHP CLI
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)
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);