Enviar correo con imágenes incrustadas con Delphi

Hace tiempo publiqué en nuestra zona de descargas un programa que envía correo electrónico en formato HTML con imágenes incrustadas. Así que he creado esta entrada para dar una breve explicación del mismo. Aunque el ejemplo está desarrollado en Delphi 7, este puede ser implementado en cualquier versión superior a D7.

Al instalar Delphi, este viene con la suite de componentes Indy instalada, esta suite de componentes es de libre uso y cuenta con valiosas clases que nos permiten conectarnos a servicios como http, ftp, smntp, gopher, pop, etc. Además nos brinda componentes que nos permiten la comunicación sobre Ip a través de Sockets tanto para los protocolos tcp como udp. En el caso que atiende esta entrada haremos uso del componente TIdSMTP que nos permite el envío de correo electrónico, de la clase TIdMessage y de la clase TIdAttachment. Responsables de la comunicación con el servidor de correo, la gestión del contenido del correo y la gestión de los archivos adjuntos del mismo. Si deseas conocer más acerca de estos componentes y clases te recomiendo visitar el sitio oficial de Indy.

Es importante mencionar que para D7 será necesario actualizar los componentes de Indy a por lo menos la versión 9.0.18.

El programa que he publicado a modo de ejemplo, realiza el envío de un correo electrónico con una imagen de cualquier tamaño o tipo a una dirección de correo electrónico cualquiera. Esta es la pantalla del mismo

El truco para enviar imágenes incrustadas en el correo está en dos partes, la primera en que el formato del mensaje debe ser Html y la imagen que se adjunte le debe ser asignado un GUID que es un identificador único global, si deseas saber más acerca de esto aquí puedes encontrar información de lo que es GUID.

Muy bien comencemos a revisar el código del programa. El código responsable de enviar el correo electrónico se encuentra en el evento OnClik del botón “Enviar correo” pues este a su vez llama al método “EnviaCorreoHtml” que explicaré a continuación.

Se declaran las instancias de clase responsables de armar el cuerpo del correo electrónico y de adjuntar un archivo:

var
  LIdmMensaje: TIdMessage; //Define el contenido del correo electrónico así como su formato
  LIdmGraf: TIdAttachment; //Responsable de la carga del 
                           //archivo a enviar junto con el correo electrónico

Después será necesario generar un identificador para la imagen por adjuntar, para ello he creado el siguiente método:

Function TForm1.DameImgID(Var PsIdGraf: String): String;
Var
  lGUIDIdentif: TGUID; //Objeto para obtener el Identificador único global
Begin
  Result := 'Nada';
  Try
    //Obtiene un identificador único global
    CreateGUID(lGUIDIdentif);
    //Convierte el identificador obtenido a formato cadena
    PsIdGraf := StringReplace(StringReplace(StringReplace(GUIDToString(lGUIDIdentif), '-', '',
[rfReplaceAll]), '{', '', [rfReplaceAll]), '}', '', [rfReplaceAll]);
  Except
    on Err : Exception do
      Result := Err.Message;
  End;
End;

Es importante generar este identificador pues será él quien nos permita incrustar nuestra imagen en el contenido del correo.  Hecho lo anterior procedemos al armado del contenido del correo que como podrán ver se encuentra en formato Html:

        LStlMensaje := TStringList.Create;
        LStlMensaje.Add('<HTML><HEAD><TITLE>Prueba de imágenes</TITLE></HEAD><BODY><BODY>');
        LStlMensaje.Add('<table border="0" cellpadding="0" cellspacing="0" width="800">');
        LStlMensaje.Add('  <tr>');
        LStlMensaje.Add('    <td colspan="3"><img border="0" src="cid:' + LsGIdImage + '" >');
        LStlMensaje.Add('      <p>&nbsp;</td>');
        LStlMensaje.Add('  </tr>');
        LStlMensaje.Add('</table>');

Si observan el código anterior veremos que la etiqueta de imagen hace referencia a un Cid que apunta al Guid generado previamente. Es esta línea la que le dice al lector de correo electrónico que la imagen que debe mostrarse está incrustada en el contenido mismo del mensaje con el identificador al que hace referencia.

El paso siguiente es crear nuestro IdMensaje que contendrá el código Html del mensaje:

        LIdmMensaje := TIdMessage.Create(Nil);
        LIdmMensaje.From.Name := EdtNomb.Text;
        LIdmMensaje.From.Address := EdtEmail.Text;
        with LIdmMensaje.Recipients.Add do
           begin
             Name := Edit2.Text;
             Address := Edit2.Text;
           end;
        LIdmMensaje.Subject := 'Prueba de envio de correo con imágenes';
        LIdmMensaje.Body.Text := LStlMensaje.Text;
        TIdText.Create(LIdmMensaje.MessageParts, LStlMensaje);
        with TIdText.Create(LIdmMensaje.MessageParts) do
          begin
            ContentType := 'text/html';
            ContentTransfer := '7bit';
            Body := TStringList.Create;
            Body.Text := LStlMensaje.Text;
          End;

Como podemos ver en el último bloque, se ha establecido que el contenido es de tipo ‘text/html’, esto permite al lector de correo interpretar el mensaje como si de una página web se tratara.  Después como siguiente paso vamos a crear nuestra instancia de clase TidAttachment para la carga del archivo:

       LIdmGraf := TIdAttachment.Create(LIdmMensaje.MessageParts,EdtImagen.Text);
       LIdmGraf.ContentType := 'image/jpg';
       LIdmGraf.ContentID   := LsGIdImage;

La propiedad ContentID de la clase TIdAttachment es la que permite ligar nuestra uimagen con el identificador generado previamente y a su vez permitirá referenciarla dentro del código html del mensaje.

Por último se hace el envio del mensaje de correo a través del método EnviaCorreo:

Function TForm1.EnviaCorreo(PIdmMensaje: TIdMessage): String;
  Var
    LIdsMtpMensaje : TIdSMTP;
begin
  Result := 'Nada';
  Try
    LIdsMtpMensaje := TIdSMTP.Create(Nil);
    LIdsMtpMensaje.Host := EdtSmtp.Text;
    LIdsMtpMensaje.Password := EdtPass.Text;
    LIdsMtpMensaje.Connect;
    LIdsMtpMensaje.Send(PIdmMensaje);
    LIdsMtpMensaje.Disconnect;
    LIdsMtpMensaje.Free;
  Except
    on Err : Exception do
       Result := 'Ocurrió un problema al enviar el mensaje. Error "' + Err.Message + '"';
  End;
end;

Que como podemos ver hace uso del componente TIdSMTP.  Todo muy sencillo como pueden ver.

Si desean descargar el código fuente del programa, podrán encontrarlo en la sección de descargas del Foro DelphiAccess: http://www.delphiaccess.com/forum/downloads/?sa=view;down=22

Cualquier comentario será apreciado. Para dudas, pueden preguntar en el foro donde yo y otros compañeros entusiastas las responderemos con mucho gusto.

2 Comments

1 Trackback / Pingback

  1. La clase TIdMessageBuilderHtml y el envío de correos HTML desde Delphi | El blog de jachguate

Deja un comentario