MimeMessage.getAllHeaders() returns 两个不同的 类 在两个不同的项目中

MimeMessage.getAllHeaders() returns two different classes in two different projects

我有一个关于邮件的项目并且工作没有问题,但我创建了另一个项目也是关于邮件生成的 MimeMessage 无法在第一个项目中解析。

我研究了 classes 并发现了 header class 和 MimeMessage 之间的区别 两个项目都在使用

javax.mail.internet.MimeMessage

但我将 header 记录为:

Enumeration enumer = originalUserMessage.getAllHeaders();
while(true){
    try{
        Object obj = enumer.nextElement();
        if(obj == null) {
            break;
        }
        LOGGER.info("Header class: "+obj.getClass().getName());
        LOGGER.info("Header super class:" + obj.getClass().getSuperclass().getName());
    } catch (NoSuchElementException nsee) {
        break;
    }

}

打印的第一个项目:

2015-03-03 16:57:16 INFO  SmimeWriter:204 - Header class: 
javax.mail.Header
2015-03-03 16:57:16 INFO  SmimeWriter:205 - Header super class: 
java.lang.Object

打印第二个项目

2015-03-03 16:57:39 INFO  SmimeWriter:204 - Header class: 
javax.mail.internet.InternetHeaders$InternetHeader
2015-03-03 16:57:39 INFO  SmimeWriter:205 - Header super class: 
javax.mail.Header

所有相关的 class 似乎都在 mail.jar 中。我正在使用 Maven 来获取 jar 并且两个项目都将 jar 获取为:

<dependency>
  <groupId>javax.mail</groupId>
  <artifactId>mail</artifactId>
  <version>1.4.2</version>
</dependency>

可能是什么问题。还有其他依赖的jar吗?

两个项目都使用相同的方法。在设置了 MIME 消息的其他部分下面的代码块之后,但此处出现问题。 代码:

        MimeMessage originalUserMessage = new MimeMessage(session);

        originalUserMessage.setFrom(from);
        originalUserMessage.setRecipients(Message.RecipientType.TO, to);
        if(cc != null && cc.length>0){
            originalUserMessage.setRecipients(Message.RecipientType.CC, cc);
        }

        Enumeration enumer = originalUserMessage.getAllHeaders();
        while(true){
            try{
                Object obj = enumer.nextElement();
                if(obj == null) {
                    break;
                }
                LOGGER.info("Header class: "+obj.getClass().getName());
                LOGGER.info("Header super class: "+obj.getClass().getSuperclass().getName());
            } catch (NoSuchElementException nsee) {
                break;
            }

        }

这根本不是问题。 contract of the MimeMessage.getAllHeaders() method 明确:

Return all the headers from this Message as an enumeration of Header objects.

该文档指的是 javax.mail.Header class。

因此,当您调用 MimeMessage.getAllHeaders() 时,只能安全地假设枚举将 return 个 javax.mail.Header 的实例。它 可能会或可能不会 return 对象是 Header 的子class,根据多态性的基本规则,这是一件完全有效的事情,只要调用代码可以像 Header 实例一样安全地对待它们。

根据您 运行 程序的方式,pom.xml 中 JavaMail 的版本可能无关紧要。在JavaEE容器(如GlassFish和JBoss)和servlet容器(如Tomcat)中,JavaMail是容器提供的,所以即使你打包自己的版本JavaMail 与您的应用程序一起使用,ClassLoader 可能会忽略它并无条件地使用服务器环境提供的 JavaMail。

旁注:遍历枚举的正确方法是使用其 hasMoreElements() 方法:

while (enumer.hasMoreElements()) {
    Header header = (Header) enumer.nextElement();
    System.out.printf("%s: %s%n", header.getName(), header.getValue());
}

尽管使用 try/catch 在技术上可行,但使用 try/catch 检测枚举结束是不正确的。它更慢,更难阅读,并且可能会无意中发现编程错误,这使得调试变得更加困难。