使用JavaMail在电子邮件中内嵌图像

时间:2010-06-08 10:29:49

标签: java mime mime-types javamail multipart

我想使用javamail发送包含内嵌图片的电子邮件。

我正在做这样的事情。

MimeMultipart content = new MimeMultipart("related");

BodyPart bodyPart = new MimeBodyPart();
bodyPart.setContent(message, "text/html; charset=ISO-8859-1");
content.addBodyPart(bodyPart);

bodyPart = new MimeBodyPart();
DataSource ds = new ByteArrayDataSource(image, "image/jpeg");
bodyPart.setDataHandler(new DataHandler(ds));
bodyPart.setHeader("Content-Type", "image/jpeg; name=image.jpg");
bodyPart.setHeader("Content-ID", "<image>");
bodyPart.setHeader("Content-Disposition", "inline");
content.addBodyPart(bodyPart);

msg.setContent(content);

我也试过

    bodyPart.setHeader("inline; filename=image.jpg");

    bodyPart.setDisposition("inline");

但无论如何,图片都是作为附件发送的,而Content-Dispostion正在变成“附件”。

如何使用javamail在电子邮件中内嵌发送图像?

9 个答案:

答案 0 :(得分:32)

您的问题

据我所知,它看起来像你创建消息的方式,一切都是正确的!您使用正确的MIME类型和所有内容。

我不确定您为什么使用DataSource和DataHandler,并且在图片上有ContentID,但是您需要为我完成问题才能排除更多问题。特别是,以下一行:

bodyPart.setContent(message, "text/html; charset=ISO-8859-1");

message中的内容是什么?它是否包含<img src="cid:image" />

您是否尝试使用String cid = ContentIdGenerator.getContentId();生成ContentID,而不是使用image


来源

此博客文章教我如何使用正确的消息类型,附加我的图像并引用HTML正文中的附件:How to Send Email with Embedded Images Using Java


详细

消息

您必须使用MimeMultipart课程创建内容。使用字符串"related"作为构造函数的参数非常重要,告诉JavaMail您的部件“一起工作”

MimeMultipart content = new MimeMultipart("related");

内容标识符

您需要生成ContentID,它是一个字符串,用于标识您附加到电子邮件中的图像,并从电子邮件正文中引用它。

String cid = ContentIdGenerator.getContentId();

注意:这个ContentIdGenerator类是假设的。您可以创建一个或内联创建内容ID。就我而言,我使用一种简单的方法:

import java.util.UUID;

// ...

String generateContentId(String prefix) {
     return String.format("%s-%s", prefix, UUID.randomUUID());
}

HTML正文

HTML代码是MimeMultipart内容的一部分。请使用MimeBodyPart类。设置该部分的文本时,请不要忘记指定encoding"html"

MimeBodyPart htmlPart = new MimeBodyPart();
htmlPart.setText(""
  + "<html>"
  + " <body>"
  + "  <p>Here is my image:</p>"
  + "  <img src=\"cid:" + cid + "\" />"
  + " </body>"
  + "</html>" 
  ,"US-ASCII", "html");
content.addBodyPart(htmlPart);

请注意,作为图片的来源,我们使用cid:和生成的ContentID。

图片附件

我们可以为图片的附件创建另一个MimeBodyPart

MimeBodyPart imagePart = new MimeBodyPart();
imagePart.attachFile("resources/teapot.jpg");
imagePart.setContentID("<" + cid + ">");
imagePart.setDisposition(MimeBodyPart.INLINE);
content.addBodyPart(imagePart);

请注意,我们在<>之间使用相同的ContentID,并将其设置为图片的ContentID。我们还将处置设置为INLINE,以表明此图片要显示在电子邮件中,而不是作为附件。

完成消息

就是这样!如果您在正确的会话上创建SMTP邮件并使用该内容,则您的电子邮件将包含嵌入的图像!例如:

SMTPMessage m = new SMTPMessage(session);
m.setContent(content);
m.setSubject("Mail with embedded image");
m.setRecipient(RecipientType.TO, new InternetAddress("your@email.com"));
Transport.send(m)

如果这对你有用,请告诉我! ;)

答案 1 :(得分:10)

你为什么不尝试这样的事?

    MimeMessage mail =  new MimeMessage(mailSession);

    mail.setSubject(subject);

    MimeBodyPart messageBodyPart = new MimeBodyPart();

    messageBodyPart.setContent(message, "text/html");

    Multipart multipart = new MimeMultipart();
    multipart.addBodyPart(messageBodyPart);

    messageBodyPart = new MimeBodyPart();
    DataSource source = new FileDataSource(new File("complete path to image.jpg"));
    messageBodyPart.setDataHandler(new DataHandler(source));
    messageBodyPart.setFileName(fileAttachment.getName());
    messageBodyPart.setDisposition(MimeBodyPart.INLINE);
    multipart.addBodyPart(messageBodyPart);

    mail.setContent(multipart);
消息中的

,有一个 <img src="image.jpg"/> 标记,你应该没问题。

祝你好运

答案 2 :(得分:10)

这对我有用:

  MimeMultipart rootContainer = new MimeMultipart();
  rootContainer.setSubType("related"); 
  rootContainer.addBodyPart(alternativeMultiPartWithPlainTextAndHtml); // not in focus here
  rootContainer.addBodyPart(createInlineImagePart(base64EncodedImageContentByteArray));
  ...
  message.setContent(rootContainer);
  message.setHeader("MIME-Version", "1.0");
  message.setHeader("Content-Type", rootContainer.getContentType());

  ...


  BodyPart createInlineImagePart(byte[] base64EncodedImageContentByteArray) throws MessagingException {
    InternetHeaders headers = new InternetHeaders();
    headers.addHeader("Content-Type", "image/jpeg");
    headers.addHeader("Content-Transfer-Encoding", "base64");
    MimeBodyPart imagePart = new MimeBodyPart(headers, base64EncodedImageContentByteArray);
    imagePart.setDisposition(MimeBodyPart.INLINE);
    imagePart.setContentID("&lt;image&gt;");
    imagePart.setFileName("image.jpg");
    return imagePart;

答案 3 :(得分:2)

如果您使用 Spring ,请使用cmd.exe发送包含内联内容的电子邮件(References)。

  

创建JavaMailSender bean或通过向application.properties文件添加相应的属性来配置它,如果您使用 Spring Boot

MimeMessageHelper
  

创建算法以生成唯一的 CONTENT-ID

@Bean
public JavaMailSender getJavaMailSender() {
    JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
    mailSender.setHost(host);
    mailSender.setPort(port);
    mailSender.setUsername(username);
    mailSender.setPassword(password);
    Properties props = mailSender.getJavaMailProperties();
    props.put("mail.transport.protocol", "smtp");
    props.put("mail.smtp.auth", authEnable);
    props.put("mail.smtp.starttls.enable", starttlsEnable);
    //props.put("mail.debug", "true");
    mailSender.setJavaMailProperties(props);
    return mailSender;
}
  

使用内联发送电子邮件。

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Random;

public class ContentIdGenerator {

    static int seq = 0;
    static String hostname;

    public static void getHostname() {
        try {
            hostname = InetAddress.getLocalHost().getCanonicalHostName();
        }
        catch (UnknownHostException e) {
            // we can't find our hostname? okay, use something no one else is
            // likely to use
            hostname = new Random(System.currentTimeMillis()).nextInt(100000) + ".localhost";
        }
    }

    /**
     * Sequence goes from 0 to 100K, then starts up at 0 again. This is large
     * enough,
     * and saves
     * 
     * @return
     */
    public static synchronized int getSeq() {
        return (seq++) % 100000;
    }

    /**
     * One possible way to generate very-likely-unique content IDs.
     * 
     * @return A content id that uses the hostname, the current time, and a
     *         sequence number
     *         to avoid collision.
     */
    public static String getContentId() {
        getHostname();
        int c = getSeq();
        return c + "." + System.currentTimeMillis() + "@" + hostname;
    }

}

答案 4 :(得分:0)

以下是完整的代码

    import java.awt.image.BufferedImage;
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.IOException;
    import javax.imageio.ImageIO;

    private BodyPart createInlineImagePart()  {
    MimeBodyPart imagePart =null;
    try
    {

        ByteArrayOutputStream baos=new ByteArrayOutputStream(10000);
        BufferedImage img=ImageIO.read(new File(directory path,"sdf_email_logo.jpg"));
        ImageIO.write(img, "jpg", baos);
        baos.flush();

        String base64String=Base64.encode(baos.toByteArray());
        baos.close();

        byte[] bytearray = Base64.decode(base64String);
        InternetHeaders headers = new InternetHeaders();
        headers.addHeader("Content-Type", "image/jpeg");
        headers.addHeader("Content-Transfer-Encoding", "base64");
        imagePart = new MimeBodyPart(headers, bytearray);
        imagePart.setDisposition(MimeBodyPart.INLINE);
        imagePart.setContentID("&lt;sdf_email_logo&gt;");
        imagePart.setFileName("sdf_email_logo.jpg");
    }
    catch(Exception exp)
    {
        logError("17", "Logo Attach Error : "+exp);
    }

    return imagePart;
}


MimeMultipart mp = new MimeMultipart();
 //mp.addBodyPart(createInlineImagePart());

mp.addBodyPart(createInlineImagePart());

String body="<img src=\"cid:sdf_email_logo\"/>"

答案 5 :(得分:0)

使用以下代码段:

MimeBodyPart imgBodyPart = new MimeBodyPart();
imgBodyPart.attachFile("Image.png");
imgBodyPart.setContentID('<'+"i01@example.com"+'>');
imgBodyPart.setDisposition(MimeBodyPart.INLINE);
imgBodyPart.setHeader("Content-Type", "image/png");

multipart.addBodyPart(imgBodyPart);

你不需要在线&amp;基本编码 - 您可以传统附加并将链接添加到主消息的文本text/html
但是,请记住在附加到主消息之前(在附加文件之后)将imgBodyPart的标题Content-Type设置为image/jpg左右。

答案 6 :(得分:0)

I had some problems having inline images displayed in GMail and Thunderbird, made some tests and resolved with the following (sample) code:

String imagePath = "/path/to/the/image.png";
String fileName = imagePath.substring(path.lastIndexOf('/') + 1);
String htmlText = "<html><body>TEST:<img src=\"cid:img1\"></body></html>";
MimeMultipart multipart = new MimeMultipart("related");
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setContent(htmlText, "text/html; charset=utf-8");
multipart.addBodyPart(messageBodyPart);
messageBodyPart = new MimeBodyPart();
DataSource fds = new FileDataSource(imagePath);
messageBodyPart.setDataHandler(new DataHandler(fds));
messageBodyPart.setHeader("Content-ID", "<img1>");
messageBodyPart.setDisposition(MimeBodyPart.INLINE);
messageBodyPart.setFileName(fileName);
multipart.addBodyPart(messageBodyPart);
message.setContent(multipart);

Just some things to notice:

  • the "Content-ID" has to be built as specified in the RFCs (https://tools.ietf.org/html/rfc2392), so it has to be the part in the img tag src attribute, following the "cid:", enclosed by angle brackets ("<" and ">")
  • I had to set the file name
  • no need for width, height, alt or title in the img tag
  • I had to put the charset that way, because the one in the html was being ignored

This worked for me making inline images display for some clients and in GMail web client, I don't mean this will work everywhere and forever! :)

(Sorry for my english and for my typos!)

答案 7 :(得分:0)

可以在此处找到

RFC规范(https://tools.ietf.org/html/rfc2392)。

首先,使用嵌入式图片时,电子邮件html内容的格式应为:“ cid:logo.png”,请参见:

<td style="width:114px;padding-top: 19px">
    <img src="cid:logo.png" />
</td>

第二,MimeBodyPart对象需要将属性“ disposition”设置为MimeBodyPart.INLINE,如下所示:

String filename = "logo.png"
BodyPart image = new MimeBodyPart();
image.setDisposition(MimeBodyPart.INLINE);
image.setFileName(filename);
image.setHeader("Content-ID", "<" +filename+">");

请注意,Content-ID属性必须透视地带有“ <”和“>”前缀和后缀,并且off filename的值应与src的内容相同 不带前缀“ cid:”的img标签的

最后,整个代码如下:

Message msg = new MimeMessage(session);
msg.setFrom(new InternetAddress("1234@gmail.com");
InternetAddress[] recipients = { "123@gmail.com"};
msg.setRecipients(Message.RecipientType.TO, recipients);
msg.setSubject("for test");
msg.setSentDate(new Date());

BodyPart content = new MimeBodyPart();
content.setContent(<html><body>  <img src="cid:logo.png" /> </body></html>, "text/html; charset=utf-8");
String fileName = "logo.png";
BodyPart image = new MimeBodyPart();
image.setHeader("Content-ID", "<" +fileName+">");
image.setDisposition(MimeBodyPart.INLINE);
image.setFileName(fileName);
InputStream stream = MailService.class.getResourceAsStream(path);
DataSource fds = new ByteArrayDataSource(IOUtils.toByteArray(stream), "image/png");
image.setDataHandler(new DataHandler(fds));

MimeMultipart multipart = new MimeMultipart("related");
multipart.addBodyPart(content);
multipart.addBodyPart(getImage(image1));
msg.setContent(multipart);
msg.saveChanges();
Transport bus = session.getTransport("smtp");
bus.connect("username", "password");
bus.sendMessage(msg, recipients);
bus.close();

答案 8 :(得分:-3)

messageBodyPart.setContent(htmlText,&#34; text / html&#34;);             multipart.addBodyPart(messageBodyPart);

        messageBodyPart = new MimeBodyPart();
        DataSource fds = new FileDataSource("resources/Images/bday.jpg");

         messageBodyPart.setDataHandler(new DataHandler(fds));
         messageBodyPart.setHeader("Content-ID", "<image>");

         // add image to the multipart
         multipart.addBodyPart(messageBodyPart);

         msg.setContent(multipart);

        Transport.send(msg);
相关问题