在HTML电子邮件中嵌入图片

170

我正在尝试发送一封包含嵌入式gif图像的multipart/related HTML电子邮件,这封邮件是使用Oracle PL/SQL生成的。我的尝试失败了,在Outlook 2007和Yahoo邮件中,图片显示为红色X。

我已经发送HTML电子邮件有一段时间了,但现在我的要求是在邮件中使用多个gif图像。 我可以将这些图像存储在我们的Web服务器上并进行链接,但许多用户的电子邮件客户端不会自动显示它们,并且需要更改设置或手动下载每个电子邮件中的图像。

所以,我的想法是嵌入图像。我的问题是:

  1. 我在这里做错了什么?
  2. 嵌入式方法是否正确?
  3. 如果我需要使用更多图像,还有其他选项吗?附件行不通,因为这些图像通常是徽标和图标,如果不放在邮件正文中就没有意义。另外,邮件的某些元素是指向在线系统的链接,因此生成静态PDF并附加也不起作用(至少我不知道如何实现)。

片段:

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

非常感谢。

顺便说一句:是的,我已经验证了base64数据是正确的,因为我可以使用创建标题数据时使用的相同算法将图像嵌入html本身中,并在Firefox/IE中看到图像。

我还应该指出,这不是用于垃圾邮件,这些电子邮件发送给特定的客户,他们每天都在期待它。内容是数据驱动的,而不是广告。


快速问题:您是将这些图像托管在外部网站上还是直接嵌入电子邮件中? - JonLim
我的问题的一部分,我两者都可以做到。我在这里尝试嵌入它们,但没有成功。如果我只链接它们,许多用户在不先下载它们的情况下看不到图片,我想避免这种情况。 - tbone
1
一个常规的 <img src="URL" /> 对我而言可行,但它是由我托管在外部的图片。这对你不起作用吗? - JonLim
"工作"是主观的...是的,如果用户愿意每次下载图像,它可以工作,但我希望避免这样做并嵌入图像。 - tbone
1
@JonLim:感谢您关注此事,查看我的回答中我所遗漏的内容。 - tbone
显示剩余3条评论
14个回答

178

尝试直接插入它,这样你就可以在电子邮件的不同位置插入多个图像。

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

为了让这篇帖子对其他人有用:

如果您没有base64数据字符串,请在此网站http://www.motobit.com/util/base64-decoder-encoder.asp上从图像文件中轻松创建一个。

电子邮件源代码类似于下面的内容,但我真的无法告诉您那个边界是什么意思:

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

//编辑:哦,我刚刚意识到,如果您将我帖子中的第一个代码片段插入到Thunderbird中编写电子邮件,Thunderbird会自动将HTML代码更改为与我帖子中的第二个代码几乎相同。


5
我尝试了这个方法,但在发送电子邮件时无效。在IE / Firefox中查看时效果很好,但发送邮件时不行。 - tbone
谢谢您发布标题!它有效!我相信在图像部分我漏掉了“name=”和“filename=”部分。另外,我改用png而不是gif。 - tbone
1
@Zesty 使用@[用户名]来提醒某人,刚看到你的问题。我使用utl_smtp。对我来说,我必须创建一个包含HTML正文、边界等的clob,然后通过utl_smtp发送。在这里查看简单示例:http://www.oracle-base.com/articles/misc/EmailFromOraclePLSQL.php 请注意,此链接不显示嵌入式图像方法,但有详细信息可供参考。 - tbone
67
电子邮件中的数据 URI 在许多主流客户端中不受支持,不应使用。请参见:https://www.campaignmonitor.com/blog/post/3927/embedded-images-in-html-email - Michael Böckling
2
似乎在hotmail/icloud上无法工作 =( 我有什么遗漏吗? - hsb1007
显示剩余6条评论

41
另一种解决方案是将图像作为附件附加,然后使用cid在html代码中引用它。
HTML代码:
<html>
    <head>
    </head>
    <body>
        <img width=100 height=100 id="1" src="cid:Logo.jpg">
    </body>
</html>

C# 代码:

EmailMessage email = new EmailMessage(service);
email.Subject = "Email with Image";
email.Body = new MessageBody(BodyType.HTML, html);
email.ToRecipients.Add("abc@xyz.com");
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();

1
谢谢提供的解决方案。在我的情况下,附加图像并在 HTML 代码中引用它是有效的。 - jpr

16

我没有发现这里任何答案有用,所以我提供我的解决方案。

  1. 问题在于您正在使用不适合此情况的multipart/related作为内容类型。我使用multipart/mixed并在其中使用multipart/alternative(在大多数客户端上都有效)。

  2. 消息结构应如下:

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

那么它就会起作用。


这个有点棘手。我已经按照上面的代码编写了,但是图片没有出现(只有一个带有alt文本的框架;文本正常工作)。我的Content-ID是<filename.jpg>,所以我的href="cid:filename.jpg"——Content-ID和cid:的值或语法是否有特殊技巧? - Peter Flynn
我查阅了RFC2392,CID表达式似乎是有效的。但它仍然无法显示。 - Peter Flynn
1
我曾回答过一个类似的问题,并创建了一幅ASCII艺术图来解释结构:https://dev59.com/-Zzha4cB1Zd3GeqPAymI#40420648 - guettli
对我来说,情况正好相反。也就是说,从混合变成相关... - koalo

11

18
img2html 是我最近看到的最疯狂的解决方案/想法。+1 - Kristjan Liiva
1
“wacky”一词总结了img2html的这个特点:作为解决方案,我们编写了一个应用程序,将图像的每个像素转换为相应的HTML单元格。 - Red Pill

7

我知道这是一个旧帖子,但当前的答案没有解决Outlook和许多其他电子邮件提供商不支持内联图片或CID图片的事实。在电子邮件中放置图片的最有效方法是将其托管在线并在电子邮件中放置链接。对于小型电子邮件列表,公共Dropbox可以很好地运作。这也可以保持电子邮件大小。


5
使用Base64在html中嵌入图片非常棒。但请注意,Base64字符串可能会使您的电子邮件变得很大。
因此,
1)如果您有许多图片,将图片上传到服务器并从服务器加载这些图片可以使您的电子邮件大小更小。(您可以通过Google获得许多免费服务)
2)如果您的邮件中只有几张图片,则使用Base64字符串绝对是一个很棒的选择。
除了现有答案提供的选项外,您还可以在Linux上使用命令生成Base64字符串:
base64 test.jpg

1
由Michael Böckling指出:在电子邮件中使用的数据URI在许多主流客户端(如Gmail)中不受支持。 - Mendy

3

对于那些无法让这些解决方案起作用的人:

发送内联图像电子邮件

遵循@T30提供的解决方案中提供的步骤,我能够让我的内联图像显示,而不被Outlook阻止(之前的方法被阻止了)。如果您像我们一样使用Exchange,则还需要执行以下操作:

service = new ExchangeService(ExchangeVersion);
service.AutodiscoverUrl("email@domain.com");
SmtpClient smtp = new SmtpClient(service.Url.Host);

您需要将您的交换服务URL主机传递给它。除此之外,按照这个解决方案,您可以轻松地发送嵌入式图像。


2

实际上,Martyn Davies写了一篇非常好的博客文章,列出了解决此问题的三种不同方法的优缺点。您可以在https://sendgrid.com/blog/embedding-images-emails-facts/阅读。

我想添加第四种方法,使用CSS背景图像。

添加

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

将以下内容添加到您的电子邮件正文和一个类似于CSS的类:

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

2
值得注意的是,如果您使用“插入/图片”菜单功能插入图像文件,Outlook和Outlook Express都可以生成这些多部分图像电子邮件格式。显然,电子邮件类型必须设置为HTML(而不是纯文本)。任何其他方法(例如拖放或任何命令行调用)都会导致图像作为附件发送。如果您将此类电子邮件发送给自己,则可以查看其格式! :) 就我个人而言,我正在寻找一个独立的Windows可执行文件,它可以在命令行模式下进行内联图像,但似乎没有这样的工具。许多人已经尝试过这条路了…… 例如,可以通过向Outlook Express传递适当格式化的.eml文件来完成此操作。

2
  1. 您需要三个边界才能完全符合内联图片的要求。

  2. 所有内容都应放在 multipart/mixed 中。

  3. 然后使用 multipart/related 包含您的 multipart/alternative 和您的图像附件头。

  4. 最后,将可下载的附件包含在 multipart/mixed 的最后一个边界内。


17
如果您提供一个例子,那将会很有帮助。 - Makyen
9
更有用的是提供规范的参考。 - jbruni

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接