Javamail 多部分未正确订购

Posted

技术标签:

【中文标题】Javamail 多部分未正确订购【英文标题】:Javamail multiparts not ordered correctly 【发布时间】:2015-06-19 13:30:40 【问题描述】:

我有一个应用程序尝试动态构建 Javamail 消息,组装邮件时可用的 Mime 正文部分。每个图像的顶部都有一个“GPC”图像,然后是一些 html 文本(正文),一个由 HTML 构造的结束,一个结束的“品牌”图像,以及结束的最后部分,也是在 HTML 中。文件附件可能包含也可能不包含。如果适用,错误免责声明 (HTML) 可能会位于第一张图片之前。

免责声明、正文、关闭和附件是正文部分,而图像是嵌套的多部分,由包含 CID 的 HTML 容器和图像正文部分本身组成。发送电子邮件后,它在 Gmail 和 Lotus Notes 中显示正确,而在 Outlook(Hotmail) 中,GPC 图像在顶部被品牌图像覆盖。身体部位的顺序得以保留,但图像除外,图像似乎总是回到顶部。

我想不通。在我看来,“父”多部分应该是“混合”子类型,因为身体部位的顺序很重要,而且它们相对不相关,而嵌套的多部分是“相关的”,因为一个身体部分引用另一个。我的代码:

public MimeMultipart email_content_builder() throws MessagingException 
   MimeMultipart mp = new MimeMultipart();
   MimeBodyPart txt_part = new MimeBodyPart(), att_part, err_part, gpc_img_location_part, gpc_img_part, brand_img_location_part, brand_img_part, closing_pt1_part, closing_pt2_part;
   DataSource att_source, gpc_img_src, brand_img_src;
   String gpc_img_container_html, brand_img_container_html;

  //Insert error disclaimer, if applicable:
   if (!error_disclaimer.isEmpty()) 
      err_part = new MimeBodyPart();
      err_part.setText(error_disclaimer, "ISO-8859-1", "html");
      mp.addBodyPart(err_part);
   

  //Insert GPC logo image, if applicable:
   if (GPC_logo.length > 0) 
      MimeMultipart gpc_imagery_mp = new MimeMultipart("related");
      MimeBodyPart gpc_imagery_part = new MimeBodyPart();

     //When resizing the GPC image, the height should be roughly 23% of the width;  use this factor:  .2331
      gpc_img_container_html = "<html><body><img src='cid:gpc_logo' height=\"23px\" width=\"100px\"></body></html>";

      gpc_img_location_part = new MimeBodyPart();
      gpc_img_location_part.setContent(gpc_img_container_html, "text/html");

      gpc_imagery_mp.addBodyPart(gpc_img_location_part);

      gpc_img_part = new MimeBodyPart();
      gpc_img_src = new ByteArrayDataSource(GPC_logo, "image/jpeg");
      gpc_img_part.setDataHandler(new DataHandler(gpc_img_src));
      gpc_img_part.setHeader("Content-ID", "<gpc_logo>");
      gpc_img_part.setDisposition(MimeBodyPart.INLINE);

      gpc_imagery_mp.addBodyPart(gpc_img_part);
      gpc_imagery_part.setContent(gpc_imagery_mp);
      mp.addBodyPart(gpc_imagery_part);
   

  //Insert main body of email:
   txt_part.setText(body, "ISO-8859-1", "html");
   mp.addBodyPart(txt_part);

  //Insert the first part of the closing, if applicable:
   if (!Closing_Part1.isEmpty()) 
      closing_pt1_part = new MimeBodyPart();
      closing_pt1_part.setText(Closing_Part1, "ISO-8859-1", "html");
      mp.addBodyPart(closing_pt1_part);
   

  //Insert brand logo image, if applicable:
   if (brand_logo.length > 0) 
      MimeMultipart brand_imagery_mp = new MimeMultipart("related");
      MimeBodyPart brand_imagery_part = new MimeBodyPart();

     //When resizing the brand image, the height should be roughly 43% of the width;  use this factor:  .4294
      brand_img_container_html = "<html><body><img src='cid:brand_logo' height=\"64px\" width=\"150px\"></body></html>";

      brand_img_location_part = new MimeBodyPart();
      brand_img_location_part.setContent(brand_img_container_html, "text/html");

      brand_imagery_mp.addBodyPart(brand_img_location_part);

      brand_img_part = new MimeBodyPart();
      brand_img_src = new ByteArrayDataSource(brand_logo, "image/jpeg");
      brand_img_part.setDataHandler(new DataHandler(brand_img_src));
      brand_img_part.setHeader("Content-ID", "<brand_logo>");
      brand_img_part.setDisposition(MimeBodyPart.INLINE);

      brand_imagery_mp.addBodyPart(brand_img_part);
      brand_imagery_part.setContent(brand_imagery_mp);
      mp.addBodyPart(brand_imagery_part);
   

  //Insert the second part of the closing, if applicable:
   if (!Closing_Part2.isEmpty()) 
      closing_pt2_part = new MimeBodyPart();
      closing_pt2_part.setText(Closing_Part2, "ISO-8859-1", "html");
      mp.addBodyPart(closing_pt2_part);
   

  //Insert attachments, if applicable:
   if (attachments != null) 
      for (int j = 0; j < attachments.size(); j++) 
         att_part = new MimeBodyPart();

         att_source = new FileDataSource((attachments.get(j)).getPath());
         att_part.setDataHandler(new DataHandler(att_source));
         att_part.setFileName((attachments.get(j)).getPath());

         mp.addBodyPart(att_part);
      
   
   return mp;

【问题讨论】:

【参考方案1】:

您对不同的邮件阅读器如何在您的邮件中显示多个正文部分的控制非常有限。最好的办法是将所有非附件内容放入单个 text/html 正文部分,使用 html 来格式化消息。您可以使用 multipart/related 在消息中包含图片,但在网络上引用图片通常更简单。

【讨论】:

谢谢比尔。我现在倾向于这个方向,尽管在本练习开始时,我不知道将这些图像托管在某处的 Web 服务器上是否是一种选择。我现在正在调查这种可能性。 参考网络上的图片解决了这个问题。谢谢。

以上是关于Javamail 多部分未正确订购的主要内容,如果未能解决你的问题,请参考以下文章

Jmeter Groovy JavaMail API 多部分向示例结果添加内容

JavaMail 问题或错误?

MailSendException SSLHandshakeException JavaMail 电子邮件未发送

javamail 阅读邮件时,有啥理由使用 Message 而不是 MimeMessage 等?

如何使用 javamail 在 android 应用程序中处理 multipart/alternative?

javaMail