2011-02-18 16 views
5

Estoy desarrollando una aplicación PHP que necesita recuperar correos electrónicos arbitrarios de un servidor de correo electrónico. Luego, el mensaje se analiza por completo y se almacena en una base de datos.Enviar correo desde el cuerpo sin procesar con fines de prueba

Por supuesto, tengo que hacer muchas pruebas ya que esta tarea no es realmente trivial con todos los diferentes formatos de correo bajo el sol. Por lo tanto, comencé a "recopilar" correos electrónicos de ciertos clientes y con diferentes contenidos.

Me gustaría tener un script para poder enviar esos correos automáticamente a mi aplicación para probar el manejo del correo.

Por lo tanto, necesito una forma de enviar los correos electrónicos en bruto, de modo que la estructura sea exactamente la misma que provendrían del cliente respectivo. Tengo los correos electrónicos almacenados como archivos .eml.

¿Alguien sabe cómo enviar correos electrónicos al suministrar el cuerpo sin procesar?

Editar: Para ser más específicos: Estoy buscando una manera de enviar correos electrónicos de varias partes mediante el uso de su código fuente. Por ejemplo, me gustaría poder usar algo como eso (un correo electrónico con partes simples y HTML, la parte HTML tiene un archivo adjunto en línea).

--Apple-Mail-159-396126150 
Content-Transfer-Encoding: quoted-printable 
Content-Type: text/plain; 

The plain text email! 

--=20  

=20 
=20 

--Apple-Mail-159-396126150 
Content-Type: multipart/related; 
    type="text/html"; 
    boundary=Apple-Mail-160-396126150 


--Apple-Mail-160-396126150 
Content-Transfer-Encoding: quoted-printable 
Content-Type: text/html; 
    charset=iso-8859-1 

<html><head> 
    <title>Daisies</title>=20 
</head><body style=3D"background-attachment: initial; background-origin: = 
initial; background-image: = 
url(cid:4BFF075A-09D1-4118-9AE5-2DA8295BDF33/bg_pattern.jpg); = 
background-position: 50% 0px; "> 

[ - snip - the html email content ] 


</body></html>= 

--Apple-Mail-160-396126150 
Content-Transfer-Encoding: base64 
Content-Disposition: inline; 
    filename=bg_pattern.jpg 
Content-Type: image/jpg; 
    x-apple-mail-type=stationery; 
    name="bg_pattern.jpg" 
Content-Id: <4BFF075A-09D1-4118-9AE5-2DA8295BDF33/tbg.jpg> 

/9j/4AAQSkZJRgABAgAAZABkAAD/7AARRHVja3kAAQAEAAAASAAA/+IFOElDQ19QUk9GSUxFAAEB 
[ - snip - the image content ] 
nU4IGsoTr47IczxmCMvPypi6XZOWKYz/AB42mcaD/9k= 

--Apple-Mail-159-396126150-- 
+0

¿Te ha encontrar alguna solución a este problema? – Johannes

+0

No, desafortunadamente no. – hbit

+0

Creo que le falta la parte principal, que con el encabezado del tema y con la sección multiparte para que su MTA sepa qué hacer. Por lo tanto, sus archivos .eml están incompletos. En un correo electrónico de varias partes, la parte raíz (la que falta) debe contener algo como esto "Content-Type: multipart/alternative; boundary =" _---------- = _ MCPart_465790590 "". Esto especificará a cualquier mimeparser qué parte leer primero, y así sucesivamente. –

Respuesta

0

Usando PHPMailer, puede configurar el cuerpo de un mensaje directamente:

$mail->Body = 'the contents of one of your .eml files here' 

Si su correo electrónico contienen los archivos adjuntos MIME, lo más probable es que no funcione correctamente, ya que algunas de las cosas MIME tiene para ir a los encabezados del correo. Habría que dar masajes a la .eml para extraer los encabezados de particulares y agregarlos al correo PHPMailer como CustomHeader

+0

Desafortunadamente esto no ayuda mucho. Por ejemplo, un caso de prueba interesante es que los archivos adjuntos en Apple Mail a menudo tienen la disposición "en línea", mientras que la mayoría de los otros clientes solo utilizan "datos adjuntos". Y, por lo tanto, me gustaría enviar algo como: --Apple-Mail-4-698704782 Content-Disposition: inline; \t filename = "bla.pdf" .... Sé que ciertos elementos del encabezado también deben ir al nuevo correo, pero eso no debería ser tan importante: simplemente filtre las cosas importantes (recibidas, remitentes) , to, ...) y use los campos de encabezado restantes nuevamente. – hbit

0

Se podía utilizar el programa telnet para enviar los correos electrónicos:

$ telnet <host> <port>     // execute telnet 
HELO my.domain.com      // enter HELO command 
MAIL FROM: [email protected]   // enter MAIL FROM command 
RCPT TO: [email protected]   // enter RCPT TO command 
<past here, without adding a newline> // enter the raw content of the message 
[ctrl]+d        // hit [ctrl] and d simultaneously to end the message 

Si realmente desea hacer esto en PHP, puede usar fsockopen() o stream_socket_client() familia. Básicamente, haces lo mismo: hablar directamente con el servidor de correo.

// open connection 
$stream = @stream_socket_client($host . ':' . $port); 

// write HELO command 
fwrite($stream, "HELO my.domain.com\r\n"); 

// read response 
$data = ''; 
while (!feof($stream)) { 
    $data += fgets($stream, 1024); 
} 

// repeat for other steps 
// ... 

// close connection 
fclose($stream); 
+0

Sí, necesito hacer esto en PHP. ¿Puedes explicar cómo esto funciona con PHP? ¿Cuáles son los peligros potenciales al hablar directamente con el servidor de correo? Puedo imaginar que hay algunos ... – hbit

+0

Este método es realmente más confiable que usar [mail()] (http://www.php.net/manual/en/function.mail.php). Un inconveniente es que tendrás que manejar algunos errores tú mismo, pero 'mail()' falla en eso, así que tal vez no sea un inconveniente.Y como lo necesita para probar, no lo necesita perfecto :) –

0

Puedes usar la función de compilación en PHP mail para ello. La parte body no tiene que ser solo texto, también puede contener datos de piezas mixtas.

Tenga en cuenta que esto es una prueba de concepto. La función sendEmlFile podría usar algo más de comprobación, como "¿Existe el archivo?" Y "¿Tiene un conjunto de delimitación?". Como mencionaste es para probar/desarrollar, no lo he incluido.

<?php 
function sendmail($body,$subject,$to, $boundry='') { 
    define ("CRLF", "\r\n"); 

    //basic settings 
    $from = "Example mail<[email protected]>"; 

    //define headers 
    $sHeaders = "From: ".$from.CRLF; 
    $sHeaders .= "X-Mailer: PHP/".phpversion().CRLF; 
    $sHeaders .= "MIME-Version: 1.0".CRLF; 


    //if you supply a boundry, it will be send with your own data 
    //else it will be send as regular html email 
    if (strlen($boundry)>0) 
     $sHeaders .= "Content-Type: multipart/mixed; boundary=\"".$boundry."\"".CRLF; 
    else 
    { 
     $sHeaders .= "Content-type: text/html;".CRLF."\tcharset=\"iso-8859-1\"".CRLF; 
     $sHeaders .= "Content-Transfer-Encoding: 7bit".CRLF."Content-Disposition: inline"; 
    } 

    mail($to,$subject,$body,$sHeaders); 
} 

function sendEmlFile($subject, $to, $filename) { 
    $body = file_get_contents($filename); 
    //get first line "--Apple-Mail-159-396126150" 
    $boundry = $str = strtok($body, "\n"); 

    sendmail($body,$subject,$to, $boundry); 
} 
?> 

Actualización:

Después de algunas pruebas más me encontré con que todos .eml archivos son diferentes. Puede haber un estándar, pero tuve toneladas de opciones al exportar a .eml. Tuve que usar una herramienta separada para crear el archivo, porque no se puede guardar en .eml de manera predeterminada usando Outlook.

Puede descargar un example of the mail script. Contiene dos versiones.

La versión simple tiene dos archivos, uno es el archivo index.php que envía el archivo test.eml. Este es solo un archivo donde pegué el código de ejemplo que publicó en su pregunta.

La versión avanzada envía un correo electrónico utilizando un archivo .eml real que he creado. obtendrá los encabezados necesarios del archivo en sí mismo. Tenga en cuenta que esto también configura la parte To y From del correo, así que cámbiela para que coincida con su configuración/servidor.

El código avanzado funciona así:

<?php 
function sendEmlFile($filename) { 
    //define a clear line 
    define ("CRLF", "\r\n"); 

    //eml content to array. 
    $file = file($filename); 

    //var to store the headers 
    $headers = ""; 
    $to = ""; 
    $subject = ""; 

    //loop trough each line 
    //the first part are the headers, until you reach a white line 
    while(true) { 
     //get the first line and remove it from the file 
     $line = array_shift($file); 
     if (strlen(trim($line))==0) { 
      //headers are complete 
      break; 
     } 

     //is it the To header 
     if (substr(strtolower($line), 0,3)=="to:") { 
      $to = trim(substr($line, 3)); 
      continue; 
     } 

     //Is it the subject header 
     if (substr(strtolower($line), 0,8)=="subject:") { 
      $subject = trim(substr($line, 8)); 
      continue; 
     } 

     $headers .= $line . CRLF; 
    } 

    //implode the remaining content into the body and trim it, incase the headers where seperated with multiple white lines 
    $body = trim(implode('', $file)); 

    //echo content for debugging 
    /* 
    echo $headers; 
    echo '<hr>'; 
    echo $to; 
    echo '<hr>'; 
    echo $subject; 
    echo '<hr>'; 
    echo $body; 
    */ 

    //send the email 
    mail($to,$subject,$body,$headers); 
} 


//initiate a test with the test file 
sendEmlFile("Test.eml"); 
?> 
+0

¿Estás seguro de que funcionaría? Como veo, incluyes cierta información MIME en el parámetro de encabezados. ¿Pero lo haría con complejos MIME estructurados, de múltiples niveles que tienen varias partes de cuerpo y de fijación? Simplemente no estoy seguro de cómo dividir eso. Puedes profundizar sobre eso? – hbit

+0

Es por eso que configura el 'límite' en el encabezado. Cada parte del cuerpo (html/texto sin formato/archivo adjunto/imagen en línea/etc.) se divide con un boundry. Vea su propio ejemplo de Apple. –

+0

Y no tienes que dividirlo. EG: Su entero ejemplo (con '--Apple-Mail-159-396126150' etc.) sería el cuerpo del correo electrónico. Si lo envía como está, recibirá un correo electrónico con un archivo adjunto. Sin embargo, el archivo adjunto fallaría debido al [snip] que incluyó –

0

Simplemente haga un guión de shell rápido que procese un directorio y llámelo cuando lo desee, p. utilizando atcrontab etc

porque en ls /mydir/ hacer cat I | awk .. | sendmail -options

http://www.manpagez.com/man/1/awk/

También puede simplemente hablar con el servidor de correo utilizando la secuencia de comandos para enviar el emls con un cuerpo de plantilla ..

+0

El punto es la cuestión de cómo procesar por lotes los emls: es el lado del cliente de correo electrónico de las cosas que manejan el envío real basado en archivos eml. – hbit

+0

Los emls se pueden dividir con 'awk'? – Jay

Cuestiones relacionadas