PHP - Dompdf and PHPMailer unexpected behavior - php

I am working on a web application using PHP as a server-side and a jQuery framework as a client-side.
One of the scenarios of the application is to send an email with pdf file attached I am doing this using PHPMailer and Dompdf libraries.
I had created a function named sendMail in a file name send.php accept 4 params (receiver email,subject,data,email number) the last param is because I have 5 different emails may be sent depending on the situation and data param is the data will be rendered in the html email body.
The problem is when I call the function from send.php it work as expected the email sent and pdf file created and attached to the email .
but when I require send.php in any other file and call sendMail function I get the email only without any pdf file and the file not even generated or saved on the server.
send.php
<?php
require_once 'dompdf/autoload.inc.php';
// reference the Dompdf namespace
use Dompdf\Dompdf;
require 'PHPMailerAutoload.php';
$body = "test message";
sendMail('peter#w34.co','MLS mail',$body,5);
function sendMail($email,$subject,$body,$index){
$mail = new PHPMailer;
$mail->IsSMTP(); // telling the class to use SMTP
$mail->SMTPDebug = 1; // debugging: 1 = errors and messages, 2 = messages only
$mail->SMTPAuth = true; // SMTP authentication
$mail->SMTPSecure = 'tls'; // secure transfer enabled REQUIRED for GMail
$mail->Host = "smtp.gmail.com"; // SMTP server
$mail->Port = 587; // SMTP Port
$mail->Username = "peterwilson.intake34#gmail.com"; // SMTP account username
$mail->Password = "Password"; // SMTP account password // TCP port to connect to
$mail->From = 'peter#example.com';
$mail->FromName = 'Wilson';
$mail->addAddress($email); // Add a recipient
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = $subject;
$mail->Body=$body;
// instantiate and use the dompdf class
$dompdf = new Dompdf();
$dompdf->loadHtml($body);
// Render the HTML as PDF
$dompdf->render();
$output = $dompdf->output();
$file_to_save= "../work-orderes/file.pdf";
file_put_contents($file_to_save, $output);
$mail->addAttachment('../work-orderes/file.pdf');
if(!$mail->send()) {
// echo $mail->ErrorInfo;
} else {
return 1;
}
}
?>
save.php
<?php
require("sendSmtp/send.php");
session_start();
$body = "Hello World!";
sendMail('peter#w34.co','MLS mail',$body,5);
?>
Any suggestions about why Dompdf not works when calling it from any other file ??
What I have tried
removing dompdf and reinstall the latest stable version from
here
cleaning all code and just leave sendMail function and calling it
try to write the code from the beginnig

I solved it finally!
after debugging I found that everything going fine till $output = $dompdf->output(); after that I get an error on save the file using $file_to_save= "../work-orderes/file.pdf";
this work properly when I call the function sendMail() from send.php but when I call it from another file I get an error regarding accessing the path.
The Answer here that I should use the absolute path not the relative one like below
$file_to_save= $_SERVER['DOCUMENT_ROOT']."\work-orderes/file.pdf";
now the file saved successfully and attached to the email like expected!

Related

Not able to attach the generated PDF in Php using FPDF

I am using FPDF and Phpmailer to generate a PDF file and sending it as an email attachment.
My script for PDF generation and phpmailer are working perfectly when I use them as independent scripts.
Now, when I combine both scripts to generate and display the PDF form (without saving it to to the filesystem) and send this PDF document as an attachment, it is not working thouht it generates the PDF and display it on browser, but does not sent it by mail.
My code is:
<?php declare(strict_types=1);
use PHPMailer\PHPMailer\PHPMailer;
require 'vendor/autoload.php';
$pdf = new mypdf();
$pdf->AliasNbPages();
$pdf->AddPage('P', 'A4', 0);
$pdf->Header();
$pdf->headerTable();
$pdf->viewTable();
$pdf->footer();
$pdf->setMargins(20, 20, 20);
$pdf->output();
$pdfString = $pdf->output();
$mail = new PHPMailer;
// getting post values
$first_name = $_POST['fname'];
$to_email = "receipent#gmail.com";
$subject = "stationery issued";
$message = "Dear sir your requested stationery has been issued by Stationery store ";
$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 = 'sender#gmail.com'; // SMTP username
$mail->Password = 'password'; // SMTP password
$mail->SMTPSecure = 'tls'; // Enable TLS encryption, `ssl` also accepted
$mail->Port = 25; // TCP port to connect to
$mail->setFrom('sender#gmail.com', 'Your_Name');
$mail->addReplyTo('sender#gmail.com', 'Your_Name');
$mail->addAddress($to_email); // Add a recipient
$mail->addStringAttachment((string)$pdfString, 'name file.pdf');
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = $subject;
$mail->Body = 'Dear ' . $first_name . '<p>' . $message . '</p>';
$mail->send();
You have left unclear which Phpmailer version you're using and which FPDF version, therefore it is hard to say what the error exactly is.
On first glance this hit my attention:
$pdfString = $pdf->output();
If the intend is to have $pdf->output() to return a string, then the invocation looks wrong to me.
That is because the invocation as $pdf->output() is doing the default output, which is sending to the browser.
Which you said is working, and that is already the line above:
$pdf->output();
$pdfString = $pdf->output();
PHP is an imperative language, that means, it does not make a difference to the method call whether or not you assign a variable to the return value.
So both method calls will behave the same:
$pdf->output();
$pdfString = $pdf->output();
It's like writing
$pdf->output();
$pdf->output();
Perhaps just an oversight in the heat of the debugging. For debugging, check the preconditions early, verify your script step-by-step. Don't ask longer than five minutes. Just verify then.
Potential fix:
$pdfString = $pdf->output('S');
may do it, better check with the documentation you have at hand for your version in use.

PHPMailer + HTML2PDF: pdf invalid and pj

Good morning all ,
I would like to attach a PDF created following a form with HTML2PDF then send it with PHMailer.
Everything works, the email goes well, I managed to create the PDF by saving it on my hard drive.
But when I try to attach it to my email, the pdf is fine in pj but I can't open it.
enter image description here
It is the same size of my locally created pdf.
I followed the tutorial and wiki of the two libraries, well I think ^^
Here is my PHPMailer code:
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require './vendor/phpmailer/phpmailer/src/Exception.php';
require './vendor/phpmailer/phpmailer/src/PHPMailer.php';
require './vendor/phpmailer/phpmailer/src/SMTP.php';
require './vendor/autoload.php';
// Instantiation and passing `true` enables exceptions
$mail = new PHPMailer(true);
$mail->CharSet = 'UTF-8';
try {
//Server settings
$mail->SMTPDebug = 0; // Enable verbose debug output
$mail->isSMTP(); // Send using SMTP
$mail->Host = '******'; // Set the SMTP server to send through
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = '*****'; // SMTP username
$mail->Password = '*****'; // SMTP password
//$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` encouraged
$mail->Port = ****; // TCP port to connect to, use 465 for `PHPMailer::ENCRYPTION_SMTPS` above
//Recipients
$mail->setFrom('****#****.com', '****');
$mail->addAddress($to); // Add a recipient
//$mail->addAddress('ellen#example.com'); // Name is optional
$mail->addReplyTo($shop_email, 'Votre magasin');
//$mail->addCC('cc#example.com');
$mail->addBCC($shop_email);
// Attachments
$mail->addStringAttachment($pdf_done, 'myPdf.pdf'); // Add attachments
//$mail->addAttachment('/tmp/image.jpg', 'new.jpg'); // Optional name
// Content
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = $subject;
$mail->Body = $message;
$mail->AltBody = strip_tags($message);
$mail->send();
echo '';
} catch (Exception $e) {
echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
}
?>
and here is the code for HTML2PDF:
ob_start();
// --> mon code HTML de creeation du PDF
$content = ob_get_clean();
require_once dirname(__FILE__).'/../vendor/autoload.php';
use Spipu\Html2Pdf\Html2Pdf;
use Spipu\Html2Pdf\Exception\Html2PdfException;
use Spipu\Html2Pdf\Exception\ExceptionFormatter;
try{
$pdf = new \Spipu\Html2Pdf\Html2Pdf('P', 'A4', 'fr');
$pdf->writeHTML($content);
$pdf_done = $pdf->output('myPdf.pdf', 'S');
}catch(\Spipu\Html2Pdf\Exception\Html2PdfException $e){
die($e);
}
?>
I tried adding ", 'base64', 'application / pdf'" in the addStringAttachment but it doesn't change anything.
Do you have any idea of my mistake?
Thank you all
Debug one thing at a time. First download the PDF manually and make sure it looks correct – if the PDF is bad to start with, emailing it isn't going to improve things. Next check that it is readable from PHP – for example serve it using readfile(). Then when you try to attach it, check the return value of your call to addAttachment() like this:
if (!$mail->addAttachment('/path/to/myPdf.pdf')) {
die('could not read PDF');
}
Also note the difference between addAttachment and addStringAttachment; you're adding a file that's been saved to disk, so you want the first one, not the second.

How to use PHPMailer without composer?

I'd like to use the latest PHPMailer library with require_once() instead of messing around with Composer. I'd like a pure xcopy deployment with minimal fuss.
Here's what I'm attempting to do:
require_once("src/PHPMailer.php");
$mail = new PHPMailer;
$mail->isSMTP();
$mail->SMTPDebug = 2;
$mail->Host = "smtp.gmail.com";
$mail->Port = 587;
$mail->SMTPSecure = 'tls';
$mail->SMTPAuth = true;
$mail->Username = $smtpUsername;
$mail->Password = $smtpPassword;
$mail->setFrom($emailFrom, $emailFromName);
$mail->addAddress($emailTo, $emailToName);
$mail->Subject = 'PHPMailer GMail SMTP test';
$mail->msgHTML("test body");
$mail->AltBody = 'HTML messaging not supported';
if(!$mail->send()){
echo "Mailer Error: " . $mail->ErrorInfo;
}else{
echo "Message sent!";
}
I get the error message: Fatal error: Class PHPMailer not found in [....]\EmailTester.php on line 21
Line 21 is this: $mail = new PHPMailer;
This line is just a guess on my part: require_once("src/PHPMailer.php"); - clearly I need to include some file or files, but I can't tell which.
I'm working from the gmail example on github which is also not included in the zip download. But I can navigate to it in github. In that example file it begins like this:
use PHPMailer\PHPMailer\PHPMailer;
require '../vendor/autoload.php';
$mail = new PHPMailer;
I see no autoload.php file in the zip download, and after googling all over I see this implies using Composer. But there must be some way to simply do an include and get the files I need.
A few things puzzle me about this PHPMailer library and perhaps github in general:
When I download PHP Mailer from GitHub, why are so many listed files and folders not included in the downloaded zip file?
Why do they reference autoload.php which doesn't exist in the zip download?
Clearly I don't understand some things about github, but why not provide a working code sample instead of referencing dependencies that don't exist in the download, forcing people to find it elsewhere and hope they can figure out how to come back and plug it in correctly?
In this YouTube video titled Send Emails with PHP & Gmail, he downloads the same zip I downloaded and from the same place, yet his zip contains different files, including PHPMailerAutoload.php. Why am I getting completely different files than he gets? That video was published March 4, 2017 -- so, less than 1 year ago -- has it really changed so much since then?
In summary: How can I get PHPMailer working without external dependencies and installations such as Composer, and instead use require_once() to get what I need?
Here's the full working example (though you see a few variables that must be defined and set):
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require 'src/Exception.php';
require 'src/PHPMailer.php';
require 'src/SMTP.php';
$mail = new PHPMailer;
$mail->isSMTP();
$mail->SMTPDebug = 2; // 0 = off (for production use) - 1 = client messages - 2 = client and server messages
$mail->Host = "smtp.gmail.com"; // use $mail->Host = gethostbyname('smtp.gmail.com'); // if your network does not support SMTP over IPv6
$mail->Port = 587; // TLS only
$mail->SMTPSecure = 'tls'; // ssl is depracated
$mail->SMTPAuth = true;
$mail->Username = $smtpUsername;
$mail->Password = $smtpPassword;
$mail->setFrom($emailFrom, $emailFromName);
$mail->addAddress($emailTo, $emailToName);
$mail->Subject = 'PHPMailer GMail SMTP test';
$mail->msgHTML("test body"); //$mail->msgHTML(file_get_contents('contents.html'), __DIR__); //Read an HTML message body from an external file, convert referenced images to embedded,
$mail->AltBody = 'HTML messaging not supported';
// $mail->addAttachment('images/phpmailer_mini.png'); //Attach an image file
if(!$mail->send()){
echo "Mailer Error: " . $mail->ErrorInfo;
}else{
echo "Message sent!";
}
This worked for me, I also downloaded phpmailer from this address
https://sourceforge.net/projects/phpmailer/
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
use PHPMailer\PHPMailer\SMTP;
require '/source/PHPMailer2/src/Exception.php';
require '/source/PHPMailer2/src/PHPMailer.php';
require '/source/PHPMailer2/src/SMTP.php';
PHP Mailer original source :
PHP Mailer In gitHub
// for use PHP Mailer without composer :
// ex. Create a folder in root/PHPMAILER
// Put on this folder this 3 files find in "src"
// folder of the distribution :
// PHPMailer.php , SMTP.php , Exception.php
// include PHP Mailer
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
include dirname(__DIR__) .'/PHPMAILER/PHPMailer.php';
include dirname(__DIR__) .'/PHPMAILER/SMTP.php';
include dirname(__DIR__) .'/PHPMAILER/Exception.php';
// i made a function
/*
*
* Function send_mail_by_PHPMailer($to, $from, $subject, $message);
* send a mail by PHPMailer method
* #Param $to -> mail to send
* #Param $from -> sender of mail
* #Param $subject -> suject of mail
* #Param $message -> html content with datas
* #Return true if success / Json encoded error message if error
* !! need -> classes/Exception.php - classes/PHPMailer.php - classes/SMTP.php
*
*/
function send_mail_by_PHPMailer($to, $from, $subject, $message){
// SEND MAIL by PHP MAILER
$mail = new PHPMailer();
$mail->CharSet = 'UTF-8';
$mail->isSMTP(); // Use SMTP protocol
$mail->Host = 'your_host.com'; // Specify SMTP server
$mail->SMTPAuth = true; // Auth. SMTP
$mail->Username = 'my_mail#your_host.com'; // Mail who send by PHPMailer
$mail->Password = 'your_passord_of_your_box'; // your pass mail box
$mail->SMTPSecure = 'ssl'; // Accept SSL
$mail->Port = 465; // port of your out server
$mail->setFrom($from); // Mail to send at
$mail->addAddress($to); // Add sender
$mail->addReplyTo($from); // Adress to reply
$mail->isHTML(true); // use HTML message
$mail->Subject = $subject;
$mail->Body = $message;
// SEND
if( !$mail->send() ){
// render error if it is
$tab = array('error' => 'Mailer Error: '.$mail->ErrorInfo );
echo json_encode($tab);
exit;
}
else{
// return true if message is send
return true;
}
}
/*
*
* END send_mail_by_PHPMailer($to, $from, $subject, $message)
* send a mail by PHPMailer method
*
*/
// use function :
send_mail_by_PHPMailer($to, $from, $subject, $message);

How to download file and immediately export as email attachment

I have a web app where users can click a button to download a PDF report.
My users requested that when the PDF is downloaded, it's immediately opened as an email attachment (sort of like when a mailto anchor is clicked).
Is this even possible? I was thinking maybe using js to generate an anchor tag behind-the-scenes but I read that mailto doesn't really support attachments.
If this matters, the PDF is generated server side using PHP mPDF set to download output mode.
mailto supports attachment if the file is available locally. You can use the attach parameter to specify that.
e.g. mailto:lastname.firstname#xxx.com?subject=Test&attach=C:\Documents%20and%20Settings\username\Desktop\foldername\file.extn
However, I'm unsure how you would use this in your code as users can download the file to any location on their machine. If it's of any use, the attach parameter supports shared drive locations if the user has appropriate access.
For this you have to separate process in two step.
Generate PDF on server in some directory using http://wkhtmltopdf.org/
Send generated pdf as part of email attachement using https://github.com/PHPMailer/PHPMailer
configure both the service will help you achieve your task.
Below is the sample code which will help you
//generate PDF file for bill and send it in email
public function sendInvoiceInEmail($register_no, $html_string, $guest_email_id)
{
//create mailer class
$mail = new PHPMailer;
//remove old invoice file if exist at public/doc
// here i have used my path you have to use your path
if(file_exists(__DIR__.'/../../public/docs/invoice.pdf')){
unlink(__DIR__.'/../../public/docs/invoice.pdf');
}
// You can pass a filename, a HTML string, an URL or an options array to the constructor
$pdf = new Pdf([
'commandOptions' => [
'useExec' => false,
'escapeArgs' => false,
'procOptions' => array(
// This will bypass the cmd.exe which seems to be recommended on Windows
'bypass_shell' => true,
// Also worth a try if you get unexplainable errors
'suppress_errors' => true,
),
],
]);
$globalOptions = array(
'no-outline'
);
$pdf->setOptions($globalOptions);
$pdf->addPage($html_string);
//for Windows in my system i have setup wkhtmltopdf here
$pdf->binary = '"C:/Program Files/wkhtmltopdf/bin/wkhtmltopdf.exe"';
// for linux when you will host you have to setp on linux abd comment windows path and uncomment below line
//$pdf->binary = '/home/username/wkhtmltox/bin/wkhtmltopdf';
if (!$pdf->saveAs(__DIR__.'/../../public/docs/invoice.pdf')) {
throw new Exception('Could not create PDF: '.$pdf->getError());
}
//now send email and attach invoice.pdf file from public/doc/invoice.pdf
//$mail->SMTPDebug = 3; // Enable verbose debug output
$mail->isSMTP(); // Set mailer to use SMTP
$mail->Host = 'hostname'; // Specify main and backup SMTP servers
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = 'username'; // SMTP username
$mail->Password = 'password'; // SMTP password
$mail->SMTPSecure = 'tls'; // Enable TLS encryption, `ssl` also accepted
$mail->Port = 587; // TCP port to connect to
$mail->setFrom('from_email_address', 'From Name',FALSE);
$mail->addAddress('to_email_address'); // Add a recipient
$mail->addAttachment(__DIR__.'/../../public/docs/invoice.pdf'); // Add attachments
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = 'Subject';
$mail->Body = 'email message body';
$is_email_sent = false;
if(!$mail->send()) {
// echo 'Message could not be sent.';
// echo 'Mailer Error: ' . $mail->ErrorInfo;
$is_email_sent = false;
} else {
// echo 'Message has been sent';
$is_email_sent = true;
}
return true;
}

php email, code reuse fails on second include

I posted earlier as an email and relocation issue, however after trying several things, and tracing (in production! yech!)
I have found the culprit - but have NO IDEA why or where to go from here.
you will see in the below code I include 'email.php' twice - because one receipt goes to the user, the other includes some meta data about the user and goes to support...
if i comment out the SECOND include, my redirect works, if i leave it in, it bombs...
the notify email is valid, and is the only thing that is different.
Im at a loss
PHP FORM PROCESSOR
...
// send two emails
$_emailTo = $email; // the email of the person requesting
$_emailBody = $text_body; // the stock response with things filled in
include ( 'email.php' );
$_emailTo = $notifyEmail; // the support email address
$_emailBody = $pretext.$text_body; // pretext added as meta data for support w/ same txt sent to user
//I make it this far in my trace - then nothing
include ( 'email.php' );
// relocate
echo '<META HTTP-EQUIV="Refresh" Content="0; URL=success.php" >';
exit;
PHP MAILER (email.php)
<?php
require 'phpmailer/class.phpmailer.php';
//Create a new PHPMailer instance
$mail = new PHPMailer();
//Tell PHPMailer to use SMTP
$mail->IsSMTP();
//Enable SMTP debugging
// 0 = off (for production use)
// 1 = client messages
// 2 = client and server messages
$mail->SMTPDebug = 0;
//Set the hostname of the mail server
$mail->Host = "mail.validmailserver.com";
//Set the SMTP port number - likely to be 25, 465 or 587
$mail->Port = 26;
//Whether to use SMTP authentication
$mail->SMTPAuth = true;
//Username to use for SMTP authentication
$mail->Username = "validusername";
//Password to use for SMTP authentication
$mail->Password = "pass1234";
//Set who the message is to be sent from
$mail->SetFrom('me#validmailserver.com', 'no-reply # this domain');
//Set an alternative reply-to address
//$mail->AddReplyTo('no-reply#validmailserver.com','Support');
//Set who the message is to be sent to
$mail->AddAddress( $_emailTo );
$mail->Subject = $_emailSubject;
$mail->MsgHTML( $_emailBody );
$_emailError = false;
//Send the message, check for errors
if( !$mail -> Send() ) {
$_emailError = true;
echo "Mailer Error: " . $mail->ErrorInfo;
}
?>
help - please
It's the require in email.php that is causing the problems. If you want to make the least change possible and make it work, change it to require_once. This will ensure "phpmailer/class.phpmailer.php" is only loaded once, therefore the class will only be defined once.
take the require() line from email.php and put it in the calling file

Categories