Send email includes image like Outlook does?

2019-09-07 00:10发布

问题:

I'm learning about javamail API. To send an email includes image, I use imgPart.setHeader ("Content-ID", "img"). The recipient will see mail content with image and image attached above. But when I compose email includes image using Outlook, the recipient won't see any attached image, just see mail text and embedded image. How can Outlook do that ?

Thank you.

回答1:

Outlook and other similar clients embed HTML version of the text in addition to the plain text. In the html they then reference the image with it's ID using the img tag (that you set when embedding the image itself). The image is embedded separately as you already do.

But I would recommend you use a more unique ID than 'img' (not to be confused with the tag I mention above) for the part-ID (f.ex. hash the original file name).

Update:

To show more clearly here's an example. Lets say I sent this email:

This will give this source sent over the SMTP - here you notice the first part is in plain text:

...other header parts snipped
Subject: Demo attachments
Content-Type: multipart/alternative;
 boundary="------------080308060008080306040307"

This is a multi-part message in MIME format.
--------------080308060008080306040307
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

This text is attached as HTML. As we reference an image this will be 
displayed here as well as being an attachment as usual.



End of message


--------------080308060008080306040307

After that Thunderbird (in this case, same with Outlook) inserts a HTML version of the same text, which it was edited in:

Content-Type: multipart/related;
 boundary="------------080209080402080405070800"


--------------080209080402080405070800
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

<html>
  <head>

    <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    This text is attached as HTML. As we reference an image this will be
    displayed here as well as being an attachment as usual.<br>
    <br>
    <img src="cid:part1.03070608.09040802@xxxxxxxxxxxxxxxx" alt=""><br>
    <br>
    End of message<br>
    <br>
  </body>
</html>

--------------080209080402080405070800

Notice the link for the image above (I scrambled the domain with x's):

<img src="cid:part1.03070608.09040802@xxxxxxxxxxxxxxxx" alt="">

If you now look at the rest of the attachments in the message body, you will see that Content-ID has the same ID as referenced in the HTML - the image itself is attached as usual in Base64 format. The reference link always starts with cid:<attachement ID>

ID can be anything that doesn't collide with other parts in the body.

Also notice the Content-Disposition line which instruct Thunderbird to display it inline, not strictly necessary as it is referenced in the HTML, but helps the client to know if the intention with this image was to show it inline or make it available to download as a "pure" attachment:

Content-Type: image/png;
 name="ddebjigc.png"
Content-Transfer-Encoding: base64
Content-ID: <part1.03070608.09040802@xxxxxxxxxxxxxxxx>
Content-Disposition: inline;
 filename="ddebjigc.png"

iVBORw0KGgoAAAANSUhEUgAAANsAAAAcCAIAAABnDF0bAAASPElEQVR4nO2b+VMTWbvHc/+I
+TNu6SiyyL4lyL4qm4gIoigiO4ii4OCGsoR9QAQZkRAC4uj4jigZRRyZV3iRfQ+BrJ3uQMjG
Ork/dLrTaxJmbt2aqkvXt6ic06efX/jUs5zzHEZ6WuKBDvTPEePx49YDHeifIwYIQQRBSghS

...snipped to shorten text in this example...

sFjyaDrJSZ6SMnZjnCKphQLLIrYhUgGSPSj6IbHoJl2HxYVvEojkezZ0oo3jlD4ScwvW2EhB
c/8Vv4zUZE66LIuGXdOdV1x0xl/H+Zs+EjNEnCKRMPy8pfs3GKdIaKPEOUXSegUikGFNJ/rB
c/D8nz3/A+4rfUt5pwb4AAAAAElFTkSuQmCC
--------------080209080402080405070800--

--------------080308060008080306040307--

Hope this made it clearer.



回答2:

Did you create a multipart/related message, as described in the JavaMail FAQ?



回答3:

                File template = new File ("template.htm");
        FileUtils readContent = new FileUtils ();
        String content = readContent.readFileToString (template);

        MimeMultipart multiPart = new MimeMultipart ("related");
        BodyPart bodyPart = new MimeBodyPart ();
        bodyPart.setContent (content, "text/html");
        multiPart.addBodyPart (bodyPart);
        BodyPart imgPart = new MimeBodyPart ();
        DataSource img_data = new FileDataSource ("template\\image001.jpg");
        imgPart.setDataHandler (new DataHandler (img_data));
        imgPart.setDisposition (MimeBodyPart.INLINE);
        imgPart.setHeader ("Content-ID", "img_1");
        multiPart.addBodyPart (imgPart);