在 html 电子邮件中嵌入图像
Posted
技术标签:
【中文标题】在 html 电子邮件中嵌入图像【英文标题】:embedding image in html email 【发布时间】:2011-10-06 02:52:32 【问题描述】:我正在尝试发送包含嵌入式 gif 图像的多部分/相关 html 电子邮件。此电子邮件是使用 Oracle PL/SQL 生成的。我的尝试失败了,图像显示为红色 X(在 Outlook 2007 和 yahoo 邮件中)
我一直在发送 html 电子邮件,但我现在的要求是在电子邮件中使用几个 gif 图像。我可以将这些存储在我们的一个网络服务器上并链接到它们,但是许多用户的电子邮件客户端不会自动显示它们,并且需要更改设置或为每封电子邮件手动下载它们。
所以,我的想法是嵌入图像。我的问题是:
-
我在这里做错了什么?
嵌入方法是否正确?
如果我需要使用越来越多的图像,还有其他选择吗?附件不起作用,因为图像通常是徽标和图标,在消息的上下文中没有意义。此外,电子邮件的某些元素是在线系统的链接,因此无法生成静态 PDF 并附加附件(据我所知)。
sn-p:
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" ></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 中查看图像。
我还应该注意,这不是垃圾邮件,电子邮件会发送给每天都在期待它的特定客户。内容是数据驱动的,而不是广告。
【问题讨论】:
快速提问:您是在异地托管这些图像还是将它们直接嵌入到电子邮件中? 我的问题的一部分,我也可以。我在这里尝试嵌入它们,但没有成功。如果我只是链接到它们,许多用户不先下载它们就看不到图像,我想避免这种情况。 普通的<img src="URL" />
为我工作,但这是我在场外托管的图像。这对你不起作用?
"works" 是主观的......是的,如果用户愿意每次都下载图像,它会起作用,但我想避免这种情况并嵌入图像。
@JonLim:感谢您的调查,请在答案中查看我的 cmets,了解我所缺少的内容。
【参考方案1】:
尝试直接插入,这样可以在邮件的不同位置插入多张图片。
<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" >
</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--
//编辑:哦,我刚刚意识到,如果您从我的帖子中插入第一个代码 sn-p 来用 Thunderbird 写一封电子邮件,Thunderbird 会自动更改 html 代码,使其看起来与我帖子中的第二个代码几乎相同.
【讨论】:
首先尝试了这个,它不适用于我的电子邮件。可以在 IE/Firefox 中查看,但不能作为电子邮件发送。 也许你知道一种方法(内容类型是什么?文本/html?我需要知道的电子邮件标题才能以这种方式发送混合的 html/图像文件) @Zesty 使用 @[username] 提醒某人,刚刚看到你的问题。我使用utl_smtp。对我来说,我必须使用 html 正文、边界等创建构建一个 clob,然后通过 utl_smtp 发送。有关简单示例,请参见此处:oracle-base.com/articles/misc/EmailFromOraclePLSQL.php 请注意,此链接不显示嵌入图像的方法,但有详细信息可以帮助您进行操作。 许多主流客户端不支持电子邮件中的数据URI,不应使用,请参阅:campaignmonitor.com/blog/post/3927/… 它在 hotmail / icloud 中似乎不起作用 =( 我错过了什么【参考方案2】:另一种解决方案是将图像作为附件附加,然后使用 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();
【讨论】:
感谢您的解决方案。在我的情况下,附加图像然后在 html 代码中引用它。【参考方案3】:我觉得这里的任何答案都没有用,所以我提供了我的解决方案。
问题是您使用multipart/related
作为内容类型,这在这种情况下不好。我正在使用multipart/mixed
并在其中使用multipart/alternative
(它适用于大多数客户端)。
消息结构应该如下:
[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 是如果它不起作用,您可以尝试将图像转换为 HTML 表格的以下工具之一(但请注意图像的大小):
http://stylecampaign.com/blog/2009/12/bypass-image-blocking-by-converting-images-to-html/ http://neil.fraser.name/software/img2html/【讨论】:
img2hmtl 是我一段时间以来见过的最古怪的解决方案/想法。 +1【参考方案5】:使用 Base64 在 html 中嵌入图像非常棒。尽管如此,请注意 base64 字符串会使您的电子邮件变大。
因此,
1) 如果您有很多图像,将图像上传到服务器并从服务器加载这些图像可以使您的电子邮件更小。 (您可以通过 Google 获得很多免费服务)
2) 如果您的邮件中只有几张图片,那么使用 base64 字符串绝对是一个不错的选择。
除了现有答案提供的选择之外,您还可以在linux上使用命令生成base64字符串:
base64 test.jpg
【讨论】:
Michael Böckling 指出:电子邮件中的数据 URI 在 gmail 等许多主流客户端中不受支持【参考方案6】:我知道这是一篇旧帖子,但当前的答案并未解决 Outlook 和许多其他电子邮件提供商不支持内联图像或 CID 图像的事实。在电子邮件中放置图像的最有效方法是将其在线托管并在电子邮件中放置指向它的链接。对于小型电子邮件列表,公共保管箱可以正常工作。这也减少了电子邮件的大小。
【讨论】:
【参考方案7】:内嵌图像需要 3 个边界才能完全合规。
一切都在multipart/mixed
中。
然后使用multipart/related
包含您的multipart/alternative
和您的图片附件标题。
最后,将可下载的附件包含在multipart/mixed
的最后一个边界内。
【讨论】:
如果你能提供一个例子会很有帮助。 更有用的是参考规范。【参考方案8】:对于那些无法使这些解决方案之一发挥作用的人: Send inline image in email 按照@T30 提供的解决方案中列出的步骤,我能够显示我的内联图像而不会被 Outlook 阻止(以前的方法被阻止)。如果您像我们一样使用交换,那么在这样做时:
service = new ExchangeService(ExchangeVersion);
service.AutodiscoverUrl("email@domain.com");
SmtpClient smtp = new SmtpClient(service.Url.Host);
您需要将您的交换服务 url 主机传递给它。除了遵循此解决方案之外,您还可以轻松发送嵌入式图像。
【讨论】:
【参考方案9】:如果您使用“插入/图片”菜单功能插入图像文件,Outlook 和 Outlook Express 都可以生成这些多部分图像电子邮件格式,这可能会很有趣。
显然电子邮件类型必须设置为 HTML(不是纯文本)。
任何其他方法(例如拖放或任何命令行调用)都会导致图像作为附件发送。
如果您随后将此类电子邮件发送给自己,您可以看到它的格式! :)
FWIW,我正在寻找一个独立的 Windows 可执行文件,它从命令行模式执行内联图像,但似乎没有。这是一条许多人都走上过的道路...可以通过将一个适当格式的 .eml 文件传递给 Outlook Express 来做到这一点。
【讨论】:
【参考方案10】:实际上,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];
【讨论】:
【参考方案11】:以下是实现此目的的两种方法的工作代码:
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 = "john@example.com";
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("john@example.com");
recipient.Resolve();
// Send.
mailItem.Send();
【讨论】:
【参考方案12】:Pavel Perna 的帖子的另一个提示对我很有帮助(无法评论我的声誉,这就是我将其发布为答案的原因):在 Microsoft Exchange 的某些版本中,内联内容处置已被删除 (see this post by Microsoft)。该图像根本不是用户在 Outlook 中看到的邮件的一部分。作为一种解决方法,请改用“Content-Disposition: attachement”。 Outlook 2016 不会将图像显示为邮件中使用的附件,尽管它们使用“内容处置:附件”。
【讨论】:
【参考方案13】:尝试使用 Context.Request 解决这个问题:
<img src="@($"Context.Request.Scheme://Context.Request.HostContext.Request.PathBase/images/logo.png")" />
在我的情况下,当我使用 Content-ID 时,我也将该图像作为附件,这不是最佳解决方案。
【讨论】:
你能分享一个工作的例子吗? context.request 代表什么?以上是关于在 html 电子邮件中嵌入图像的主要内容,如果未能解决你的问题,请参考以下文章
在 html 中嵌入图像以自动发送 Outlook365 电子邮件