MIME multiparte no e-mail

Sep 25 2020

Estou tentando incorporar imagens em um e-mail.

O e-mail é criado enviando dados por meio de um soquete para um servidor SMTP na porta 25. Este é o bit MIME:

MIME-Version: 1.0
Content-Type: multipart/mixed; boundary=mixedsection;

--mixedsection
Content-Type: text/plain;
Content-Transfer-Encoding: 8bit
Content-Disposition: inline

Below should be an inline embedded image

--mixedsection
Content-Type: image/png; file=ts-charts.png
Content-Transfer-Encoding: base64
Content-Disposition: inline; filename=ts-charts.png

iVBORw0KGgoAAAANSUhEUgAAAnoAAAHqCAMAAACk+hPgAAABpFBMVEX// (etc etc etc)

--mixedsection--

Quando o e-mail é recebido, parece que a segunda seção, a imagem, é convertida em um anexo e nunca exibida inline. Todas as outras partes funcionam bem, a imagem está codificada corretamente como base64 para que o anexo possa ser aberto. O texto / parte simples funciona corretamente quando o Content-Disposition está definido como embutido ou anexo.

Eu usei outros clientes de e-mail (outlook, thunderbird) para incorporar a imagem, e nenhum problema com a imagem sendo exibida inline.

Não consigo nem fazer com que a imagem seja exibida embutida, mesmo se eu remover todo o resto. O seguinte ainda é recebido como um anexo:

MIME-Version: 1.0
Content-Type: image/png; file=ts-charts.png
Content-Transfer-Encoding: base64
Content-Disposition: inline; filename=ts-charts.png

iVBORw0KGgoAAAANSUhEUgAAAnoAAAHqCAMAAAC (etc etc)

Portanto, a questão é: o que estou perdendo aqui e como faço para que a imagem seja exibida embutida?

Respostas

1 Mark Sep 25 2020 at 20:04

Por alguma razão, eu simplesmente não conseguia fazê-lo funcionar de uma forma simples, direto do modo padrão RFC; se alguém souber como fazer assim, por favor poste.

Então, desisti e usei HTML / CID embutido para incorporar a imagem.

Veja como eu fiz:

MIME-Version: 1.0
Content-Type: multipart/mixed; boundary=mixedsection;

--mixedsection
Content-Type: multipart/related; boundary=relatedsection;

--relatedsection
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: 8Bit
Content-Disposition: inline

<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
  </head>
  <body>
    <p><img src="cid:myembeddedimage" alt=""></p>
  </body>
</html>

--relatedsection
Content-Type: image/png; name=ts-charts.png
Content-ID: myembeddedimage
Content-Transfer-Encoding: base64
Content-Disposition: inline; filename=ts-charts.png

iVBORw0KGgoAAAANSUhEUgAAAnoAAAHqCAMAAACk+hPgAAABpFBMVEX//3 (etc etc)

--relatedsection--
--mixedsection--

Observe que também mudei:

Content-Type: image/png; file=ts-charts.png

removendo a propriedade do arquivo e substituindo por uma propriedade de nome:

Content-Type: image/png; name=ts-charts.png

Não estou muito confiante de que essa seja uma maneira boa ou recomendada de fazer isso, mas funciona.

EDITAR: .... Só para terminar. Eu não consegui por nada descobrir como misturar texto simples e imagens HTML incorporadas, então optei por simplesmente colocar o texto em HTML.

Aqui está a mensagem final:

MIME-Version: 1.0
Content-Type: multipart/related; boundary=relatedsection;

--relatedsection
Content-Type: text/html;
Content-Transfer-Encoding: 8bit
Content-Disposition: inline

<html>
   <head>
      <meta http-equiv="content-type" content="text/html;">
   </head>
   <body>
      <p> Below is an embedded image ...</p>
      <p><img src="cid:myembeddedimage" alt=""></p>
   </body>
</html>

--relatedsection
Content-Type: image/png; name=ts-charts.png
Content-ID: myembeddedimage
Content-Transfer-Encoding: base64
Content-Disposition: inline; filename=ts-charts.png
 
AHqCAMAAACk+hPgAAABpFBMVEX///8PDw8jIyPDw8OPj333mOm2ajzGtEbdPpm (etc (etc)
--relatedsection--

Tive de remover o multipart / mixed externo, pois a execução desta mensagem por meio de um servidor Exchange resultou em anexos (att0001, att0002) à mensagem. Nenhum problema com esses anexos fantasmas no thunderbird, gmail ou o que quer que o cliente seja chamado nos i-Phones.