2010-08-19 31 views
7

Recientemente he creado una plantilla en línea para crear ofertas de trabajo para nuestro sitio web. Todo está hecho, se formatea correctamente en un navegador y se publica automáticamente en nuestro sitio web, bla bla bla.Envío por correo electrónico de un PDF creado dinámicamente a través de PHP

La última pieza que estoy creando es para darle al administrador algunas opciones para distribuir la publicación en varios lugares (por correo electrónico) de una manera consistente y conveniente. Creé una página PHP que crea un documento PDF sobre la marcha, utilizando la biblioteca TCPDF. Al cargar pdf.php? Id = X, la página muestra un PDF con el contenido de la publicación de trabajo X. Esto significa que nunca guardo el archivo PDF en el servidor, simplemente lo creo sobre la marcha cada vez que se lo llama.

Pero quiero adjuntar este PDF a un correo electrónico, y enviarlo a varias universidades, listas de correo internas, etc. Si adjunto el pdf.php? Id = x al correo electrónico, no se adjunta el PDF, adjunta lo que parece ser un archivo en blanco, con el nombre anterior.

¿Es posible adjuntar esto al correo electrónico sin guardarlo en el servidor?


Debajo se agregó en función de la respuesta de JM4 para más problemas. Puse la creación del archivo PDF en una función y lo puse en un archivo de inclusión, solo para facilitar la administración.

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

Aquí es una versión simplificada de 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

Muéstranos el código (o preferiblemente un esqueleto muy cortado). Parece que el método que está utilizando para convertir la URL en un archivo adjunto es incorrecto. ¿Por qué estás tan preocupado por no escribir un archivo, incluso temporalmente? – symcbean

+0

http://api.joomla.org/com-tecnick-tcpdf/TCPDF.html#methodOutput Estoy usando la opción 'I' para dest. Me pregunto si la opción S es lo que debería estar usando. –

+0

¿Alguna de las respuestas aquí te ayudó? – JM4

Respuesta

0

Es posible que desee consultar el envío como archivo adjunto a través del PEAR Mail_Mime. Puede aceptar un archivo adjunto como una cadena de datos.

El paquete de RMail también parece que va a hacer lo mismo a través de la clase stringAttachment. Tendrás que buscar en Google, porque soy un nuevo usuario y, por lo tanto, puedo publicar solo un enlace a la vez.

5

Si entiendo completamente lo que está preguntando, esto es bastante simple. Supongo que ya tiene el PDF generado usando algo como fdpf o tcpdf. En ese caso - sólo tiene que utilizar el siguiente código:

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

Tiene la idea correcta. Todo aquí funciona, pero cuando llega a la línea para enviar realmente el correo electrónico, parece colgar indefinidamente. Sin error, sin nada. ¿Hay un límite para los encabezados que pueden pasarse? Esto es un poco más de 810,000 caracteres (pero es solo un PDF de una página). –

+0

@Cory - Mi script funciona. si está colgando, hay algo incorrecto o diferente en tu script pdf. He utilizado lo anterior para páginas de 100 pdfs sin problema. No hay límite en la cantidad de encabezados que se pueden pasar. Publica tu código real en una edición para que podamos ver. – JM4

+0

Gracias JM4, he agregado el código en la publicación original. Como dije, hará todo menos la llamada real de mail(). Así que puedo generar $ encabezados por echo sin problemas. –

1

sólo tenía que resolver esto y mis ojos estaban definitivamente dolor por el final ...

1) Es necesario instalar PHPMailer a la php servidor.

2) Incluir la clase PHPMailer en el script TCPDF, al igual que (su ruta puede variar):

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

3) Ahora, después de su código pdf simplemente hablar con PHPMailer así:

$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 

Por supuesto que tiene muchas opciones para el correo electrónico enviado, como no usar html, o enviar tanto html como texto, agregar muchos destinatarios y/o cc's, etc.

EDITAR: Esto guarda el archivo temporalmente en el servidor, pero se limpia después de sí mismo con el comando desvincular.

+0

Su solución implica que necesita cargar los scripts de PHP Mailer a su directorio, que no es el caso. Los comandos simples de PHP Mail() enviarán correo electrónico. Tampoco necesita guardar el archivo PDF como usted lo implica, funciona muy bien como $ pdf-> Salida ($ nombre de archivo, 'S'); – JM4

+0

Gracias- En realidad, mientras el correo funciona, phpmailer es mucho mejor, es decir, necesitaba las funciones SMTP autenticadas. Supongo que la opción 'S' mantendría la temperatura temporal en la memoria y no como un archivo real en el disco ... si puede proporcionar un ejemplo de trabajo ... Recibí un error de transmisión fallida. – Mischa

0

Acepto el uso de una biblioteca de correo en lugar de crear mensajes mime a mano con la función predeterminada de correo(). SwiftMailer es otra buena biblioteca de correo PHP de código abierto. Aquí está el sample code para usar contenido dinámico como archivo adjunto sin tener que guardarlo primero en el sistema de archivos.

0

Sus cabeceras parecen ser un poco fuera:

  • application/octet-stream debe convertirse en application/octetstream

  • Content-Disposition: attachment .. debe convertirse en Content-Disposition: attachment; filename="' . basename($filename) . '"

heres lo que las cabeceras attachement debe ser similar:

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

Esto fue tomado de una de mis aplicaciones de trabajo, aquí está el bucle si desea verlo:

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

¿cómo harías eso si el pdf no existe en el servidor pero a través de la url con tcpdf? – Alex

Cuestiones relacionadas