• Publicidad

CGI que envíe un mail multipart

Todo lo relacionado con el desarrollo Web con Perl: desde CGI hasta Mojolicious

CGI que envíe un mail multipart

Notapor lacris » 2016-05-12 05:38 @276

¡Buenos días!

Estoy tratando de programar un CGI que, entre otras cosas, envíe un correo con determinado texto y con una imagen a modo de firma.

Mi código es este:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my $correo = Email::MIME->create(
  2.                 attributes => {
  3.                     content_type => 'multipart/alternative',
  4.                 },
  5.                 header_str => [
  6.                     From    =>  'usuario',
  7.                     To      => join(',', @direcciones),
  8.                     Subject => encode('MIME-B', $asunto),
  9.                 ],
  10.                 parts => [
  11.                     Email::MIME->create(
  12.                         attributes => {
  13.                             content_type => 'text/plain' ,
  14.                             encoding     => 'quoted-printable',
  15.                             charset      => 'utf-8',
  16.                         },
  17.                         body => $cuerpoCorreo,
  18.                     ),
  19.                     Email::MIME->create(
  20.                         attributes => {
  21.                             content_type => 'text/html'
  22.                         },
  23.                         body => '<img src="firma.png">',
  24.                     )
  25.                 ],
  26. );
  27.  
  28. my $transporte = Email::Sender::Transport::SMTP::TLS->new(
  29.                     host     => 'servidor.correo.es',
  30.                     port     => 587,
  31.                     username => 'usuario',
  32.                     password => 'contraseña',
  33. );
  34.  
  35. try {
  36.     sendmail( $correo, {transport => $transporte} );
  37. }
  38. catch {
  39.     print "<br><b>Error enviando datos: $_</b><br><br>";
  40. };
Coloreado en 0.005 segundos, usando GeSHi 1.0.8.4


Pero no lo consigo. Me llega solo la segunda parte y mal: ayer llegué a recibir la imagen sola. Hoy (que no he tocado nada) me llega el icono de cuando muestras una imagen de una dirección que no existe. La imagen firma.png está en el mismo directorio que el CGI.

Cualquier ayuda, indicación, recomendación, etc ¡será bienvenida!

¡Muchas gracias!

Cristina
Última edición por explorer el 2016-05-12 15:57 @706, editado 1 vez en total
Razón: Poner marcas de código Perl
lacris
Perlero nuevo
Perlero nuevo
 
Mensajes: 11
Registrado: 2016-04-18 10:38 @484

Publicidad

Re: CGI que envíe un mail multipart

Notapor explorer » 2016-05-12 17:59 @791

Claro, es que eso es justo lo que significa multipart/alternative: estás indicando que el correo se compone de partes, cada una de ellas de un determinado tipo MIME, y tiene que ser el cliente de correo el que debe decidir cuál es el mejor que puede presentar en pantalla.

Si envías una primera parte que es puro texto, y una segunda parte que es HTML, y se lo envías a alguien, en que su cliente no tiene problemas para ver HTML, pues elegirá ver esa parte, Y SOLO ESA PARTE.

Yo... quitaría la parte de attributes de las líneas 2 a 4. Me parece que he leído en la documentación de Email::MIME que se definiría un content_type multipart/related, que creo que es lo que quieres. Mira la parte de SINOPSIS, al final, y verás que crean un correo multiparte de forma muy sencilla.

De todas formas... crear un HTML es algo complicado. En un correo puede haber varias partes (alternative), pero dentro de la parte HTML, a su vez, se divide en varias partes: una para el HTML y las demás para el resto de recursos que solicita ese HTML.

En Email::MIME::CreateHTML hay una mejor explicación. Y es un módulo específico para crear correos con HTML.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: CGI que envíe un mail multipart

Notapor lacris » 2016-05-13 03:12 @175

¡Muchas gracias!

Voy a echar un vistazo a ese módulo específico para crear HTML.

¡Un saludo!
Cristina
lacris
Perlero nuevo
Perlero nuevo
 
Mensajes: 11
Registrado: 2016-04-18 10:38 @484

Re: CGI que envíe un mail multipart

Notapor lacris » 2016-05-13 04:24 @225

¡Se me está complicando demasiado la cosa!

He pensado en poner una firma "construida" en el cuerpo del mensaje pero ahora me encuentro con que no puedo hacer un salto de línea normalito sin dejar espacios entre líneas.

He probado todo tipo de combinaciones pero algo debo estar haciendo mal porque no consigo un simple salto de línea (no de párrafo):

$cuerpoCorreo = $cuerpoCorreo . "Para cualquier informacion podra solicitar cualquier aclaracion a traves del correo electronico [email protected] \n\n";
$cuerpoCorreo = $cuerpoCorreo . "Agradeciendo su interes, reciba un cordial saludo. \n\n";
$cuerpoCorreo = $cuerpoCorreo . "------------------------------------------------------- \n\n";
$cuerpoCorreo = $cuerpoCorreo . "Servicio de Compras\n\r";
$cuerpoCorreo = $cuerpoCorreo . "Dirección\r\n";

Cuyo resultado es:
***********************
Para cualquier informacion podra solicitar cualquier aclaracion a traves del correo electronico xxxxx.es --> NO saca la @servidor
Agradeciendo su interes, reciba un cordial saludo.

-------------------------------------------------------

Servicio de Compras Direccion
***********************

Aprovecho para preguntar por los acentos... (esto para mi ya es para nota).

¡Gracias!
Cristina
lacris
Perlero nuevo
Perlero nuevo
 
Mensajes: 11
Registrado: 2016-04-18 10:38 @484

Re: CGI que envíe un mail multipart

Notapor explorer » 2016-05-13 18:16 @803

El problema de la '@' es que la tienes dentro de una cadena de caracteres que está entrecomillada doble, y Perl piensa que lo que quieres hacer es sacar el contenido del array @servidor :)

La solución pasa por "escapar" la '@' para que Perl sepa que tiene que sacarlo de forma literal, y que no inicia una variable array. Eso lo haces poniendo una '\' delante de la arroba. Perl te habría avisado de esto si hubieras puesto 'use warnings;' al principio del programa.

No sé porqué estás obligada a poner un doble carácter de fin de línea, pero deberíamos saber si estamos hablando de la parte de texto simple, o de la HTML.

Te aconsejo que no uses el carácter "\r", salvo que el protocolo de red así lo indique. Por regla general, no hace falta.

Una cosilla... no hace repetir la variable en asignaciones como esta:

$cuerpoCorreo = $cuerpoCorreo . "Servicio de Compras\n\n";

La forma abreviada es esta:

$cuerpoCorreo .= "Servicio de Compras\n\n";

Con el siguiente programa he conseguido enviar correo con varias partes MIME:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use Email::MIME;
  3. use Email::Sender::Simple qw(sendmail);
  4. use Email::Sender::Transport::SMTP qw();
  5. use Try::Tiny;
  6. use utf8;
  7.  
  8. my $correo = Email::MIME->create(
  9.                 attributes => {
  10.                     content_type => 'multipart/alternative',
  11.                 },
  12.                 header_str => [
  13.                     From    => '[email protected]',
  14.                     To      => '[email protected]',
  15.                     Subject => 'Asunto: pruebas',
  16.                 ],
  17.                 parts => [
  18.                     Email::MIME->create(
  19.                         attributes => {
  20.                             content_type => 'text/plain' ,
  21.                             # encoding     => 'quoted-printable',
  22.                             charset      => 'utf-8',
  23.                         },
  24.                         body => "Este es el cuerpo. áéíóúñÁÉÍÓÚÑ",
  25.                     ),
  26.                     Email::MIME->create(
  27.                         attributes => {
  28.                             content_type => 'text/html'
  29.                         },
  30.                         body => '<h1>Test</h1>',
  31.                     )
  32.                 ],
  33. );
  34.  
  35. try {
  36.     sendmail(
  37.         $correo,
  38.         {
  39.             transport => Email::Sender::Transport::SMTP->new(
  40.                             host     => 'correo.servidor.com',
  41.                             helo     => 'nuestra.maquina.com',
  42.                             port     => 25,
  43.                             username => 'usuario',
  44.                             password => 'contraseña',
  45.                             debug    => 1,
  46.             )
  47.         }
  48.     );
  49. }
  50. catch {
  51.     print "Error enviando datos: $_";
  52. };
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


Como se ha dicho antes: el atributo content_type de attributes indica el aspecto de todo el documento. Si ponemos alternative, saldrá la versión texto o la HTML, según escoja el usuario. Si ponemos mixed, saldrán las dos. Y hay otra opción más, que no recuerdo.

Como el programa hay cadenas con caracteres con tildes, y estoy escribiendo en un editor/terminal con soporte de utf8, pongo el 'use utf8' para indicar que en todo el programa, en los literales y expresiones regulares, los caracteres están codificados de esa manera. Esto también facilita que los textos sean enviados así por correo. Y así también lo ponemos en el charset.

No me ha funcionado el encoding => 'quoted-printable', pero creo que es una cosa propia de mi programa de correo.

El debug => 1 sirve para ver qué está haciendo el programa.

Si, en tu caso, quieres poner adjuntos que sean imágenes, debes indicar, en la parte MIME del HTML, que se compone a su vez de un grupo de partes MIME. La primera será el HTML, y luego una por cada imagen. Cada imagen debe ser leída en formato binario, y puesta en cada parte, con un nombre.

En la página de manual de Email::MIME, en la sinopsis, vienen todos estos casos.

Lo que no está documentado es un ejemplo para ver cómo se refiere desde el código HTML a cada imagen, pero creo que era que con el nombre coincidiese, bastaba.

El propio manual aconseja el uso de Email::Stuffer, ya que es muchísimo más fácil adjuntar los archivos y crear el HTML.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: CGI que envíe un mail multipart

Notapor lacris » 2016-05-16 03:14 @177

Muchas gracias, explorer.

Me di cuenta lo de escapar la "@" y ya vi que me llegaba bien.

Lo de "\n\n" o "\r\n" o cosas similares es porque si únicamente ponía "\n" no me hacía ni el retorno de carro ni nada. Me saca todo en una misma línea. No consigo que me haga únicamente un cambio de línea y no de párrafo.

Voy a intentar hacer algo similar al ejemplo que me envías y ya te contaré.

¡Un cordial saludo!
Cristina
lacris
Perlero nuevo
Perlero nuevo
 
Mensajes: 11
Registrado: 2016-04-18 10:38 @484

Re: CGI que envíe un mail multipart (Resuelto)

Notapor lacris » 2016-05-17 03:17 @178

¡Buenos días!

¡Lo conseguí! Al final con el Email::Stuffer que me dijiste me funcionó.

Me queda la duda de cómo controlar si el mensaje ha ido bien o no. Me explico: Antes hacía:
my $correcto="NO";
try {
sendmail( $correo, {transport => $transporte} );
$correcto = "SI"; --> Lo uso para insertarlo en BD

} catch {
print "<br><b>Error enviando datos: $_</b>";
};


Y ahora no sé cómo hacerlo ya que me ha funcionado de la siguiente manera:

Email::Stuffer
-> html_body($html)
->subject(encode('MIME-B', $asunto))
->from ('[email protected]')
->to (join(',', @direccionesBcc))
->transport(Email::Sender::Transport::SMTP::TLS->new(
host => 'smtp.servidor.es',
port => 587,
username => '[email protected]',
password => '*******',
))
->send;

Según leo, si el send() va mal devuelve un false pero no sé dónde o cómo controlarlo.

¿Puedes ayudarme con esto?

¡Muchísimas gracias!
Cristina
lacris
Perlero nuevo
Perlero nuevo
 
Mensajes: 11
Registrado: 2016-04-18 10:38 @484

Re: CGI que envíe un mail multipart

Notapor lacris » 2016-05-17 03:37 @192

¡Ya está!

He probado a hacer esto y parece que va bien:

my $correo =
Email::Stuffer
-> html_body($html)
->subject(encode('MIME-B', $asunto))
->from ('[email protected]')
->to (join(',', @direccionesBcc))
->transport(Email::Sender::Transport::SMTP::TLS->new(
host => 'smtp.servidor.es',
port => 587,
username => '[email protected]',
password => '*******',
));

try {
$correo->send;
$correcto="SI";
} catch {
print "<br><b>Error enviando datos: $_</b>";
};

Aunque no sé si es mejor con un if(). ¿Qué opinas?

¡Gracias!
Cristina
lacris
Perlero nuevo
Perlero nuevo
 
Mensajes: 11
Registrado: 2016-04-18 10:38 @484

Re: CGI que envíe un mail multipart

Notapor explorer » 2016-05-17 16:38 @735

Con un try{} catch{} te aseguras que capturas algún posible error grave, pero lo normal es que esos errores graves ya estén capturados por el send().

Lo podrías dejar con algo sencillo:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my $se_envio_correctamente = $correo->send();
  2.  
  3. if ($se_envio_correctamente) {
  4.     # ...
  5. }
  6. else {
  7.     # ...
  8. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


O incluso
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. if ($correo->send()) {
  2.     # ...
  3. }
  4. else {
  5.     # ...
  6. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España


Volver a Web

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 3 invitados

cron