18

I want to email a PDF as an attachment that was created using FPDF. My code looks like this, but the attachment never comes through.

<?php
require('lib/fpdf/fpdf.php');

$pdf = new FPDF('P', 'pt', array(500,233));
$pdf->AddFont('Georgiai','','georgiai.php');
$pdf->AddPage();
$pdf->Image('lib/fpdf/giftcertificate.jpg',0,0,500);
$pdf->SetFont('georgiai','',16);
$pdf->Cell(40,10,'Hello World!');
$doc = $pdf->Output('test.pdf', 'S');

//define the receiver of the email
$to = 'myemail@example.com';
//define the subject of the email
$subject = 'Test email with attachment';
//create a boundary string. It must be unique
//so we use the MD5 algorithm to generate a random hash
$random_hash = md5(date('r', time()));
//define the headers we want passed. Note that they are separated with \r\n
$headers = "From: reply@test.com\r\nReply-To: reply@test.com";
//add boundary string and mime type specification
$headers .= "\r\nContent-Type: multipart/mixed; boundary=\"PHP-mixed-".$random_hash."\"";
//read the atachment file contents into a string,
//encode it with MIME base64,
//and split it into smaller chunks
$attachment = chunk_split(base64_encode(file_get_contents($doc)));
//define the body of the message.
ob_start(); //Turn on output buffering
?>
--PHP-mixed-<?php echo $random_hash; ?> 
Content-Type: multipart/alternative; boundary="PHP-alt-<?php echo $random_hash; ?>"

--PHP-alt-<?php echo $random_hash; ?> 
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

Hello World!!!
This is simple text email message.

--PHP-alt-<?php echo $random_hash; ?> 
Content-Type: text/html; charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

<h2>Hello World!</h2>
<p>This is something with <b>HTML</b> formatting.</p>

--PHP-alt-<?php echo $random_hash; ?>--

--PHP-mixed-<?php echo $random_hash; ?> 
Content-Type: application/zip; name="attachment.zip" 
Content-Transfer-Encoding: base64 
Content-Disposition: attachment 

<?php echo $attachment; ?>
--PHP-mixed-<?php echo $random_hash; ?>--

<?php
//copy current buffer contents into $message variable and delete current output buffer
$message = ob_get_clean();
//send the email
$mail_sent = @mail( $to, $subject, $message, $headers );
//if the message is sent successfully print "Mail sent". Otherwise print "Mail failed"
echo $mail_sent ? "Mail sent" : "Mail failed"; 

?>

Anyone familiar with doing this? I'm hoping to use the PHP mail() function.

HWD
  • 1,547
  • 7
  • 36
  • 72
  • 2
    If it's not for learning purposes, use a PHP mailer library like Swiftmailer. http://swiftmailer.org/ – Pekka Dec 04 '10 at 11:42
  • As Pekka says, Swift Mailer is a much better idea than doing mail with attachments by hand. – Orbling Dec 04 '10 at 15:11

5 Answers5

30

This ended up working for me:

<?php
require('lib/fpdf/fpdf.php');

$pdf = new FPDF('P', 'pt', array(500,233));
$pdf->AddFont('Georgiai','','georgiai.php');
$pdf->AddPage();
$pdf->Image('lib/fpdf/image.jpg',0,0,500);
$pdf->SetFont('georgiai','',16);
$pdf->Cell(40,10,'Hello World!');

// email stuff (change data below)
$to = "myemail@example.com"; 
$from = "me@example.com"; 
$subject = "send email with pdf attachment"; 
$message = "<p>Please see the attachment.</p>";

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

// carriage return type (we use a PHP end of line constant)
$eol = PHP_EOL;

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

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

// main header
$headers  = "From: ".$from.$eol;
$headers .= "MIME-Version: 1.0".$eol; 
$headers .= "Content-Type: multipart/mixed; boundary=\"".$separator."\"";

// no more headers after this, we start the body! //

$body = "--".$separator.$eol;
$body .= "Content-Transfer-Encoding: 7bit".$eol.$eol;
$body .= "This is a MIME encoded message.".$eol;

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

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

// send message
mail($to, $subject, $body, $headers);

?>
HWD
  • 1,547
  • 7
  • 36
  • 72
  • thanks, works perfectly in Gmail, but in Outlook the email is a blank page and the message is a 2nd attachment... You know what's causing this? – Frederik Voordeckers Mar 21 '13 at 07:56
  • I am using this code and occasionally some emails are not received by all recipients. But the Bcc I have set up seems to always come through. I have the code running on Go Daddy shared hosting (Deluxe)... Anybody know why? – Bigfootbud Aug 14 '18 at 00:28
25

if you use PHPMailer

$attachment= $pdf->Output('attachment.pdf', 'S');

$mailer->AddStringAttachment($attachment, 'attachment.pdf');

Enjoy

xavip
  • 545
  • 5
  • 14
3

I think you have a superfluous command there. You are using the string variant of the Output() command:

$doc = $pdf->Output('test.pdf', 'S');

Then you are performing a file_get_contents() on it:

$attachment = chunk_split(base64_encode(file_get_contents($doc)));

It is not a file, it is a file in a string, as file_get_contents() would return if $doc was a filename.

Just reduce that down to:

$attachment = chunk_split(base64_encode($doc));

Then see if any more errors occur.

Orbling
  • 20,413
  • 3
  • 53
  • 64
  • I don't get any more errors, but the file is never attached. The email I'm sent has an attachment "noname" at 0kb. Any thoughts on why this might be? Thanks for your help. – HWD Dec 04 '10 at 20:32
  • Getting MIME encoding to work by hand is very difficult, especially when you are adding complicated attachments, I would definitely recommend using a mailing library as mention on your question. Incidentally, you seem to be telling it the filename is attachment.zip and it is a zip file, at no point have you zipped the PDF. – Orbling Dec 04 '10 at 23:51
1
Create one pdf file name as testing.pdf  
 <?php 
    //define the receiver of the email 
    $to = 'elangovan2me@gmail.com'; 

    //define the subject of the email 
    $subject = 'Test email with attachment'; 

    //create a boundary string. It must be unique 
    //so we use the MD5 algorithm to generate a random hash 
    $random_hash = md5(date('r', time())); 

    //define the headers we want passed. Note that they are separated with \r\n 
    $headers = "From: elangovan2me@gmail.com\r\nReply-To: meeetcity@gmail.com";

    //add boundary string and mime type specification 
    $headers .= "\r\nContent-Type: multipart/mixed; boundary=\"PHP-mixed-".$random_hash."\""; 

    //read the atachment file contents into a string,
    //encode it with MIME base64,
    //and split it into smaller chunks
    $attachment = chunk_split(base64_encode(file_get_contents('testing.pdf'))); 

    //define the body of the message. 
    ob_start(); //Turn on output buffering 
    ?> 
    --PHP-mixed-<?php echo $random_hash; ?>  
    Content-Type: multipart/alternative; boundary="PHP-alt-<?php echo $random_hash; ?>" 

    --PHP-alt-<?php echo $random_hash; ?>  
    Content-Type: text/plain; charset="iso-8859-1" 
    Content-Transfer-Encoding: 7bit

    Hello World!!! 
    This is simple text email message. 

    --PHP-alt-<?php echo $random_hash; ?>  
    Content-Type: text/html; charset="iso-8859-1" 
    Content-Transfer-Encoding: 7bit

    <h2>Email Pdf File Attachements</h2> 
    <p>This is something with <b>HTML</b> formatting.</p> 

    --PHP-alt-<?php echo $random_hash; ?>-- 

    --PHP-mixed-<?php echo $random_hash; ?>  
    Content-Type: application/pdf; name="attachment.pdf"  
    Content-Transfer-Encoding: base64  
    Content-Disposition: attachment  

    <?php echo $attachment; ?> 
    --PHP-mixed-<?php echo $random_hash; ?>-- 

    <?php 
    //copy current buffer contents into $message variable and delete current output buffer 
    $message = ob_get_clean(); 
    //send the email 
    $mail_sent = @mail( $to, $subject, $message, $headers ); 
    //if the message is sent successfully print "Mail sent". Otherwise print "Mail failed" 
    echo $mail_sent ? "Mail sent" : "Mail failed"; 
?>
Elangovan
  • 3,469
  • 4
  • 31
  • 38
0

None of these worked for me...but were close. This is what worked for me and within a WordPress Plugin

function mmd_CreatePDFTest()
{
require(plugin_dir_path( __FILE__ ).'pdf/fpdf.php');    
$pdf = new FPDF();
$pdf->AddPage();
$pdf->SetFont("Arial","B",14);
$pdf->Cell(40,10, "this is a pdf example");
$pdfdoc  = $pdf->Output("", "S");
$content = chunk_split(base64_encode($pdfdoc));

$filename  = "test.pdf";
$file_name = "test.pdf";


$uid       = md5(uniqid(time()));

$mailto = "recipient@gmail.com";
$from_mail = "office@yourdomain.com";
$replyto = $from_mail = "office@yourdomain.com";
$from_name = "YOUR COMPANY NAME | PDF Test";
$subject = "send email with pdf attachment"; 
$message = "<Please see the attachment.";


// header
$header = "From: ".$from_name." <".$from_mail.">\r\n";
$header .= "Reply-To: ".$replyto."\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/plain; charset=iso-8859-1\r\n";
$nmessage .= "Content-Transfer-Encoding: 7bit\r\n\r\n";
$nmessage .= $message."\r\n\r\n";
$nmessage .= "--".$uid."\r\n";
$nmessage .= "Content-Type: application/octet-stream; name=\"".$filename."\"\r\n";
$nmessage .= "Content-Transfer-Encoding: base64\r\n";
$nmessage .= "Content-Disposition: attachment; filename=\"".$file_name."\"\r\n\r\n";
$nmessage .= $content."\r\n\r\n";
$nmessage .= "--".$uid."--";


$returnpath = "-f" . $from_mail; 
if (mail($mailto, $subject, $nmessage, $header, $returnpath)) 
  return true; 
 else 
  return false;

}  // function mmd_CreatePDFTest()
Debbie Kurth
  • 403
  • 3
  • 16