การฝังรูปภาพในอีเมล html


113

ฉันกำลังพยายามส่งอีเมล html แบบหลายส่วน / ที่เกี่ยวข้องพร้อมภาพ GIF แบบฝัง อีเมลนี้สร้างขึ้นโดยใช้ Oracle PL / SQL ความพยายามของฉันล้มเหลวโดยมีภาพแสดงเป็น X สีแดง (ใน Outlook 2007 และ Yahoo Mail)

ฉันส่งอีเมล html มาระยะหนึ่งแล้ว แต่ตอนนี้ข้อกำหนดของฉันคือต้องใช้รูปภาพ gif หลายรูปในอีเมล ฉันสามารถจัดเก็บสิ่งเหล่านี้ไว้ในเว็บเซิร์ฟเวอร์ของเราและเชื่อมโยงไปยังเซิร์ฟเวอร์เหล่านี้ แต่อีเมลไคลเอ็นต์ของผู้ใช้จำนวนมากจะไม่แสดงโดยอัตโนมัติและจะต้องเปลี่ยนการตั้งค่าหรือดาวน์โหลดด้วยตนเองสำหรับอีเมลแต่ละฉบับ

ดังนั้นความคิดของฉันคือการฝังรูปภาพ คำถามของฉันคือ:

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

ขอบคุณมาก.

BTW: ใช่ฉันได้ตรวจสอบแล้วว่าข้อมูล base64 นั้นถูกต้องเนื่องจากฉันสามารถฝังรูปภาพใน html ได้เอง (โดยใช้ algo เดียวกันในการสร้างข้อมูลส่วนหัว) และดูรูปภาพใน Firefox / IE

ฉันควรทราบด้วยว่านี่ไม่ได้มีไว้สำหรับสแปมอีเมลจะถูกส่งไปยังลูกค้าเฉพาะที่คาดหวังว่าจะได้รับทุกวัน เนื้อหาขับเคลื่อนด้วยข้อมูลไม่ใช่โฆษณา


คำถามด่วน: คุณโฮสต์ภาพเหล่านี้นอกสถานที่หรือฝังลงในอีเมลโดยตรงหรือไม่?
JonLim

ส่วนหนึ่งของคำถามของฉันจริงๆฉันสามารถทำได้ ฉันพยายามที่จะฝังไว้ที่นี่ แต่ก็ไม่สำเร็จ หากฉันเพียงแค่เชื่อมโยงไปยังผู้ใช้จำนวนมากจะไม่เห็นภาพหากไม่ดาวน์โหลดก่อนซึ่งฉันต้องการหลีกเลี่ยง
tbone

1
ปกติ<img src="URL" />ใช้ได้ผลสำหรับฉัน แต่เป็นภาพที่ฉันโฮสต์นอกสถานที่ ที่ไม่ได้ผลสำหรับคุณ?
JonLim

"งาน" เป็นเรื่องส่วนตัว ... ใช่มันใช้ได้ผลถ้าผู้ใช้ยินดีที่จะดาวน์โหลดภาพทุกครั้ง แต่ฉันต้องการหลีกเลี่ยงสิ่งนั้นและฝังรูปภาพ
tbone

1
@JonLim: ขอบคุณสำหรับการตรวจสอบดูความคิดเห็นของฉันในคำตอบสำหรับสิ่งที่ฉันขาดหายไป
tbone

คำตอบ:


139

พยายามแทรกโดยตรงวิธีนี้จะทำให้คุณสามารถแทรกรูปภาพหลาย ๆ ภาพในตำแหน่งต่างๆในอีเมลได้

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

และเพื่อให้โพสต์นี้เป็นประโยชน์สำหรับผู้อื่น: หากคุณไม่มีสตริง base64-data ให้สร้างได้อย่างง่ายดายที่: 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--

// แก้ไข: โอ้ฉันเพิ่งรู้ว่าถ้าคุณใส่ข้อมูลโค้ดแรกจากโพสต์ของฉันเพื่อเขียนอีเมลด้วยธันเดอร์เบิร์ดธันเดอร์เบิร์ดจะเปลี่ยนโค้ด html โดยอัตโนมัติให้ดูเหมือนกับโค้ดที่สองในโพสต์ของฉัน


5
ลองสิ่งนี้ก่อนมันไม่ได้ผลสำหรับฉันสำหรับอีเมล ใช้งานได้ดีสำหรับการดูใน IE / Firefox แต่ไม่ได้ส่งเป็นอีเมล
tbone

บางทีคุณอาจจะรู้วิธี (เนื้อหาจะเป็นแบบไหนข้อความ / html ส่วนหัวอีเมลที่ฉันต้องรู้เพื่อส่งไฟล์ html / รูปภาพแบบผสมด้วยวิธีนี้)
tbone

1
@ Zesty ใช้ @ [ชื่อผู้ใช้] เพื่อแจ้งเตือนใครบางคนเพิ่งเห็นคำถามของคุณ ฉันใช้ utl_smtp สำหรับฉันฉันต้องสร้าง build clob ด้วยเนื้อหา html ขอบเขต ฯลฯ แล้วส่งผ่าน utl_smtp ดูตัวอย่างง่ายๆได้ที่นี่: oracle-base.com/articles/misc/EmailFromOraclePLSQL.phpโปรดทราบว่าลิงก์นี้ไม่แสดงวิธีการฝังรูปภาพ แต่มีรายละเอียดเพื่อให้คุณไปได้
tbone

41
URI ของข้อมูลในอีเมลไม่ได้รับการสนับสนุนในไคลเอนต์กระแสหลักจำนวนมากและไม่ควรใช้โปรดดูที่campaignmonitor.com/blog/post/3927/…
Michael Böckling

2
ดูเหมือนว่าจะไม่ทำงานใน hotmail / icloud = (ฉันพลาดอะไรไปหรือ
เปล่า

22

วิธีแก้ปัญหาอื่นคือการแนบรูปภาพเป็นสิ่งที่แนบมาจากนั้นอ้างอิงโค้ด html โดยใช้ cid

รหัส 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--

จากนั้นมันจะทำงาน


ดิ้นรนกับสิ่งนี้ ฉันได้เข้ารหัสตามด้านบนทุกประการ แต่รูปภาพไม่ปรากฏ (เพียงแค่กรอบที่มีข้อความแสดงแทนข้อความใช้งานได้ดี) Content-ID ของฉันคือ <filename.jpg> ดังนั้น href = "cid: filename.jpg" ของฉัน - มีเคล็ดลับพิเศษสำหรับค่าหรือไวยากรณ์ของ Content-ID และ cid:?
Peter Flynn

ฉันตรวจสอบด้วย RFC2392 และดูเหมือนว่านิพจน์ CID จะถูกต้อง แต่มันยังไม่แสดง
Peter Flynn

ฉันเขียนคำตอบสำหรับคำถามที่คล้ายกันและสร้างศิลปะ ascii เพื่ออธิบายโครงสร้าง: stackoverflow.com/a/40420648/633961
guettli

10

หากไม่ได้ผลคุณอาจลองใช้เครื่องมือเหล่านี้ที่แปลงรูปภาพเป็นตาราง HTML (โปรดระวังขนาดของรูปภาพของคุณ):


10
img2hmtl เป็นวิธีแก้ปัญหา / แนวคิดที่แปลกประหลาดที่สุดที่ฉันเคยเห็นมาระยะหนึ่ง +1
Kristjan Liiva

4

การใช้ Base64 เพื่อฝังรูปภาพใน html นั้นยอดเยี่ยมมาก อย่างไรก็ตามโปรดสังเกตว่าสตริง base64 สามารถทำให้ขนาดอีเมลของคุณใหญ่ได้

ดังนั้น,

1) หากคุณมีรูปภาพจำนวนมากการอัปโหลดรูปภาพของคุณไปยังเซิร์ฟเวอร์และการโหลดรูปภาพเหล่านั้นจากเซิร์ฟเวอร์อาจทำให้ขนาดอีเมลของคุณเล็กลง (คุณสามารถรับบริการฟรีมากมายผ่าน Google)

2) หากมีภาพเพียงไม่กี่ภาพในอีเมลของคุณการใช้สตริง base64 เป็นตัวเลือกที่ยอดเยี่ยมอย่างแน่นอน

นอกจากตัวเลือกที่มีให้โดยคำตอบที่มีอยู่คุณยังสามารถใช้คำสั่งเพื่อสร้างสตริง base64 บน linux:

base64 test.jpg

ชี้ให้เห็นโดย Michael Böckling: URI ข้อมูลในอีเมลไม่ได้รับการสนับสนุนในไคลเอนต์กระแสหลักจำนวนมากเช่น gmail
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/ 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);

คุณจะต้องส่งต่อโฮสต์ URL บริการแลกเปลี่ยนของคุณ นอกเหนือจากนั้นการทำตามวิธีนี้จะช่วยให้คุณสามารถส่งภาพฝังตัว


1

อาจเป็นเรื่องที่น่าสนใจที่ทั้ง Outlook และ Outlook Express สามารถสร้างรูปแบบอีเมลรูปภาพหลายส่วนเหล่านี้ได้หากคุณแทรกไฟล์รูปภาพโดยใช้ฟังก์ชันเมนูแทรก / รูปภาพ

แน่นอนว่าต้องตั้งค่าประเภทอีเมลเป็น HTML (ไม่ใช่ข้อความธรรมดา)

วิธีการอื่นใด (เช่นการลาก / วางหรือการเรียกใช้บรรทัดคำสั่ง) ส่งผลให้รูปภาพถูกส่งเป็นไฟล์แนบ

หากคุณส่งอีเมลดังกล่าวถึงตัวเองคุณจะเห็นว่ามีรูปแบบอย่างไร! :)

FWIW ฉันกำลังมองหาหน้าต่างปฏิบัติการแบบสแตนด์อโลนซึ่งทำภาพอินไลน์จากโหมดบรรทัดคำสั่ง แต่ดูเหมือนจะไม่มีเลย มันเป็นเส้นทางที่หลายคนได้ขึ้นไป ... หนึ่งสามารถทำได้ด้วยการพูด 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: Attachement" แทน Outlook 2016 จะไม่แสดงรูปภาพเป็นไฟล์แนบที่ใช้ในข้อความเมลแม้ว่าจะใช้ "Content-Disposition: Attachement" ก็ตาม


-31

หากคุณกำลังใช้ Outlook เพื่อส่งภาพนิ่งที่มีไฮเปอร์ลิงก์วิธีง่ายๆคือใช้ Word

  1. เปิด MS Word
  2. คัดลอกรูปภาพไปยังหน้าว่าง
  3. เพิ่มไฮเปอร์ลิงก์ให้กับรูปภาพ (Ctrl + K)
  4. คัดลอกรูปภาพไปยังอีเมลของคุณ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.