如何将MimeBodyPart的ContentType设置为"text/html"?

37
下面的程序显示了HTML多部分MIME类型的意外返回值。为什么这个程序打印出"text/plain"而不是"text/html"?
public class Main {
  public static void main(String[] args) throws javax.mail.MessagingException, java.io.IOException {
    javax.mail.internet.MimeBodyPart mime_body_part = new javax.mail.internet.MimeBodyPart();
    mime_body_part.setContent("<h1>foo</h1>", "text/html");
    System.out.println(mime_body_part.getContentType());
  }
}

我已经尝试了许多替代方式,包括使用ByteArrayDataSource并将其包装在DataHandler中,但都没有成功。当我尝试将其用于MimeBodyPart时,出现了相同的情况。

在Linux上编译和运行:

javac -classpath .:activation.jar:mail.jar Main.java
java -classpath .:activation.jar:mail.jar Main
8个回答

64

在封装消息上调用MimeMessage.saveChanges(),这将通过在你的正文部分上调用MimeBodyPart.updateHeaders()来更新标题。正是这个updateHeaders调用将内容类型从DataHandler转移到部分的MIME Content-Type标头。

当您设置MimeBodyPart的内容时,JavaMail在内部(并不明显地)创建一个包装您传递的对象的DataHandler对象。部分的Content-Type标头不会立即更新。

由于没有包含MimeMessage,且MimeBodyPart.updateHeaders()不是public,因此在测试程序中没有直接的方法可以实现它。


这是一个可行的示例,可以说明预期和意外输出:

public class MailTest {

  public static void main( String[] args ) throws Exception {
    Session mailSession = Session.getInstance( new Properties() );
    Transport transport = mailSession.getTransport();

    String text = "Hello, World";
    String html = "<h1>" + text + "</h1>";

    MimeMessage message = new MimeMessage( mailSession );
    Multipart multipart = new MimeMultipart( "alternative" );

    MimeBodyPart textPart = new MimeBodyPart();
    textPart.setText( text, "utf-8" );

    MimeBodyPart htmlPart = new MimeBodyPart();
    htmlPart.setContent( html, "text/html; charset=utf-8" );

    multipart.addBodyPart( textPart );
    multipart.addBodyPart( htmlPart );
    message.setContent( multipart );

    // Unexpected output.
    System.out.println( "HTML = text/html : " + htmlPart.isMimeType( "text/html" ) );
    System.out.println( "HTML Content Type: " + htmlPart.getContentType() );

    // Required magic (violates principle of least astonishment).
    message.saveChanges();

    // Output now correct.    
    System.out.println( "TEXT = text/plain: " + textPart.isMimeType( "text/plain" ) );
    System.out.println( "HTML = text/html : " + htmlPart.isMimeType( "text/html" ) );
    System.out.println( "HTML Content Type: " + htmlPart.getContentType() );
    System.out.println( "HTML Data Handler: " + htmlPart.getDataHandler().getContentType() );
  }
}

1
更新 - 这对我的测试程序运行良好,但在我的真实代码中却不行。区别在于真实代码获取的是由邮件系统创建的MimeMessage对象,然后更新其中的一部分,并调用MimeMessage.saveChanges()方法。即使在调用.saveChanges()之前,内容已经改变,但仍然无法更改MIME类型。解决方案:我从旧的MimeMessage对象创建了一个新的MimeMessage(old_mime_message)对象,修改了内容和类型,然后调用.saveChanges(),这样就可以正常工作了。 - necromancer
1
MimeMessage.saveChanges() 是我需要的魔法,让我们的 JUnit 测试通过了。 - Neil Wightman

28

不知道为什么(该方法没有文档),但是通过查看源代码,应该可以用这一行来实现:

mime_body_part.setHeader("Content-Type", "text/html");

4
谢谢 - 我非常感激您的帮助。我选择了不同的答案,因为它更符合图书馆的意图。但是您的答案对我在紧急任务中取得进展非常有价值。再次感谢。 - necromancer

7
尝试使用这个:

尝试使用这个:

msg.setContent(email.getBody(), "text/html; charset=ISO-8859-1");

5
使用什么呢:
mime_body_part.setHeader("Content-Type", "text/html");

getContentType 文档 中提到,返回的值是使用 getHeader(name) 找到的。因此,如果您使用 setHeader 设置标头,一切应该都没问题。

1
谢谢你 - 我感激你的帮助。我选择了上面不同的答案,因为它更符合库被设计的使用方式。但是你的答案对我在完成紧急任务时取得即时进展非常有价值。再次感谢。 - necromancer

4

有一个方法叫做setText(),它有三个参数:

public void setText(String text, String charset, String subtype)
    throws MessagingException

参数:

text - the text content to set
charset - the charset to use for the text
subtype - the MIME subtype to use (e.g., "html")

注意:子类型指MIME类型中“/”后面的文本,例如:

  • text/html 将成为 html
  • text/css 将成为 css
  • 以此类推……

http://docs.oracle.com/javaee/6/api/javax/mail/internet/MimeMessage.html#setText(java.lang.String, java.lang.String, java.lang.String)请参考上述链接,了解有关JavaMail中MimeMessage类的setText()方法的详细信息。 - Ken Lin

2
使用"<h1>STRING<h1>".getBytes();,您可以创建一个带有内容类型的ByteArrayDataSource,并在MimeBodyPart中设置setDataHandler
尝试:
String html "Test JavaMail API example. <br><br> Regards, <br>Ivonei Jr"
byte[] bytes = html.getBytes(); 
DataSource dataSourceHtml= new ByteArrayDataSource(bytes, "text/html");
MimeBodyPart bodyPart = new MimeBodyPart();
bodyPart.setDataHandler(new DataHandler(dataSourceHtml));

MimeMultipart mimeMultipart = new MimeMultipart();
mimeMultipart.addBodyPart(bodyPart);

2

对我来说,我设定了两个时间点:

(MimeBodyPart)messageBodyPart.setContent(content, text/html)
(Multipart)multipart.addBodyPart(messageBodyPart)
(MimeMessage)msg.setContent(multipart, text/html)

它一直运行良好。


1

我在我的SpringBoot应用程序中使用了以下代码。

MimeMessage message = sender.createMimeMessage();
message.setContent(message, "text/html");
MimeMessageHelper helper = new MimeMessageHelper(message);

helper.setFrom(fromAddress);
helper.setTo(toAddress);
helper.setSubject(mailSubject);
helper.setText(mailText, true);

sender.send(message);

在我的情况下,添加“message.setContent(message, "text/html");”和“helper.setText(mailText, true);”解决了问题。 - Pravin Kumar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接