将图像嵌入html电子邮件中


113

我正在尝试发送包含嵌入式gif图像的多部分/相关html电子邮件。该电子邮件是使用Oracle PL / SQL生成的。我的尝试失败了,图片显示为红色X(在Outlook 2007和yahoo邮件中)

我已经发送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 2011年

我的部分问题确实可以解决。我在这里尝试将其嵌入,但未成功。如果我仅链接到它们,则很多用户必须先下载图像,否则不先下载图像。
tbone

1
一位常客<img src="URL" />为我工作,但这是我在异地托管的图像。那对你不起作用吗?
JonLim 2011年

“作品”是主观的……是的,如果用户每次都愿意下载图像,那么它是可行的,但是我想避免这种情况并嵌入图像。
tbone 2011年

1
@JonLim:感谢您对它的研究,请在答案中查看我的评论以了解我所缺少的内容。
tbone 2011年

Answers:


139

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

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

也许您知道一种方法(内容类型是什么?text / html?以这种方式发送混合的html / image文件我需要知道的电子邮件标题)
tbone 2011年

1
@Zesty使用@ [用户名]提醒某人,刚看到您的问题。我使用utl_smtp。对我来说,我必须用html主体,边界等创建一个Clob,然后通过utl_smtp发送。请参见此处的简单示例:oracle-base.com/articles/misc/EmailFromOraclePLSQL.php请注意,此链接不显示嵌入式图像方法,但有详细信息以助您一臂之力
tbone 2012年

41
数据URI在电子邮件中许多主流的客户端不支持,不应该被使用,请参阅:campaignmonitor.com/blog/post/3927/...
迈克尔Böckling

2
它似乎在hotmail中不起作用/ icloud =(我是否错过任何事情
hsb1007 2015年

21

另一种解决方案是将图像作为附件附加,然后使用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();

11

我没有找到任何有用的答案,所以我提供了解决方案。

  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的值或语法是否有一些特殊技巧:
彼得·弗林

我检查了RFC2392,CID表达式似乎有效。但是它仍然不显示。
彼得·弗林

我写了一个类似问题的答案,并创建了一种ascii艺术来解释这种结构:stackoverflow.com/a/40420648/633961
guettli


4

使用Base64将图像嵌入html非常棒。尽管如此,请注意base64字符串可能会使您的电子邮件变得很大。

因此,

1)如果您有很多图像,将图像上传到服务器并从服务器加载这些图像可以减小电子邮件的大小。(您可以通过Google获得很多免费服务)

2)如果您的邮件中只有少量图像,那么使用base64字符串绝对是一个很棒的选择。

除了现有答案提供的选择之外,您还可以在Linux上使用命令生成base64字符串:

base64 test.jpg

迈克尔·伯克林(MichaelBöckling)指出:gmail等许多主流客户端均不支持电子邮件中的数据URI
Mendy

3

我知道这是一篇过时的文章,但是当前答案并未解决Outlook和许多其他电子邮件提供商不支持嵌入式图像或CID图像的事实。将图像放置在电子邮件中最有效的方法是在线托管图像并将其链接放置在电子邮件中。对于小型电子邮件列表,可以使用公共投寄箱。这也可以减小电子邮件的大小。


2
  1. 您需要3个边界才能使内嵌图像完全兼容。

  2. 一切都在内部multipart/mixed

  3. 然后使用multipart/related来包含您multipart/alternative和您的图片附件标题。

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


11
如果您包含一个示例,将会很有帮助。
Makyen

7
更为有用的将是对该规范的引用。
jbruni

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

对于那些无法使用以下解决方案之一的用户: 通过电子邮件发送嵌入式图像 按照@ T30提供的解决方案中列出的步骤,我能够显示嵌入式图像而不会受到Outlook的阻止(以前的方法已阻止) 。如果您像我们一样在使用交换,那么在进行以下操作时:

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

您需要将其传递给您的交换服务网址托管人。除了遵循此解决方案之外,还可以使您轻松发送嵌入式图像。


1

如果您使用“插入/图片”菜单功能插入图像文件,则Outlook和Outlook Express都可以生成这些多部分图像电子邮件格式可能会很有趣。

显然,电子邮件类型必须设置为HTML(不是纯文本)。

任何其他方法(例如,拖放或任何命令行调用)都会导致将图像作为附件发送。

然后,如果您将这样的电子邮件发送给自己,则可以查看其格式!:)

FWIW,我正在寻找一个独立的Windows可执行文件,它从命令行模式执行内联图像,但是似乎没有。这是许多人走的一条路...可以使用Outlook Express通过传递适当格式的.eml文件来做到这一点。


0

以下是具有两种实现方式的工作代码:

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();
        }
    }
}

0

Pavel Perna帖子的另一个提示对我很有帮助(无法评论我的声誉,这就是为什么我将其发布为答案):在某些版本的Microsoft Exchange中,删除了内联内容处置(请参阅Microsoft的这篇文章)。该图像根本不属于用户在Outlook中看到的邮件的一部分。解决方法是改用“ Content-Disposition:附件”。尽管Outlook 2016使用“内容处置:附件”,但它们不会将邮件中显示的图像显示为附件。


-30

如果使用Outlook发送带有超链接的静态图像,一种简单的方法是使用Word。

  1. 打开MS Word
  2. 将图像复制到空白页上
  3. 将超链接添加到图像(Ctrl + K)
  4. 将图片复制到您的电子邮件中
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.