MimeMessage.getAllHeaders() 在两个不同的项目中返回两个不同的类
Posted
技术标签:
【中文标题】MimeMessage.getAllHeaders() 在两个不同的项目中返回两个不同的类【英文标题】:MimeMessage.getAllHeaders() returns two different classes in two different projects 【发布时间】:2015-05-04 07:55:51 【问题描述】:我有一个关于邮件的项目并且可以正常工作,但我创建了另一个项目,该项目也是关于邮件的,生成的 MimeMessage 无法在第一个项目中解析。
我研究了这些类,发现 MimeMessage 的头类之间的区别 两个项目都在使用
javax.mail.internet.MimeMessage
但我将标题记录为:
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
所有相关的类似乎都在 mail.jar 中。我正在使用 maven 来获取 jars,两个项目都将 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;
【问题讨论】:
如果从 cmets 正确理解您的真正问题:在某些 JavaMail 实现中,调用setRecipients(Message.RecipientType.TO, addr)
,其中 addr 是包含两个或多个逗号分隔地址的字符串,结果在多个“To:”标头中,而不是 MimeMessage 中的单个统一“To:”标头。对吗?
这正是我的问题 :) 很抱歉没有解决这个问题。
您说 servlet 容器提供 JavaMail,即使我在我的应用程序 ClassLoader 中放置所需版本的 JavaMail 也可能会忽略它并使用服务器环境提供的版本。在第一个项目中,我们使用定制版本的 tomcat,但在第二个项目中,我们在常规 tomcat 上运行。这可能是实际问题。如何强制 ClassLoader 从包而不是 tomcat 提供的包中加载 JavaMail。
顺便说一句,我错过了说 addr is javax.mail.Address[]
听起来定制的Tomcat在它的库目录中有一个更新的JavaMail,你的JavaMail可能有bug。考虑将您的依赖项更改为a more recent JavaMail version。
【参考方案1】:
这根本不是问题。 contract of the MimeMessage.getAllHeaders() method 很清楚:
将此消息中的所有标头作为 Header 对象的枚举返回。
该文档指的是javax.mail.Header 类。
因此,当您调用 MimeMessage.getAllHeaders() 时,只能假设 Enumeration 将返回 javax.mail.Header 的实例是安全的。它可能会或可能不会返回作为 Header 子类的对象,根据多态性的基本规则,这是完全有效的事情,只要调用代码可以安全地将它们视为 Header实例。
根据您运行程序的方式,您的 pom.xml 中的 JavaMail 版本可能无关紧要。在 Java EE 容器(如 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 检测枚举的结束是不正确的。它更慢、更难阅读,并且可能会无意中捕捉到编程错误,这使得调试变得相当困难。
【讨论】:
首先,感谢您的回答和附注:) 关于标题类型的问题是:当邮件有 2 个地址并且我使用 MimeMessage 的 writeTo 方法并将其写入 eml 文件时第一个项目将标头导出为:到:a@domain.com、b@domain.com 但第二个项目的 InternetHeader 导出标头有两行:到:a@domain.com 到:b@domain.com。与邮件服务器联系的实际项目是第一个项目,当它解析从第二个项目生成的 eml 文件时,它只需要第一个 To: 标头并忽略第二个收件人,我认为标头对此负责 考虑编辑您的问题以包含您在 MimeMessage 中设置收件人的代码。您可能还应该在问题中包含您的评论文本,因为这是您遇到的真正问题。 我寻找您关于 addr 的评论是字符串并包含一些用逗号分隔的地址,并尝试使用 String 调用 setRecipients 方法并且它有效。这是一种解决方法,但无论如何,它奏效了。以上是关于MimeMessage.getAllHeaders() 在两个不同的项目中返回两个不同的类的主要内容,如果未能解决你的问题,请参考以下文章