How to send pdf generated by TCPDF as Swiftmailer attachment - php

I already tried several solutions, the closest (for me) should look like this:
$file = $pdf->Output('', 'E');
$message->attach(Swift_Attachment::newInstance($file, 'name.pdf', 'application/pdf'));
$pdf is an instance of TCPDF and $message is an instance of Swift_Message.
Using above the email is being sent ok, file is attached but when I try to open it I get the error message that file is corrupted or badly encoded.
My question is: how to send pdf generated by TCPDF as Swiftmailer attachment without saving the file to server and deleting it after sending the email. Here is the link to the TCPDF output method documentation, maybe somebody can see something I have missed.

I am using something like this and it is working. For the PDF content I am using one of the simplest examples on the PDF library.
[...]
$pdf_as_string = $pdf->Output('', 'S'); // $pdf is a TCPDF instance
[...]
$transport = Swift_MailTransport::newInstance(); // using php mail function
$message->setTo(array(
"client#customdomain.com" => "Main Email",
"client#publicdomain.com" => "Secondary Email"
));
$message->setSubject("This email is sent using Swift Mailer");
$message->setBody("You're our best client ever.");
$message->setFrom("developers#mydomain.com", "Developers United");
$attachment = Swift_Attachment::newInstance($pdf_as_string, 'my-file.pdf', 'application/pdf');
$message->attach($attachment);
[...]
Maybe this answer comes a little late since I am using swiftmailer v4_3_0 and TCPDF v6_0_002. But just in case is worth to someone.

I have had no problems attaching TCPDFs on the fly.
I call a function which eventually returns the PDF using the Output type 'S':
return $pdf->Output('TE_Invoice.pdf', 'S');
I attach the file using:
$message->attach(Swift_Attachment::newInstance()
->setFilename('TE_Invoice.pdf')
->setContentType('application/pdf')
->setBody($val['file']));
Where $val['file'] is the returned value from above.
I am using TCPDF Version: 5.9.134 and Swift Mailer Version: 4.1.3

You can use outputmode 'E' to get base64String.
$base64PdfString = $pdf->Output('', 'E');
Beware: Maybe you have to cut the first 5-6 lines, because of
Content-Type: application/pdf; name=""
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename=""
Base64StringStartsHere....
cut
$base64PdfArray = explode("\r\n", $base64PdfString);
$base64 = '';
for($i = 5; $i < count($base64PdfArray); $i++) {
$base64 .= $base64PdfArray[$i];
}
Now you have the Email as base64String.
Before sending you have to decode it.
$mail->attach(new \Swift_Attachment(base64_decode($base64), 'Pdf.pdf', 'application/pdf'));

Did you try this?
$file = $pdf->Output('', 'S');
I'm doing this with another mail backend in PHP, and this does work. I guess the mail backend takes care of encoding the attachment, so there is no need to encode it as base64 manually.

Related

Send pdf output as stringAttachment using PHPMailer

I am trying to attach a file using the PHPMailer's addStringAttachment method.
I generated the pdf from TCPDF using:
$b64_enc_doc = $pdf->Output($file_name, 'E');
Then inside of the script to send the email, I have
...
$mail->addStringAttachment($b64_enc_doc, $file_name)
However, the PDF attachment is corrupted when I try opening it.
I tried debugging the output of the PDF generated from TCPDF and it looks something similar to this:
Content-Type: application/pdf;
name="file.pdf"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="file.pdf"
JVBERi0xLjcKJeLjz9MKMjEgMCBvYmoKPDwgL1R5cGUgL1BhZ2UgL1BhcmVudCAxIDAgUiAvTGFz
dE1vZGlmaWVkIChEOjIwMjIwMTA0MTMwODQ2KzAwJzAwJykgL1Jlc291cmNlcyAyIDAgUiAvTWVk
aWFCb3ggWzAuMDAwMDAwIDAuMDAwMDAwIDU5NS4yNzYwMDAgODQxLjg5MDAwMF0gL0Nyb3BCb3gg
WzAuMDAwMDAwIDAuMDAwMDAwIDU5NS4yNzYwMDAgODQxLjg5MDAwMF0gL0JsZWVkQm94IFswLjAw
MDAwMCAwLjAwMDAwMCA1OTUuMjc2MDAwIDg0MS44OTAwMDBdIC9UcmltQm94IFswLjAwMDAwMCAw
LjAwMDAwMCA1OTUuMjc2MDAwIDg0MS44OTAwMDBdIC9BcnRCb3ggWzAuMDAwMDAwIDAuMDAwMDAw
IDU5NS4yNzYwMDAgODQxL...
Please I do not want to save the file to the server but send the file straight to the user's email. Please help.
Thanks!
You don't show the code you're using, but that string is a fragment of an email message, not a PDF binary PDF string as it should be.
Your code should be along the lines of (I don't remember tcpdf's syntax offhand):
//Render the PDF to a string in memory
$pdf = $tcpdf->output('S');
$mail->addStringAttachment($pdf, 'file.pdf');
PHPMailer will take care of the rest.

phpmailer and fpdf output file

i am using phpmailer and fpdf, to create pdf and send it by email.
I am using this lines for output and attach the file.
$pdfdoc = $pdf->Output('', 'S');
...
$mail->addStringAttachment($pdfdoc, 'my-doc.pdf');
I would like to ask if it is possible to attach file without saving it first to disk?

TCPDF Laravel Email Attachments

TCPDF doesn't seem to be working well with either $dest option ("E" or "S") for sending PDF attachments in Laravel 5.1. Files are always corrupt with an error upon launching Acrobat Reader (error message: ... for example, it was sent as an email attachment and wasn't correctly decoded). Decoding seems ok when I try another PDF generator like DOMPDF.
$pdf = new \TCPDF('P', 'in', 'LETTER', true, 'UTF-8', false);
$pdf->WriteHTML(view('emails.receipt_pdf', $receipt_data));
$attachment = $pdf->Output('Receipt - '.date("M-d-Y").'.pdf','E');
Mail::queue('emails.receipt_email', $receipt_data, function($message) use ($email, $attachment)
{
$message->from('no-reply#website.com')
->to($email)
->subject('Receipt')
->attachData($attachment, 'Receipt.pdf');
});
Just use "S" option while generating pdf. Email-related things will be done by Laravel.
Update
$attachment = $pdf->Output('Receipt - '.date("M-d-Y").'.pdf','E');
to
$attachment = $pdf->Output('Receipt - '.date("M-d-Y").'.pdf','S');
Additionally, if you are using queue() instead of send(), it will fail because of the attachment. To queue, write a job and send with the job queue.

Apple Mail does not display PDF sent using Zend_Mail

My web application creates PDF documents using Zend_Pdf and sends them using Zend_Mail. It also attaches some user uploaded documents (also PDF). The attachments show up in all general used mail programs, except in Apple Mail. The created PDF is about 30 KB and the message is sent using an external mail server.
In Apple Mail the message list shows the message with a paper clip (indicating that it has attachments), but when the message is opened no attachments are visible. When I click 'Details' in the message head, it shows the attachments and the option to save them.
This is the (stripped down) code that sends the e-mail:
<?php
$mail = new Zend_Mail('utf-8');
$mail->setFrom('niels#example.com', 'Niels')
->setSubject('Subject')
->addTo('niels#example.com', 'Niels')
->setBodyHtml('Hi there', 'utf-8', Zend_Mime::ENCODING_8BIT);
$a = new Zend_Mime_Part($pdfContent);
$a->type = 'application/pdf';
$a->filename = 'my_pdf.pdf';
$a->disposition = Zend_Mime::DISPOSITION_ATTACHMENT;
$a->encoding = Zend_Mime::ENCODING_BASE64;
$mail->addAttachment($a);
$mail->setHeaderEncoding(Zend_Mime::ENCODING_BASE64);
$mail->send();
The mail I receive has the following header for the message
Content-Type: multipart/mixed; boundary="=_f6a669390c6713f60a851af814fe897f"
Content-Disposition: inline
Content-Transfer-Encoding: 7bit
MIME-Version: 1.0
The HTML mail content:
--=_f6a669390c6713f60a851af814fe897f
Content-Type: text/html; charset="utf-8"
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable
The attachment content:
--=_f6a669390c6713f60a851af814fe897f
Content-Type: application/pdf
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="my_pdf.pdf"
Is there a way that the attachments show up in the message in Apple Mail? Now some people respond with 'there are no attachments'. Does Apple do some 'smart' things to hide/show the attachments? Or should I use another Content-Disposition etc? I've searched quite some time to find a solution, but am running out of clues.
This is not Zend issue but Apple Mail issue. Install Thunderbird ;-)
Here are few tips:
problem like this can occur if you are sending inline files and attachments at the same time
mail app settings are defaulted to inline attachments
Close Mail
Open Terminal
enter command defaults write com.apple.mail DisableInlineAttachmentViewing -bool yes,
Open Mail and try again
you should not be explicitly specifying encoding in setting body, your mail is initialized with default 'UTF-8' encoding by the way you
you should not be encoding header unless you are sending emails in languages that use not Roman letters-based character set
Try attaching the file inline and
$mail = new Zend_Mail('utf-8');
$mail->setFrom('niels#example.com', 'Niels')
->setSubject('Subject')
->addTo('niels#example.com', 'Niels')
->setBodyHtml('Hi there');
// add attachment
$mail->createAttachment(file_get_contents('my_pdf.pdf'), 'application/pdf', Zend_Mime::DISPOSITION_ATTACHMENT , Zend_Mime::ENCODING_BASE64);
// try sending attachment inline... maybe this will work (not sure if supported by all mail clients)
// $mail->createAttachment(file_get_contents('my_pdf.pdf'), 'application/pdf', Zend_Mime::DISPOSITION_INLINE , Zend_Mime::ENCODING_BASE64);
$mail->send();
The answer that Alex provided was indeed the solution: it is an Apple Mail issue. When the attachment size increases, it shows up in the e-mail. For example: I just sent a PDF document that is bigger (79KB, shows up as 112KB in the message list) and that is visible. If I send the same kind of PDF (but smaller) it is hidden.

DOMPDF - attach created PDF to email

What is the easiest way to attach a PDF to an email via DOMPDF?
The end of my script I am using (part of it) is below:
$dompdf = new DOMPDF();
$dompdf->load_html($html);
$dompdf->render();
//below to save the pdf file - not needed if emailing pdf
file_put_contents('/home/ststrave/public_html/pdf/STS_Brochure.pdf', $dompdf->output());
//below to open pdf in browser - required
$dompdf->stream("STS_Brochure_".rand(10,1000).".pdf", array("Attachment" => false));
jexit();
Just for clarification - this is being used in Joomla.
Appreciate the simplest/quickest way using standard PHP mail function.
Cheers ;-)
Ok. You already accepted an answer, but for anyone else coming here, I think there is an easier way, but it's also not PHP's standard mail function, which really isn't going to work. If you can get the pear packages Mail and Mail_mime, it's really easy to send emails with attachments. You can also directly attach the DomPDF output without creating a file, like so:
$dompdf = new DOMPDF();
$dompdf->load_html($html);
$dompdf->set_paper("letter", "portrait" );
$dompdf->render();
$output = $dompdf->output();
$mm = new Mail_mime("\n");
$mm->setTxtBody($body);
$mm->addAttachment($output,'application/pdf','output.pdf', false);
$body = $mm->get();
$headers = $mm->headers(array('From'=>$from,'Subject'=>$subject));
$mail =& Mail::factory('mail');
if($mail->send($to,$headers,$body)){
echo "Your message has been sent.";
}
Here is the solution I was looking for when I came here:
Instead of:
$dompdf->stream();
do this:
$fileatt = $dompdf->output();
And than send mail using PHPMailer and attach the pdf to mail like so:
$filename = 'MyDocument.pdf';
$encoding = 'base64';
$type = 'application/pdf';
$mail->AddStringAttachment($fileatt,$filename,$encoding,$type);
In this way you don't have to deal with saving the file on the server.
PHP's mail function has no "standard" file attachment method. It's an extremely barebones interface to the SMTP system that forces you to do ALL the work of attaching a file yourself.
I strongly suggest using PHPMailer or Swiftmailer to do the email for you - it reduces the heavy grunt work of generating your own MIME email and inserting the attachment (many many lines of code) does to maybe 5 lines total.
Note that neither of them will handle a streamed PDF from DOMPDF. You'll have to save the PDF to a temporary file and attach that,
Raw Data Attachments
The attachData method may be used to attach a raw string of bytes as an attachment. For example, you might use this method if you have generated a PDF in memory and want to attach it to the email without writing it to disk. The attachData method accepts the raw data bytes as its first argument, the name of the file as its second argument, and an array of options as its third argument:
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->view('emails.orders.shipped')
->attachData($this->pdf, 'name.pdf', [
'mime' => 'application/pdf',
]);
}

Categories