Отправка по электронной почте динамически созданного PDF через PHP - PullRequest
7 голосов
/ 19 августа 2010

Я недавно создал онлайн-шаблон для создания вакансий для нашего сайта. Все сделано, форматируется правильно в браузере, автоматически публикуется на нашем сайте, бла бла бла.

Последняя часть, которую я создаю, - это дать администратору несколько вариантов последовательного и удобного распределения сообщений в различных местах (по электронной почте). Я создал страницу PHP, которая создает документ PDF на лету, используя библиотеку TCPDF. При загрузке pdf.php? Id = X на странице отображается PDF-файл с содержимым публикации вакансии X. Это означает, что я никогда не сохраняю PDF-файл на сервер, а просто создаю его на лету при каждом вызове.

Но я хочу прикрепить этот PDF-файл к электронному письму и отправить его в различные колледжи, во внутренние списки рассылки и т. Д. Если я прикреплю pdf.php? Id = x к электронному письму, он не прикрепит PDF-файл. , он прикрепляет то, что кажется пустым файлом, с указанным выше именем.

Можно ли прикрепить это к письму, не сохраняя его на сервере?


Ниже добавлено на основе ответа JM4 для дальнейшего устранения неполадок. Я поместил создание PDF-файла в функцию и поместил его во включаемый файл, чтобы упростить управление.

// 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<valid_email@mydomain.com>".$eol;
//$headers .= "Bcc: email@domain.com".$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('valid_email@mydomain.com', 'test job posting', 'message body goes here', $headers)) {
    echo 'mail sent';
} else {
    echo 'error in email';
}

Вот урезанная версия 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");
}

Ответы [ 6 ]

5 голосов
/ 02 сентября 2010

Если я полностью понимаю, что вы спрашиваете, это довольно просто. Я предполагаю, что у вас уже есть PDF, созданный с использованием чего-то вроде fdpf или tcpdf. В таком случае - просто используйте следующий код:

<?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<sender@domain.com>".$eol;
    $headers .= "Bcc: email@domain.com".$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);

    ?>
1 голос
/ 05 сентября 2010

Мне просто нужно было это выяснить, и мои глазные яблоки определенно болели к концу ...

1) Вам нужно установить PHPMailer на php-сервер.

2) Включите класс PHPmailer в ваш скрипт TCPDF, например, так (ваш путь может отличаться):

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

3) Теперь, после того, как ваш pdf-код, просто поговорите с PHPMailer следующим образом:

$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 = "noreply@yourhost.com";
$mail->FromName = "Stack Overflower";
$mail->AddAddress( $email, $name );  //  in this case the variable has been passed
$mail->AddCC( "person@somehost.net", "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

Конечно, у вас есть много возможностей для отправки электронной почты, например, не использовать html или отправлять html и текст, добавлять много получателей и / или копии и т. Д.

EDIT: это сохраняет файлвременно на сервере, но он очищает себя командой unlink.

0 голосов
/ 29 сентября 2010

Ваши заголовки выглядят немного не так:

  • application/octet-stream должно стать application/octetstream

  • Content-Disposition: attachment .. должно стать Content-Disposition: attachment; filename="' . basename($filename) . '"

вот как должны выглядеть заголовки вложений:

// attachment
$headers .= "--".$separator.$eol;
$headers .= "Content-Type: application/octetstream;".$eol; //Fixed
$headers .= "Content-Transfer-Encoding: base64".$eol;
$headers .= 'Content-Disposition: attachment; filename="' . basename(filename).'"'.$eol;
$headers .= 'Content-ID: <' . basename($filename) . '>' . $eol . $eol //EOL X2 Before
$headers .= $attachment;

//Run the above in a loop for multiple attachments, after add the final line
$headers .= '--' . $separator . '--' . $eol;

Это было взято из одного из моих рабочих приложений, вот цикл, если выхочу это увидеть:

foreach ($this->attachments as $attachment) { 
     if (file_exists($attachment['file'])) {
        $handle = fopen($attachment['file'], 'r');
        $content = fread($handle, filesize($attachment['file']));

        fclose($handle); 

        $message .= '--' . $boundary . $this->newline;
        $message .= 'Content-Type: application/octetstream' . $this->newline;   
        $message .= 'Content-Transfer-Encoding: base64' . $this->newline;
        $message .= 'Content-Disposition: attachment; filename="' . basename($attachment['filename']) . '"' . $this->newline;
        $message .= 'Content-ID: <' . basename($attachment['filename']) . '>' . $this->newline . $this->newline;
        $message .= chunk_split(base64_encode($content));
    }
}
$message .= '--' . $boundary . '--' . $this->newline; 
0 голосов
/ 20 сентября 2010

Я согласен с использованием почтовой библиотеки вместо создания сообщений MIME вручную с помощью функции mail () по умолчанию. SwiftMailer - еще одна хорошая почтовая библиотека PHP с открытым исходным кодом. Вот пример кода для использования динамического содержимого в качестве вложения без необходимости сначала сохранять его в файловой системе.

0 голосов
/ 01 сентября 2010

Вы также можете посмотреть на отправку в виде вложения через PEAR Mail_Mime .Он может принять вложение в виде строки данных.

Пакет RMail также выглядит так, как если бы он делал то же самое с помощью класса stringAttachment.Вам придется поискать его в Google, потому что я новый пользователь и поэтому могу публиковать только одну ссылку за раз.

0 голосов
/ 19 августа 2010

Взгляните на эту страницу, где обсуждается расширенная электронная почта на PHP.

http://articles.sitepoint.com/article/advanced-email-php/5

Они берут загруженный файл и загружают двоичные данные в $ data, но вы можете просто начать с этого.

...