2010-08-19 7 views
7

Ostatnio utworzyłem internetowy szablon do tworzenia ofert pracy dla naszej witryny. Wszystko jest zrobione, formatuje się poprawnie w przeglądarce, automatycznie publikuje na naszej stronie internetowej, bla bla bla.Wysyłanie e-mailem dynamicznie utworzonego pliku PDF za pośrednictwem PHP

Ostatni element, który tworzę, to dać administratorowi kilka opcji dystrybucji ogłoszeń w różnych miejscach (za pośrednictwem poczty elektronicznej) w spójny i wygodny sposób. Stworzyłem stronę PHP, która na bieżąco tworzy dokument PDF, korzystając z biblioteki TCPDF. Podczas ładowania pliku pdf.php? Id = X strona wyświetla plik PDF z zawartością zadania X. Oznacza to, że nigdy nie zapisuję pliku PDF na serwerze, po prostu tworząc go w locie za każdym razem, gdy jest wywoływany.

Ale chcę dołączyć ten plik PDF do wiadomości e-mail i wysłać go do różnych szkół wyższych, wewnętrznych list adresowych itp. Jeśli dołączę plik pdf.php? Id = x do wiadomości e-mail, nie zostanie on dołączony do wiadomości e-mail. PDF, dołącza to, co wydaje się pustym plikiem, o powyższej nazwie.

Czy można dołączyć to do wiadomości e-mail bez zapisywania jej na serwerze?


Poniżej dodano na podstawie odpowiedzi JM4 na dalsze rozwiązywanie problemów. Umieściłem tworzenie pliku PDF w funkcji i umieściłem go w pliku włączającym, aby ułatwić zarządzanie.

// 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'; 
} 

Oto okrojona wersja 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"); 
} 
+0

Pokaż nam kod (lub korzystnie bardzo wycięty dół szkielet). Wygląda na to, że metoda, której używasz, aby zmienić adres URL w załącznik do pliku, jest niepoprawna. Dlaczego tak bardzo zależy ci na tym, aby nie zapisywać pliku nawet tymczasowo? – symcbean

+0

http://api.joomla.org/com-tecnick-tcpdf/TCPDF.html#methodOutput Używam opcji "I" dla dest. Zastanawiam się, czy opcja S jest tym, czego powinienem używać. –

+0

czy któraś z odpowiedzi tutaj pomogła? – JM4

Odpowiedz

0

Być może zechcesz również spojrzeć na wysyłanie go jako załącznika przez PEAR Mail_Mime. Może przyjąć załącznik jako ciąg danych.

Pakiet RMail wygląda również tak, jakby zrobił to samo poprzez klasę stringAttachment. Będziesz musiał google, ponieważ jestem nowym użytkownikiem, więc mogę opublikować tylko jeden link na raz.

5

Jeśli całkowicie zrozumiem, o co prosisz, jest to całkiem proste. Zakładam, że masz już wygenerowany plik PDF przy użyciu czegoś takiego jak fdpf lub tcpdf. W tym przypadku - po prostu użyć następującego kodu:

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

    ?> 
+0

Masz właściwy pomysł. Wszystko tu działa, ale kiedy dojdzie do linii, aby wysłać e-mail, wydaje się, że zawiesi się w nieskończoność. Bez błędu, bez niczego. Czy istnieje limit nagłówków, które można przekazać? To niewiele ponad 810 000 znaków (ale to tylko jednostronicowy plik PDF). –

+0

@Cory - Mój skrypt działa. jeśli jest zawieszony, jest coś złego lub innego w twoim skrypcie pdf. Użyłem powyższych na 100 stron pdf bez problemu. Nie ma ograniczenia liczby nagłówków, które można przekazać. Opublikuj swój aktualny kod w edycji, abyśmy mogli zobaczyć. – JM4

+0

Dzięki JM4, dodałem kod w oryginalnym poście. Tak jak powiedziałem, zrobi wszystko oprócz rzeczywistego połączenia mail(). Mogę więc wyprowadzać nagłówki $ za pomocą echa bez żadnych problemów. –

1

miałem tylko dowiedzieć się tego i moje gałki oczne były zdecydowanie ból do końca ...

1) Musisz zainstalować PHPMailer do php serwer.

2) obejmują klasę PHPMailer w skrypcie TCPDF, jak tak (ścieżka może się różnić):

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

3) Teraz po kod pdf po prostu porozmawiać z PHPMailer tak:

$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 

Oczywiście masz wiele opcji wysyłania e-maili, takich jak nie używanie html lub wysyłanie zarówno html, jak i tekstu, dodawanie wielu odbiorców i/lub cc itp.

EDYCJA: Zapisuje plik tymczasowo na serwerze, ale po nim sam usuwa za pomocą polecenia odłączenia.

+0

Twoje rozwiązanie sugeruje, że musi załadować skrypty PHP Mailer do swojego katalogu, co nie jest prawdą. Proste polecenia PHP Mail() będą wysyłać wiadomości e-mail. Nie musisz również zapisywać pliku PDF, ponieważ sugerujesz, że działa poprawnie, jak $ pdf-> Dane wyjściowe ($ filename, 'S'); – JM4

+0

Dzięki - W rzeczywistości, gdy poczta działa, phpmailer jest znacznie lepszy, tj. Potrzebowałem uwierzytelnionych funkcji SMTP. Przypuszczam, że opcja "S" zachowałaby temp pracy w pamięci, a nie jako rzeczywisty plik na dysku ... jeśli możesz podać działający przykład ... Mam błąd nieudanego otwarcia strumienia. – Mischa

0

Zgadzam się na używanie biblioteki poczty zamiast ręcznego budowania wiadomości MIME przy użyciu domyślnej funkcji mail(). SwiftMailer to kolejna dobra biblioteka pocztowa PHP o otwartym kodzie źródłowym. Oto sample code do używania dynamicznej zawartości jako załącznika bez konieczności zapisywania go najpierw w systemie plików.

0

Twoje nagłówki wydają się być trochę:

  • application/octet-stream powinna stać application/octetstream

  • Content-Disposition: attachment .. powinna stać Content-Disposition: attachment; filename="' . basename($filename) . '"

herezje co nagłówki Attachement powinna wyglądać następująco:

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

ten został zaczerpnięty z jednego z moich zastosowaniach roboczych, Herezje pętlę, jeśli chcesz je zobaczyć:

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

jak byś to zrobił, gdyby plik pdf nie istniał na serwerze, ale przez URL z tcpdf? – Alex

Powiązane problemy