incorporação de imagem em e-mail html

113

Estou tentando enviar um e-mail multipart / html relacionado com imagens GIF incorporadas. Este e-mail é gerado usando Oracle PL / SQL. Minhas tentativas falharam, com a imagem aparecendo como um X vermelho (no Outlook 2007 e no yahoo mail)

Eu tenho enviado emails em html há algum tempo, mas meus requisitos agora são usar várias imagens GIF no email. Posso armazená-los em um de nossos servidores web e apenas criar um link para eles, mas muitos clientes de e-mail de usuários não os mostram automaticamente e precisarão alterar as configurações ou baixá-los manualmente para cada e-mail.

Então, meu pensamento é incorporar a imagem. Minhas perguntas são:

  1. O que eu estou fazendo errado aqui?
  2. A abordagem de incorporação é a correta?
  3. Alguma outra opção se eu precisar usar mais e mais imagens? Os anexos não funcionam, pois as imagens são normalmente logotipos e ícones que não farão sentido fora do contexto da mensagem. Além disso, alguns elementos do e-mail são links para um sistema online, portanto, gerar um PDF estático e anexá-lo não funcionará (pelo que eu sei).

snippet:

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

Muito Obrigado.

BTW: Sim, eu verifiquei que os dados base64 estão corretos, pois posso incorporar a imagem no próprio html (usando o mesmo uso de algoritmo para criar dados de cabeçalho) e ver a imagem no Firefox / IE.

Devo também notar que NÃO se trata de spam, os e-mails são enviados para clientes específicos que o esperam diariamente. O conteúdo é orientado por dados e não por anúncios.

tbone
fonte
Pergunta rápida: você está hospedando essas imagens fora do site ou incorporando-as diretamente no e-mail?
JonLim
Parte da minha pergunta realmente, eu posso fazer qualquer um. Estou tentando incorporá-los aqui, mas não com sucesso. Se eu apenas criar um link para eles, muitos usuários não verão as imagens sem fazer o download primeiro, o que gostaria de evitar.
tbone
1
Um regular <img src="URL" />funcionou para mim, mas era uma imagem que eu hospedava fora do local. Isso não funciona para você?
JonLim
"funciona" é subjetivo ... sim, funciona se o usuário estiver disposto a baixar as imagens todas as vezes, mas eu gostaria de evitar isso e incorporar a imagem.
tbone
1
@JonLim: obrigado por olhar, veja meus comentários na resposta sobre o que estava faltando.
tbone

Respostas:

139

Tente inseri-lo diretamente, desta forma você pode inserir várias imagens em vários locais no e-mail.

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

E para tornar esta postagem útil para outros: Se você não tem uma string de dados base64, crie uma facilmente em: http://www.motobit.com/util/base64-decoder-encoder.asp a partir de um arquivo de imagem .

O código-fonte do e-mail é parecido com isto, mas eu realmente não posso dizer para que serve esse limite:

 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: Ah, acabei de perceber que se você inserir o primeiro trecho de código da minha postagem para escrever um e-mail com o thunderbird, o thunderbird altera automaticamente o código html para se parecer muito com o segundo código da minha postagem.

Bernd
fonte
5
tentei isso primeiro, não funciona para mim por e-mail. funciona bem para visualização no IE / Firefox, mas não enviado por e-mail.
tbone
Talvez você conheça uma maneira (qual seria o tipo de conteúdo? Texto / html? Os cabeçalhos de e-mail que eu precisaria saber para enviar um arquivo html / imagem misturado dessa maneira)
tbone
1
@Zesty use @ [nome de usuário] para alertar alguém, acabei de ver sua pergunta. Eu uso utl_smtp. Para mim, tive que criar, construir um clob com o corpo html, limites, etc e enviar via utl_smtp. Veja aqui um exemplo simples: oracle-base.com/articles/misc/EmailFromOraclePLSQL.php Observe que este link não mostra a abordagem de imagens incorporadas, mas tem detalhes para você continuar.
tbone
41
URIs de dados em e-mails não são compatíveis com muitos clientes convencionais e não devem ser usados, consulte: campaignmonitor.com/blog/post/3927/…
Michael Böckling
2
Não parece funcionar no hotmail / icloud = (perdi alguma coisa
hsb1007
22

A outra solução é anexar a imagem como anexo e, em seguida, referenciá-la ao 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
fonte
11

Não acho nenhuma das respostas aqui úteis, então estou fornecendo minha solução.

  1. O problema é que você está usando multipart/relatedcomo tipo de conteúdo, o que não é bom neste caso. Estou usando multipart/mixede dentro dele multipart/alternative(funciona na maioria dos clientes).

  2. A estrutura da mensagem deve ser a seguinte:

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

Então vai funcionar

Pavel Perna
fonte
Lutando com este. Codifiquei exatamente como acima, mas a imagem não está aparecendo (apenas um quadro com o texto alternativo; o texto funciona bem). Meu Content-ID é <filename.jpg> então meu href = "cid: filename.jpg" - existe algum truque especial para o valor ou sintaxe de Content-ID e cid:?
Peter Flynn
Eu verifiquei com RFC2392 e a expressão CID parece ser válida. Mas ainda não é exibido.
Peter Flynn
Escrevi uma resposta a uma pergunta semelhante e criei uma arte ascii para explicar a estrutura: stackoverflow.com/a/40420648/633961
guettli
4

Usar Base64 para incorporar imagens em html é incrível. No entanto, observe que as strings de base64 podem aumentar o tamanho do seu e-mail.

Portanto,

1) Se você tiver muitas imagens, enviá-las a um servidor e carregá-las do servidor pode diminuir o tamanho do seu e-mail. (Você pode obter muitos serviços gratuitos por meio do Google)

2) Se houver apenas algumas imagens em seu e-mail, usar strings em base64 é definitivamente uma opção incrível.

Além das opções fornecidas pelas respostas existentes, você também pode usar um comando para gerar uma string base64 no linux:

base64 test.jpg
Brian
fonte
Indicado por Michael Böckling: URIs de dados em e-mails não são compatíveis com muitos clientes convencionais, como gmail
Mendy
3

Eu sei que esta é uma postagem antiga, mas as respostas atuais não abordam o fato de que o Outlook e muitos outros provedores de e-mail não suportam imagens embutidas ou imagens CID. A maneira mais eficaz de colocar imagens em emails é hospedá-los online e colocar um link para ele no email. Para pequenas listas de e-mail, uma caixa de depósito pública funciona bem. Isso também mantém o tamanho do e-mail baixo.

Scooter Crawford
fonte
2
  1. Você precisa de 3 limites para que as imagens embutidas sejam totalmente compatíveis.

  2. Tudo vai dentro do multipart/mixed.

  3. Em seguida, use multipart/relatedpara conter seus multipart/alternativecabeçalhos de anexo de imagem e seu.

  4. Por último, inclua seus anexos para download dentro do último limite de multipart/mixed.

Steven Newman
fonte
11
Seria útil incluir um exemplo.
Makyen
7
Ainda mais útil seria uma referência às especificações.
jbruni
2

Na verdade, há um post de blog muito bom que lista prós e contras de três abordagens diferentes para este problema por Martyn Davies. Você pode lê-lo em https://sendgrid.com/blog/embedding-images-emails-facts/ .

Eu gostaria de adicionar uma quarta abordagem usando imagens de fundo CSS.

Adicionar

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

ao corpo do seu e-mail e uma classe 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
fonte
2

Para aqueles que não conseguiram fazer com que uma dessas soluções funcionasse: Enviar imagem embutida por e-mail Seguindo os passos descritos na solução oferecida por @ T30, consegui fazer com que minha imagem embutida fosse exibida sem ser bloqueada pelo Outlook (métodos anteriores ela estava bloqueada) . Se você estiver usando o Exchange como nós, também fazemos:

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

você precisará transmiti-lo ao host de url do serviço de troca. Além de seguir esta solução deve permitir que você envie facilmente imagens incorporadas.

tstrand66
fonte
1

Pode ser interessante que tanto o Outlook quanto o Outlook Express possam gerar esses formatos de e-mail de imagem com várias partes, se você inserir os arquivos de imagem usando a função de menu Inserir / Imagem.

Obviamente, o tipo de e-mail deve ser definido como HTML (não texto simples).

Qualquer outro método (por exemplo, arrastar / soltar ou qualquer invocação de linha de comando) resulta no envio das imagens como um anexo.

Se você enviar esse e-mail para si mesmo, poderá ver como ele está formatado! :)

FWIW, estou procurando um executável autônomo do Windows que faz imagens embutidas no modo de linha de comando, mas parece não haver nenhum. É um caminho que muitos percorreram ... Pode-se fazer isso, digamos, com o Outlook Express, passando um arquivo .eml formatado apropriadamente.

Peter
fonte
0

A seguir está o código de trabalho com duas maneiras de conseguir isso:

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
fonte
0

Uma dica adicional ao post de Pavel Perna que me ajudou muito (não posso comentar sobre minha reputação, é por isso que posto como resposta): Em algumas versões do Microsoft Exchange, a disposição de conteúdo inline é removida ( veja este post da Microsoft ). A imagem simplesmente não faz parte do e-mail que o usuário vê no Outlook. Como alternativa, use "Content-Disposition: attachement". O Outlook 2016 não mostrará imagens como anexos que são usados ​​na mensagem de correio, embora usem o "Content-Disposition: attachement".

Klendatho
fonte
-31

Se você estiver usando o Outlook para enviar uma imagem estática com hiperlink, uma maneira fácil seria usar o Word.

  1. Abra o MS Word
  2. Copie a imagem em uma página em branco
  3. Adicionar hiperlink à imagem (Ctrl + K)
  4. Copie a imagem para o seu e-mail
Claudio Viz
fonte