Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Emailing A Dynamically Created PDF Through PHP

I've recently created an online template for creating job postings for our website. Everything is all done, it formats correctly in a browser, automatically posts to our website, bla bla bla.

The last piece I'm creating is to give the administrator a few options for distributing the posting to various places (via email) in a consistent, convenient way. I've created a PHP page that creates a PDF doc on the fly, using the TCPDF library. When loading pdf.php?id=X, the page displays a PDF with the content of job posting X. This means I'm never saving the PDF file to the server, just creating it on the fly each time it's called.

But I want to attach this PDF to an email, and send it to various colleges, and internal mailing lists, etc. If I attach the pdf.php?id=x to the email, it doesn't attach the PDF, it attaches what appears to be a blank file, with the above name.

Is it possible to attach this to the email without saving it to the server?


Below added based on JM4's response for further trouble shooting. I have put the PDF file creation into a function, and put it into an include file, just to keep things easier to manage.

// random hash necessary to send mixed content
$separator = md5(time());

$eol = PHP_EOL;

// attachment name
$filename = "_Desiredfilename.pdf";

include_once('pdf.php');
// encode data (puts attachment in proper format)
$pdfdoc = job_posting_to_pdf($posting_id);
$attachment = chunk_split(base64_encode($pdfdoc));

///////////HEADERS INFORMATION////////////
// main header (multipart mandatory) message
$headers  = "From: Sender_Name<[email protected]>".$eol;
//$headers .= "Bcc: [email protected]".$eol;
$headers .= "MIME-Version: 1.0".$eol; 
$headers .= "Content-Type: multipart/mixed; boundary=\"".$separator."\"".$eol.$eol; 
$headers .= "Content-Transfer-Encoding: 7bit".$eol;
$headers .= "This is a MIME encoded message.".$eol.$eol;

// message
$headers .= "--".$separator.$eol;
$headers .= "Content-Type: text/html; charset=\"iso-8859-1\"".$eol;
$headers .= "Content-Transfer-Encoding: 8bit".$eol.$eol;
$headers .= $message.$eol.$eol;

// attachment
$headers .= "--".$separator.$eol;
$headers .= "Content-Type: application/octet-stream; name=\"".$filename."\"".$eol; 
$headers .= "Content-Transfer-Encoding: base64".$eol;
$headers .= "Content-Disposition: attachment".$eol.$eol;
$headers .= $attachment.$eol.$eol;
$headers .= "--".$separator."--";

//Email message
if(mail('[email protected]', 'test job posting', 'message body goes here', $headers)) {
    echo 'mail sent';
} else {
    echo 'error in email';
}

Here is a stripped down version of pdf.php:

function job_posting_to_pdf($job_id) {
    require_once(ROOT . 'assets/libs/tcpdf/config/lang/eng.php');
    require_once(ROOT . 'assets/libs/tcpdf/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('');
    $pdf->SetTitle('OPL Job Posting');
    $pdf->SetSubject('Job Posting');
    $pdf->SetKeywords('TCPDF, PDF, example, test, guide');

    // remove default header/footer
    $pdf->setPrintHeader(false);
    $pdf->setPrintFooter(false);

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

    //set margins
    $pdf->SetMargins(11, PDF_MARGIN_TOP, 11);

    //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); 

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

    $pdf->SetFont('times', 'I', 9);
    $pdf->AddPage();

    $left_cell_width = 60;
    $row_height = 6;

    $pdf->Image(ROOT . 'assets/gfx/logos/OPL-Logo.jpg', 0, 5, null, 16, null, null, 'N', false, null,'R');
    $pdf->Ln('3');

    if(!$row['internal']) {
        $pdf->Cell(0,0,'This position will be posted internally and externally, concurrently.',0,2,'C');
    } else {
        $pdf->Cell(0,0,'Internal posting only.',0,2,'C');
    }

    //Remainder of actual PDF creation removed to keep things simple


    return $pdf->Output("", "S");
}
like image 517
Cory Dee Avatar asked Aug 19 '10 19:08

Cory Dee


2 Answers

If I completely understand what you are asking this is quite simple. I am assuming you already have the PDF generated using something like fdpf or tcpdf. In that case - simply use the following code:

<?php
    // random hash necessary to send mixed content
    $separator = md5(time());

    $eol = PHP_EOL;

    // attachment name
    $filename = "_Desiredfilename.pdf";

    // encode data (puts attachment in proper format)
    $pdfdoc = $pdf->Output("", "S");
    $attachment = chunk_split(base64_encode($pdfdoc));

    ///////////HEADERS INFORMATION////////////
    // main header (multipart mandatory) message
    $headers  = "From: Sender_Name<[email protected]>".$eol;
    $headers .= "Bcc: [email protected]".$eol;
    $headers .= "MIME-Version: 1.0".$eol; 
    $headers .= "Content-Type: multipart/mixed; boundary=\"".$separator."\"".$eol.$eol; 
    $headers .= "Content-Transfer-Encoding: 7bit".$eol;
    $headers .= "This is a MIME encoded message.".$eol.$eol;

    // message
    $headers .= "--".$separator.$eol;
    $headers .= "Content-Type: text/html; charset=\"iso-8859-1\"".$eol;
    $headers .= "Content-Transfer-Encoding: 8bit".$eol.$eol;
    $headers .= $message.$eol.$eol;

    // attachment
    $headers .= "--".$separator.$eol;
    $headers .= "Content-Type: application/octet-stream; name=\"".$filename."\"".$eol; 
    $headers .= "Content-Transfer-Encoding: base64".$eol;
    $headers .= "Content-Disposition: attachment".$eol.$eol;
    $headers .= $attachment.$eol.$eol;
    $headers .= "--".$separator."--";


    //Email message
    mail($emailto, $emailsubject, $emailbody, $headers);

    ?>
like image 69
JM4 Avatar answered Oct 04 '22 21:10

JM4


I just had to figure this out and my eyeballs were definitely sore by the end...

1) You need to install PHPMailer to the php server.

2) Include the PHPmailer class in your TCPDF script, like so (your path may vary):

require_once('../PHPMailer_v5.1/class.phpmailer.php');

3) Now after your pdf code simply talk to PHPMailer like so:

$filename = "custompdf_$name_$time.pdf";

$pdf->Output($filename, 'F'); // save the pdf under filename

$mail = new PHPMailer(); $mail->IsSMTP();

$mail->Host = "mail.yourhost.com";
$mail->SMTPAuth   = true;                  // enable SMTP authentication
$mail->Port       = 26;                    // set the SMTP port for the GMAIL server
$mail->Username   = "user+yourhost.com"; // SMTP account username
$mail->Password   = "topsecret";        // SMTP account password

$mail->From = "[email protected]";
$mail->FromName = "Stack Overflower";
$mail->AddAddress( $email, $name );  //  in this case the variable has been passed
$mail->AddCC( "[email protected]", "Johnny Person"); // in this case we just hard code it
$mail->SMTPDebug = 0;  // use 2 for debugging the email send

$pdf_content = file_get_contents($filename);

$mail->WordWrap = 50;
$mail->AddStringAttachment($pdf_content, "custompdf_for_$name_$time.pdf", "base64", "application/pdf");  // note second item is name of emailed pdf
$mail->IsHTML(true);
$mail->Subject = "Your pdf is here";
$mail->Body = "Dear $name,<br>
Here is your custom generated pdf generated at $t.<br><br>
Thank you";
if(!$mail->Send()) {
     echo "Sorry ... EMAIL FAILED"; 
     } else {  echo "Done. . .  Email sent to $email at $t."; }

unlink($filename); // this will delete the file off of server

Of course you have many options for the email sent, like not using html, or sending both html and text, adding many recipients and/or cc's, etc.

EDIT: This does save the file temporarily on the server, but it cleans up after itself with the unlink command.

like image 38
Mischa Avatar answered Oct 04 '22 20:10

Mischa