Home » Php » php – sending an email attachment using TCPDF

php – sending an email attachment using TCPDF

Posted by: admin July 12, 2020 Leave a comment

Questions:

PHP
I have a simple course application form, which when filled, an email is sent to the applicant with a fees quotation for the courses he selected as a pdf attachment.

I am using TCPDF and am passing the data from the form to the library using session variables. The content is in html format.

The PDF is generated and sent as an attachment as required, Problem is that it is blank..only the header and footer is in the document. This is particularly so in linux. In windows the pdf document is generated as expected when downloaded. However, when you click on “view” before downloading the document, only the header and footer shows.

Here is my code. Please someone help. Thank you.

<?php
session_start();
require_once('../config/lang/eng.php');
require_once('../tcpdf.php');

// create new PDF document
$pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);

// set document information
$pdf->SetCreator(PDF_CREATOR);
$pdf->SetAuthor('Josiah Njuki');
$pdf->SetTitle('Quotation Request');
$pdf->SetSubject('TCPDF Tutorial');
$pdf->SetKeywords('TCPDF, PDF, example, test, guide');

// set default header data
$pdf->SetHeaderData(PDF_HEADER_LOGO, PDF_HEADER_LOGO_WIDTH, '', PDF_HEADER_STRING);

// set header and footer fonts
$pdf->setHeaderFont(Array(PDF_FONT_NAME_MAIN, '', PDF_FONT_SIZE_MAIN));
$pdf->setFooterFont(Array(PDF_FONT_NAME_DATA, '', PDF_FONT_SIZE_DATA));

// set default monospaced font
$pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);

//set margins
$pdf->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT);
$pdf->SetHeaderMargin(PDF_MARGIN_HEADER);
$pdf->SetFooterMargin(PDF_MARGIN_FOOTER);

//set auto page breaks
$pdf->SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM);

//set image scale factor
$pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);

//set some language-dependent strings
$pdf->setLanguageArray($l);

// ---------------------------------------------------------

// set default font subsetting mode
$pdf->setFontSubsetting(true);

// Set font
// dejavusans is a UTF-8 Unicode font, if you only need to
// print standard ASCII chars, you can use core fonts like
// helvetica or times to reduce file size.
$pdf->SetFont('dejavusans', '', 14, '', true);

// Add a page
// This method has several options, check the source code documentation for more information.
$pdf->AddPage();

// Set some content to print
$html = '<span style="font-size:7pt;">' . $_SESSION['content'] . '</span>';
$html .= <<<EOD
EOD;

// Print text using writeHTMLCell()
$pdf->writeHTMLCell($w=0, $h=0, $x='', $y='', $html, $border=0, $ln=1, $fill=0, $reseth=true, $align='', $autopadding=true);

// ---------------------------------------------------------

// Close and output PDF document
// This method has several options, check the source code documentation for more information.
//$pdf->Output('example_001.pdf', 'I');
$doc = $pdf->Output('quotation.pdf', 'S');

//define the receiver of the email
$name = "Name goes here";
$email = "[email protected]";

$to = "$name <{$_SESSION['email']}>";

$from = "John-Smith ";

$subject = "Here is your attachment";

$fileatt = $pdf->Output('quotation.pdf', 'S');
//$fileatt = "./test.pdf";

$fileatttype = "application/pdf";

$fileattname = "newname.pdf";

$headers = "From: $from";

$file = fopen($fileatt, 'rb');

$data = fread($file, filesize($fileatt));

fclose($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" .
    $message .= "\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";

if (mail($to, $subject, $message, $headers)) {
    echo "The email was sent.";
} else {
    echo "There was an error sending the mail.";
}
//============================================================+
// END OF FILE
//============================================================+
How to&Answers:

1.you can do that using:

$fileatt = $pdf->Output('quotation.pdf', 'E');

the option E: return the document as base64 mime multi-part email attachment (RFC 2045) , i found this info on: tcpdf documentation

after that you only need to do:

$data = chunk_split($fileatt);

and your file is ready to be attached to mail, there is no need to work with files. Just keep your headers and other settings and it will do the work.

or

2.you can use F to save it on your server, then get data like this:

$filename = location_on_server."quotation.pdf";

$fileatt = $pdf->Output($filename, 'F');

$data = chunk_split( base64_encode(file_get_contents($filename)) );

Answer:

Output($name='yourfilename.pdf', $dest='E')

E is the solution for the problem u have. Here is a lisst of the possible values of the $dest string (Destination where to send the document):

  • I: send the file inline to the browser (default).
  • D: send to the browser and force a file download with the name given by name.
  • F: save to a local server file with the name given by name.
  • S: return the document as a string (name is ignored).
  • FI: equivalent to F + I option
  • FD: equivalent to F + D option
  • E: return the document as base64 mime multi-part email attachment (RFC 2045)

Answer:

I have tried many options. The one that worked was when I used the tcpdf output setting “F” setting to save to a folder. Included the phpmailer files and used the code below.

$pdf->Output("folder/filename.pdf", "F"); //save the pdf to a folder setting `F`
require_once('phpmailer/class.phpmailer.php'); //where your phpmailer folder is
$mail = new PHPMailer();                    
$mail->From = "email.com";
$mail->FromName = "Your name";
$mail->AddAddress("[email protected]");
$mail->AddReplyTo("[email protected]", "Your name");               
$mail->AddAttachment("folder/filename.pdf");      
// attach pdf that was saved in a folder
$mail->Subject = "Email Subject";                  
$mail->Body = "Email Body";
if(!$mail->Send())
{
   echo "Message could not be sent. <p>";
   echo "Mailer Error: " . $mail->ErrorInfo;
}
else
{
   echo "Message sent";
} //`the end`

Answer:

First generate the PDF using tcpdf library.Here is the example for generate PDF:

<?php
    ini_set("display_errors", 1);

    require_once('./TCPDF/tcpdf.php');

    class MYPDF extends TCPDF {
        public function Footer() {
            $this->SetY(-15);
            $this->SetFont('helvetica', 'I', 8);
            $this->Cell(0, 0, 'Product Company - Spider india, Phone : +91 9940179997, TIC : New No.7, Old No.147,Mount Road, Little Mount,Saidapet, Chennai, Tamilnadu,Pin - 600015, India.', 0, 0, 'C');
            $this->Ln();
            $this->Cell(0,0,'www.spiderindia.com - TEL : +91-44-42305023, 42305337  - E : [email protected]', 0, false, 'C', 0, '', 0, false, 'T', 'M');
            $this->Cell(0, 10, 'Page '.$this->getAliasNumPage().'/'.$this->getAliasNbPages(), 0, false, 'C', 0, '', 0, false, 'T', 'M');
        }    
    }

    $pdf = new MYPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
    $pdf->SetCreator(PDF_CREATOR);
    $pdf->SetAuthor('Manikandan');
    $pdf->SetTitle('Quote');
    $pdf->SetSubject('Quote');
    $pdf->SetKeywords('PDF, Quote');

    $pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);
    $pdf->SetFooterMargin(PDF_MARGIN_FOOTER);
    $pdf->SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM);
    $pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);

    $pdf->SetFont('times', '', 15); 

    $pdf->AddPage();

    // create some HTML content
    $now = date("j F, Y");
    $company_name = 'ABC test company';

    $user_name = 'Mr. Manikandan';
    $invoice_ref_id = '2013/12/03';


    $html = '';
    $html .= '<table style="padding-top:25px;">
                <tr>
                    <td colspan="2" align="left"><h4>Kannama & CO</h4></td>
                    <td colspan="2" align="right"><h1 style="color:#6C8BB5;">Quote</h1></td>
                </tr>

                <tr>
                    <td colspan="2" align="left"><table><tr><td>'.$user_name.'</td></tr><tr><td>Mob NO : 9791564278</td></tr></table></td>
                    <td colspan="2" align="right"><table border="1" align="center"><tr><td>Date</td><td>'.$now.'</td></tr><tr><td>Quote</td><td>#0041</td></tr></table></td>
                </tr>

                <tr>
                    <td colspan="2" align="left"><table><tr><td style="background-color: #2B7DB9;color:white;width:75%;">Customer</td></tr><tr><td>Dear senthil kumar,</td></tr><tr><td>39,Jawahar sangam street,Chockalingapuram,Aruppukottai.</td></tr><tr><td><b>Mob no : </b> 9791564821</td></tr></table></td>
                </tr>


             </table>';

    $html .= '<br><br>
              <table border="1" cellpadding="5">
                <tr style="background-color: #2B7DB9;color:white;">
                    <td colspan="4">Quote # Quote 001</td>            
                </tr>
                <tr>
                    <td><b>Product</b></td>
                    <td><b>Quantity</b></td>
                    <td><b>Subtotal</b></td>
                    <td align="right"><b>Amount (Rs.)</b></td>
                </tr>
                <tr style="background-color: #C1E1F8;">
                    <td>Product 1</td>
                    <td>30</td>
                    <td>10</td>
                    <td align="right">300</td>
                </tr>
                <tr>
                    <td>Product 3</td>
                    <td>15</td>
                    <td>3</td>
                    <td align="right">75</td>
                </tr>
                <tr style="background-color: #C0E1F8;">
                    <td>Product 2</td>
                    <td>15</td>
                    <td>3</td>
                    <td align="right">75</td>
                </tr>
                <tr>
                    <td colspan="3" align="right"><b>Sub Total:</b></td>
                    <td align="right"><b> 375</b></td>
                </tr>
                <tr>
                    <td colspan="3" align="right"><b>GST:</b></td>
                    <td align="right"><b> 5</b></td>
                </tr>
                <tr>
                    <td colspan="3" align="right"><b>CGST:</b></td>
                    <td align="right"><b> 10</b></td>
                </tr>
                <tr>
                    <td colspan="3" align="right"><b>Delivery:</b></td>
                    <td align="right"><b> 100</b></td>
                </tr>
                <tr>
                    <td colspan="3" align="right"><b>Total:</b></td>
                    <td align="right"><b> 1000</b></td>
                </tr>
             </table>';

    $html = str_replace('{now}',$now, $html);
    $html = str_replace('{company_name}',$company_name, $html);
    $html = str_replace('{user_name}',$user_name, $html);
    $html = str_replace('{invoice_ref_id}',$invoice_ref_id, $html);

    $pdf->writeHTML($html, true, false, true, false, '');

    $pdf->lastPage();

    $fileName = time() . '.pdf';
    ob_clean();
    $pdf->Output(FCPATH . 'files/' . $fileName, 'F');

    if (file_exists(FCPATH . 'files/' . $fileName)) {
        if (!empty($data->email)) {
            $status = $this->sendReceiptEmail($fileName, $data->email);
            return $status;   
        } else {
            return false;
        }
    } else {
        return false;
    }

    Use PHP Mailer library to send email. Here is the example to send mail with attachment.

    function sendReceiptEmail($fileName, $mailto)
    {
        $file = FCPATH . 'files/' . $fileName;
        date_default_timezone_set('Asia/Kolkata');

        require __DIR__.'/../libraries/phpmailer/PHPMailerAutoload.php';

        $mail = new PHPMailer;

        $mail->SMTPDebug = 0;
        $mail->Debugoutput = 'html';
        $mail->IsSMTP();
        $mail->Host = "xxx.xxx.com";
        $mail->Port = 587;
        $mail->SMTPAuth = true;
        $mail->Username = "[email protected]";
        $mail->Password = "xxxxx";
        $mail->setFrom('[email protected]', 'Company Quote');
        $mail->addReplyTo('[email protected]');
        $mail->addAddress($mailto);
        $mail->Subject = 'Quote';
        $mail->Body = 'Here we attached quote detail.Please find the attachment.';

        $mail->addAttachment($file);

        //send the message, check for errors
        if (!$mail->send()) {
            return false;
        } else {
            $file = FCPATH . 'files/' . $fileName;
            if (file_exists($file)) {
                unlink($file);
            }
            return true;
        }
    }

Answer:

I know this is kind of old question (put old on it!). But I manage to do it like this.

function createPDF($html){
    $pdf = new TCPDF();
    $pdf->AddPage();
    $pdf->writeHTML($html, true, false, true, false, '');

    return $pdf->Output('filename.pdf', 'S'); //S: return the document as a string (name is ignored).
}


function sendEmail() {

    $pdf = createPDF('<a>Hello</a>');
    $filename = 'hello.pdf';
    $encoding = 'base64';
    $type = 'application/pdf';

    //using PHPMailer
    $mail->AddStringAttachment($pdf,$filename,$encoding,$type);
}

Answer:

Since the officially documented method using 'S' or 'E' returned null for me I went ahead and used the tried and tested output buffer trick, e.g.:

protected function PDF_string($pdf, $base64 = false) {
    ob_start();
    $pdf->Output('file.pdf', 'I');
    $pdf_data = ob_get_contents();
    ob_end_clean();

    return ($base64) ? base64_encode($pdf_data) : $pdf_data;
}

Answer:

Its a lot more work to do it my way but I wanted to give the user the Output option D: send to the browser and force a file download with the name given by name or save it immediately as a PDF File ready for editing.

Example_054.php.

Then I created a identical form from TCPDF with DOMPDF.

Once the form is submitted the form will call my submit script and the submit script will access the populated values and in turn populate my identical DOMPDF doc. I then save my DOMPDF doc with its new polulated values. The saved DOMPDF file can Now be emailed via PHPMailer as a fully populated PDF file email attachment.

There was probably an easier way to do this via TCPDF itself but this satisfied my requirements perfectly. And I got to learn DOMPDF along with TCPDF at the same time.

Answer:

As an ammendment to my last post this ONLY applies if the user elects to access the PDF file from the browser, Output Option D: Example_054.php. I did NOT see any other way of emailing as a PDF created on the browser and send that as the actual PDF file email attachment without re-creating the PDF with DOMPDF and saving the populated PDF so it could be sent then as the email attachment. If the user elects to save the PDF before populating then this is a non-issue as the populated file will then exist for the attachment. If there is a easier way to handle this scenario please let me know!!

Answer:

There is code from tcpdf.php. we can see that what does E option do in Output function. it uses base64_encode & chunk_split and also add headers with it so there is no need to add headers again.

case 'E': {
            // return PDF as base64 mime multi-part email attachment (RFC 2045)
            $retval = 'Content-Type: application/pdf;'."\r\n";
            $retval .= ' name="'.$name.'"'."\r\n";
            $retval .= 'Content-Transfer-Encoding: base64'."\r\n";
            $retval .= 'Content-Disposition: attachment;'."\r\n";
            $retval .= ' filename="'.$name.'"'."\r\n\r\n";
            $retval .= chunk_split(base64_encode($this->getBuffer()), 76, "\r\n");
            return $retval;
        }

So in above question

$attachFile = $pdf->Output('quotation.pdf', 'E');
$html_message = '<p> Your HTML/ Plain message Here </p>' ;
$uid = md5() ;

$header = "From: <[email protected]>\r\n";
$header .= "Reply-to: <[email protected]>\r\n";
$header .= "MIME-Version: 1.0\r\n";
$header .= "Content-type: multipart/mixed; boundary=\"".$uid."\"\r\n\r\n";

// message & attachment
$nmessage = "--".$uid."\r\n";
$nmessage .= "Content-type:text/html ;charset=UTF-8\r\n";
$nmessage .= $html_message."\r\n\r\n"; //Your message

$nmessage .= "--".$uid."\r\n";
$nmessage .= $attachFile."\r\n\r\n"; //adding Your PDF file
$nmessage .= "--".$uid."--" ;

Answer:

Using CodeIgniter and TCPDF, this is what worked for me.

  1. Step 1: Save the document in the server.
  2. Step 2: Get the file path and send the file path to the function for sending the email.

    <?php
    
    function GenerateQuotation(){
        session_start();
    
        require_once('../config/lang/eng.php');
    
        require_once('../tcpdf.php');
    
        // create new PDF document
    
        $pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
    
        // set document information
    
        $pdf->SetCreator(PDF_CREATOR);
    
        $pdf->SetAuthor('Name of Author');
    
        $pdf->SetTitle('Quotation Request');
    
        $pdf->SetSubject('TCPDF Tutorial');
    
        $pdf->SetKeywords('TCPDF, PDF, example, test, guide');
    
        $pdf->SetHeaderData(PDF_HEADER_LOGO, PDF_HEADER_LOGO_WIDTH, '', PDF_HEADER_STRING);
    
        $pdf->setHeaderFont(Array(PDF_FONT_NAME_MAIN, '', PDF_FONT_SIZE_MAIN));
        $pdf->setFooterFont(Array(PDF_FONT_NAME_DATA, '', PDF_FONT_SIZE_DATA));
    
        $pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);
    
        $pdf->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT);
        $pdf->SetHeaderMargin(PDF_MARGIN_HEADER);
        $pdf->SetFooterMargin(PDF_MARGIN_FOOTER);
    
        $pdf->SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM);
    
        $pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);
    
        $pdf->setLanguageArray($l);
    
        $pdf->setFontSubsetting(true);
    
        $pdf->SetFont('dejavusans', '', 14, '', true);
    
        $pdf->AddPage();
    
        $html = '<span style="font-size:7pt;">' . $_SESSION['content'] . '</span>';
        $html .= <<<EOD
        EOD;
    
        $pdf->writeHTMLCell($w=0, $h=0, $x='', $y='', $html, $border=0, $ln=1, $fill=0, $reseth=true, $align='', $autopadding=true);       
    
        //Change this according to where you want your document to be uploaded to
        $LocationOnServer = 'C:\wamp64\www\projectname\uploads\invoices/\/'; 
    
        $FileNamePath = $LocationOnServer.'quotation.pdf';
    
        //Save the document to the server
        $QuotationAttachment = $pdf->Output($FileNamePath, 'F');
    
        $EmailAddress = $_SESSION['email'];       
    
        if(!empty($FileNamePath)){
            $this->SendQuotation($EmailAddress,$FileNamePath);
        }
        else{
            print_r('Could not trace file path');
        }             
    
    }
    
    function SendQuotation($EmailAddress,$FileNamePath){
        $Subject = 'My subject here';
        $Message = 'My Email body message here';
    
        $this->email
            ->from('[email protected]', 'From Who')    
            ->to($EmailAddress) 
            ->subject($Subject)
            ->message($Message);
    
        $this->email->attach($FileNamePath);
        if($this->email->send()){
            print_r('Email Sent');
    
        }else{
            print_r($this->email->print_debugger());
        }
    
    }
    
    
    }
    ?>
    

Invoke GenerateQuotation() function to generate the quotation and email it.