incrustación de imagen en correo electrónico html

113

Estoy intentando enviar un correo electrónico html de varias partes / relacionado con imágenes gif incrustadas. Este correo electrónico se genera utilizando Oracle PL / SQL. Mis intentos han fallado, y la imagen aparece como una X roja (en Outlook 2007 y Yahoo Mail)

He estado enviando correos electrónicos html durante algún tiempo, pero mis requisitos ahora son usar varias imágenes gif en el correo electrónico. Puedo almacenarlos en uno de nuestros servidores web y simplemente vincularlos, pero muchos clientes de correo electrónico de los usuarios no los mostrarán automáticamente y necesitarán cambiar la configuración o descargarlos manualmente para cada correo electrónico.

Entonces, mis pensamientos son incrustar la imagen. Mis preguntas son:

  1. ¿Qué estoy haciendo mal aquí?
  2. ¿El enfoque de integración es el correcto?
  3. ¿Alguna otra opción si necesito usar más y más imágenes? Los archivos adjuntos no funcionarán, ya que las imágenes suelen ser logotipos e iconos que no tendrán sentido fuera del contexto del mensaje. Además, algunos elementos del correo electrónico son enlaces a un sistema en línea, por lo que generar un PDF estático y adjuntarlo no funcionará (que yo sepa).

retazo:

MIME-Version: 1.0
To: me@gmail.com
BCC: me@yahoo.com
From: email@yahoo.com
Subject: Test
Reply-To: email@yahoo.com
Content-Type: multipart/related; boundary="a1b2c3d4e3f2g1"

--a1b2c3d4e3f2g1

content-type: text/html;

    <html>
    <head><title>My title</title></head>
    <body>
    <div style="font-size:11pt;font-family:Calibri;">
    <p><IMG SRC="cid:my_logo" alt="Logo"></p>

... more html here ...

</div></body></html> 

--a1b2c3d4e3f2g1

Content-Type: image/gif;
Content-ID:<my_logo>
Content-Transfer-Encoding: base64
Content-Disposition: inline

[base64 image data here]

--a1b2c3d4e3f2g1--

Muchas gracias.

Por cierto: Sí, he verificado que los datos base64 son correctos, ya que puedo incrustar la imagen en el propio html (usando el mismo uso de algoritmo para crear datos de encabezado) y ver la imagen en Firefox / IE.

También debo tener en cuenta que esto NO es para spam, los correos electrónicos se envían a clientes específicos que lo esperan a diario. El contenido se basa en datos y no en anuncios.

tbone
fuente
Pregunta rápida: ¿aloja estas imágenes fuera del sitio o las inserta directamente en el correo electrónico?
JonLim
En realidad, parte de mi pregunta, puedo hacer ambas cosas. Intento insertarlos aquí, pero no con éxito. Si solo los vinculo, muchos usuarios no verán las imágenes sin descargarlas primero, lo que me gustaría evitar.
tbone
1
Un habitual <img src="URL" />me funcionó, pero era una imagen que alojé fuera del sitio. ¿Eso no funciona para ti?
JonLim
"funciona" es subjetivo ... sí, funciona si el usuario está dispuesto a descargar las imágenes cada vez, pero me gustaría evitar eso e incrustar la imagen.
tbone
1
@JonLim: gracias por investigarlo, vea mis comentarios en la respuesta de lo que me faltaba.
tbone

Respuestas:

139

Intente insertarlo directamente, de esta manera puede insertar varias imágenes en varias ubicaciones en el correo electrónico.

<img src="data:image/jpg;base64,{{base64-data-string here}}" />

Y para que esta publicación sea útil para que otros: Si no tiene una cadena de datos base64, cree una fácilmente en: http://www.motobit.com/util/base64-decoder-encoder.asp desde un archivo de imagen .

El código fuente del correo electrónico se parece a esto, pero realmente no puedo decirte para qué sirve ese límite:

 To: email@email.de
 Subject: ...
 Content-Type: multipart/related;
 boundary="------------090303020209010600070908"

This is a multi-part message in MIME format.
--------------090303020209010600070908
Content-Type: text/html; charset=ISO-8859-15
Content-Transfer-Encoding: 7bit

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>

    <meta http-equiv="content-type" content="text/html; charset=ISO-8859-15">
  </head>
  <body bgcolor="#ffffff" text="#000000">
    <img src="cid:part1.06090408.01060107" alt="">
  </body>
</html>

--------------090303020209010600070908
Content-Type: image/png;
 name="moz-screenshot.png"
Content-Transfer-Encoding: base64
Content-ID: <part1.06090408.01060107>
Content-Disposition: inline;
 filename="moz-screenshot.png"

[base64 image data here]

--------------090303020209010600070908--

// EDITAR: Oh, me acabo de dar cuenta de que si inserta el primer fragmento de código de mi publicación para escribir un correo electrónico con thunderbird, thunderbird cambia automáticamente el código html para que se parezca más o menos al segundo código de mi publicación.

Bernd
fuente
5
Probé esto primero, no me funciona para el correo electrónico. funciona bien para ver en IE / Firefox, pero no se envía como correo electrónico.
tbone
Quizás conozca una manera (¿cuál sería el tipo de contenido? Texto / html? Los encabezados de correo electrónico que necesitaría saber para enviar un archivo html / imagen mixto de esta manera)
tbone
1
@Zesty usa @ [nombre de usuario] para alertar a alguien, acabo de ver tu pregunta. Yo uso utl_smtp. Para mí, tuve que crear build un clob con el cuerpo html, límites, etc. y luego enviarlo a través de utl_smtp. Vea aquí un ejemplo simple: oracle-base.com/articles/misc/EmailFromOraclePLSQL.php Tenga en cuenta que este enlace no muestra el enfoque de imágenes incrustadas, pero tiene detalles para que pueda comenzar.
tbone
41
Los URI de datos en los correos electrónicos no son compatibles con muchos clientes convencionales y no deben usarse, consulte: campaignmonitor.com/blog/post/3927/…
Michael Böckling
2
No parece funcionar en hotmail / icloud = (me
perdí
22

La otra solución es adjuntar la imagen como archivo adjunto y luego hacer referencia al código html usando cid.

Código HTML:

<html>
    <head>
    </head>
    <body>
        <img width=100 height=100 id="1" src="cid:Logo.jpg">
    </body>
</html>

Código C #:

EmailMessage email = new EmailMessage(service);
email.Subject = "Email with Image";
email.Body = new MessageBody(BodyType.HTML, html);
email.ToRecipients.Add("[email protected]");
string file = @"C:\Users\acv\Pictures\Logo.jpg";
email.Attachments.AddFileAttachment("Logo.jpg", file);
email.Attachments[0].IsInline = true;
email.Attachments[0].ContentId = "Logo.jpg";
email.SendAndSaveCopy();
Khyati Elhance
fuente
11

No encuentro ninguna de las respuestas aquí útiles, por lo que estoy proporcionando mi solución.

  1. El problema es que está utilizando multipart/relatedcomo tipo de contenido, lo que no es bueno en este caso. Lo estoy usando multipart/mixedy dentro multipart/alternative(funciona en la mayoría de los clientes).

  2. La estructura del mensaje debe ser la siguiente:

    [Headers]
    Content-type:multipart/mixed; boundary="boundary1"
    --boundary1
    Content-type:multipart/alternative; boundary="boundary2"
    --boundary2
    Content-Type: text/html; charset=ISO-8859-15
    Content-Transfer-Encoding: 7bit
    [HTML code with a href="cid:..."]
    
    --boundary2
    Content-Type: image/png;
    name="moz-screenshot.png"
    Content-Transfer-Encoding: base64
    Content-ID: <part1.06090408.01060107>
    Content-Disposition: inline; filename="moz-screenshot.png"
    [base64 image data here]
    
    --boundary2--
    --boundary1--

Entonces funcionará

Pavel Perna
fuente
Luchando en este. He codificado exactamente como se indica arriba, pero la imagen no aparece (solo un marco con el texto alternativo; el texto funciona bien). Mi Content-ID es <filename.jpg> entonces my href = "cid: filename.jpg" - ¿Existe algún truco especial para el valor o la sintaxis de Content-ID y cid:?
Peter Flynn
Verifiqué con RFC2392 y la expresión CID parece ser válida. Pero todavía no se muestra.
Peter Flynn
Escribí una respuesta a una pregunta similar y creé un arte ascii para explicar la estructura: stackoverflow.com/a/40420648/633961
guettli
4

Usar Base64 para incrustar imágenes en html es increíble. No obstante, tenga en cuenta que las cadenas base64 pueden aumentar el tamaño de su correo electrónico.

Por lo tanto,

1) Si tiene muchas imágenes, cargar sus imágenes en un servidor y cargar esas imágenes desde el servidor puede reducir el tamaño de su correo electrónico. (Puede obtener muchos servicios gratuitos a través de Google)

2) Si hay solo unas pocas imágenes en su correo, usar cadenas base64 es definitivamente una opción increíble.

Además de las opciones proporcionadas por las respuestas existentes, también puede usar un comando para generar una cadena base64 en linux:

base64 test.jpg
Brian
fuente
Señalado por Michael Böckling: los URI de datos en los correos electrónicos no son compatibles con muchos clientes convencionales como gmail
Mendy
3

Sé que esta es una publicación antigua, pero las respuestas actuales no abordan el hecho de que Outlook y muchos otros proveedores de correo electrónico no admiten imágenes en línea o imágenes CID. La forma más eficaz de colocar imágenes en correos electrónicos es alojarlas en línea y colocar un enlace a ellas en el correo electrónico. Para listas de correo electrónico pequeñas, un buzón público funciona bien. Esto también reduce el tamaño del correo electrónico.

Scooter Crawford
fuente
2
  1. Necesita 3 límites para que las imágenes en línea sean totalmente compatibles.

  2. Todo va dentro del multipart/mixed.

  3. Luego use el multipart/relatedpara contener sus multipart/alternativeencabezados de archivos adjuntos de imagen y los suyos.

  4. Por último, incluya sus archivos adjuntos descargables dentro del último límite de multipart/mixed.

Steven Newman
fuente
11
Sería útil si incluyera un ejemplo.
Makyen
7
Aún más útil sería una referencia a la especificación.
jbruni
2

De hecho, hay una publicación de blog muy buena que enumera los pros y los contras de tres enfoques diferentes de este problema por Martyn Davies. Puede leerlo en https://sendgrid.com/blog/embedding-images-emails-facts/ .

Me gustaría agregar un cuarto enfoque usando imágenes de fondo CSS.

Añadir

<div id="myImage"></div>

a su cuerpo de correo electrónico y una clase css como:

#myImage {
    background-image:  url('data:image/png;base64,iVBOR...[some more encoding]...rkggg==');
    width: [the-actual-image-width];
    height: [the-actual-image-height];
}
GerardV
fuente
2

Para aquellos que no pudieron hacer que una de estas soluciones funcionara: Enviar imagen en línea por correo electrónico Siguiendo los pasos establecidos en la solución ofrecida por @ T30, pude hacer que mi imagen en línea se mostrara sin ser bloqueada por Outlook (métodos anteriores estaba bloqueado) . Si está utilizando Exchange como nosotros, entonces también cuando haga:

service = new ExchangeService(ExchangeVersion);
service.AutodiscoverUrl("[email protected]");
SmtpClient smtp = new SmtpClient(service.Url.Host);

Deberá pasarle el host de la URL del servicio de intercambio. Aparte de eso, esta solución debería permitirle enviar imágenes incrustadas fácilmente.

tstrand66
fuente
1

Puede ser de interés que tanto Outlook como Outlook Express puedan generar estos formatos de correo electrónico de imágenes de varias partes, si inserta los archivos de imagen utilizando la función de menú Insertar / Imagen.

Obviamente, el tipo de correo electrónico debe establecerse en HTML (no en texto sin formato).

Cualquier otro método (por ejemplo, arrastrar / soltar, o cualquier invocación de la línea de comandos) hace que las imágenes se envíen como un archivo adjunto.

Si luego te envías ese correo electrónico a ti mismo, ¡podrás ver cómo está formateado! :)

FWIW, estoy buscando un ejecutable de Windows independiente que haga imágenes en línea desde el modo de línea de comandos, pero parece que no hay ninguno. Es una ruta que muchos han subido ... Uno puede hacerlo con, por ejemplo, Outlook Express, pasándole un archivo .eml con el formato adecuado.

Pedro
fuente
0

El siguiente es un código de trabajo con dos formas de lograrlo:

using System;
using Outlook = Microsoft.Office.Interop.Outlook;

namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {

            Method1();
            Method2();
        }

        public static void Method1()
        {
            Outlook.Application outlookApp = new Outlook.Application();
            Outlook.MailItem mailItem = outlookApp.CreateItem(Outlook.OlItemType.olMailItem);
            mailItem.Subject = "This is the subject";
            mailItem.To = "[email protected]";
            string imageSrc = "D:\\Temp\\test.jpg"; // Change path as needed

            var attachments = mailItem.Attachments;
            var attachment = attachments.Add(imageSrc);
            attachment.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x370E001F", "image/jpeg");
            attachment.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x3712001F", "myident"); // Image identifier found in the HTML code right after cid. Can be anything.
            mailItem.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/id/{00062008-0000-0000-C000-000000000046}/8514000B", true);

            // Set body format to HTML

            mailItem.BodyFormat = Outlook.OlBodyFormat.olFormatHTML;
            string msgHTMLBody = "<html><head></head><body>Hello,<br><br>This is a working example of embedding an image unsing C#:<br><br><img align=\"baseline\" border=\"1\" hspace=\"0\" src=\"cid:myident\" width=\"\" 600=\"\" hold=\" /> \"></img><br><br>Regards,<br>Tarik Hoshan</body></html>";
            mailItem.HTMLBody = msgHTMLBody;
            mailItem.Send();
        }

        public static void Method2()
        {

            // Create the Outlook application.
            Outlook.Application outlookApp = new Outlook.Application();

            Outlook.MailItem mailItem = (Outlook.MailItem)outlookApp.CreateItem(Outlook.OlItemType.olMailItem);

            //Add an attachment.
            String attachmentDisplayName = "MyAttachment";

            // Attach the file to be embedded
            string imageSrc = "D:\\Temp\\test.jpg"; // Change path as needed

            Outlook.Attachment oAttach = mailItem.Attachments.Add(imageSrc, Outlook.OlAttachmentType.olByValue, null, attachmentDisplayName);

            mailItem.Subject = "Sending an embedded image";

            string imageContentid = "someimage.jpg"; // Content ID can be anything. It is referenced in the HTML body

            oAttach.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x3712001E", imageContentid);

            mailItem.HTMLBody = String.Format(
                "<body>Hello,<br><br>This is an example of an embedded image:<br><br><img src=\"cid:{0}\"><br><br>Regards,<br>Tarik</body>",
                imageContentid);

            // Add recipient
            Outlook.Recipient recipient = mailItem.Recipients.Add("[email protected]");
            recipient.Resolve();

            // Send.
            mailItem.Send();
        }
    }
}
Tarik
fuente
0

Una pista adicional a la publicación de Pavel Perna que me ayudó mucho (no puedo comentar sobre mi reputación, es por eso que publico esto como respuesta): En algunas versiones de Microsoft Exchange, se elimina la disposición del contenido en línea ( consulte esta publicación de Microsoft ). La imagen simplemente no forma parte del correo que el usuario ve en Outlook. Como solución alternativa, utilice "Content-Disposition: Attachement" en su lugar. Outlook 2016 no mostrará las imágenes como archivos adjuntos que se utilizan en el mensaje de correo, aunque utilizan el "Contenido-Disposición: archivo adjunto".

Klendatho
fuente
-30

Si utiliza Outlook para enviar una imagen estática con hipervínculo, una forma sencilla sería utilizar Word.

  1. Abrir MS Word
  2. Copie la imagen en una página en blanco
  3. Agregar hipervínculo a la imagen (Ctrl + K)
  4. Copia la imagen a tu correo electrónico
Claudio Viz
fuente