0

I have a project about mailing and works without problem but I created another project that is also about mailing generated MimeMessage cannot be parsed in first project.

I studied the classes and found difference between header class of MimeMessage Both projects are using

javax.mail.internet.MimeMessage

but I logged header as:

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;
    }

}

first project printed:

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

second project printed

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

all relevant classes seems like in mail.jar. I am using maven to get jars and both projects getting that jar as:

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

what can be the problem. is there any other dependent jars?

both projects are using same method. after code block below other parts of mime message are set but problem occurs here. code:

        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;
            }

        }
bdogru
  • 812
  • 1
  • 11
  • 19
  • If understand your real issue correctly from the comments: In some JavaMail implementations, calling `setRecipients(Message.RecipientType.TO, addr)`, where **addr** is a String containing two or more comma-separated addresses, results in multiple "To:" headers instead of a single unified "To:" header in the MimeMessage. Is that correct? – VGR Mar 04 '15 at 15:49
  • this is exactly my problem :) sorry for not clearing that out. – bdogru Mar 05 '15 at 08:34
  • You said servlet containers provide JavaMail and even if my put desired version of JavaMail within my application ClassLoader may ignore it and use the one provided by server environment. In first project we are using a customized version of tomcat, but in second project is run on a regular tomcat. This can be the actual problem. How can I force ClassLoader to load JavaMail from the package not the one provided by tomcat. – bdogru Mar 05 '15 at 08:40
  • by the way, I missed to say something addr is javax.mail.Address[] – bdogru Mar 05 '15 at 09:48
  • It sounds like the customized Tomcat has a newer JavaMail in its library directory, and your JavaMail may have a bug. Consider changing your dependency to [a more recent JavaMail version](http://mvnrepository.com/artifact/javax.mail/javax.mail-api/1.5.2). – VGR Mar 05 '15 at 13:06

1 Answers1

1

This isn't a problem at all. The contract of the MimeMessage.getAllHeaders() method is clear:

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

That documentation is referring to the javax.mail.Header class.

So when you call MimeMessage.getAllHeaders(), it is only safe to assume that the Enumeration will return instances of javax.mail.Header. It might or might not return objects which are a subclass of Header, which according to the basic rules of polymorphism, is a perfectly valid thing to do, as long as the calling code can safely treat them like Header instances.

Depending on how you run your program, the version of JavaMail in your pom.xml may be irrelevant. In Java EE containers (like GlassFish and JBoss) and servlet containers (like Tomcat), JavaMail is provided by the container, so even if you package your own version of JavaMail with your application, the ClassLoader may ignore it and unconditionally use the JavaMail provided by the server environment.

Side note: the correct way to loop through an Enumeration is with its hasMoreElements() method:

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

Even though using try/catch technically works, it is not correct to use try/catch to detect the end of an Enumeration. It is slower, harder to read, and may inadvertently catch programming errors, which makes debugging considerably harder.

VGR
  • 40,506
  • 4
  • 48
  • 63
  • first of all, thanks for your answer and the side note :) the problem about header type is that: when mail has 2 to addresses and I use writeTo method of MimeMessage and write it to an eml file first projects export header as: To: a@domain.com, b@domain.com but second project with InternetHeader export header with two rows as: To: a@domain.com To: b@domain.com. actual project with contact to mail server is first project and when it parse the eml file generated from the second project it only takes the first To: header and ignores the second recipient, I thought header is responsible for this – bdogru Mar 03 '15 at 18:32
  • Consider editing your question to include your code which sets the recipients in the MimeMessage. You probably also should include your comment's text in your question, as it is the real problem you are having. – VGR Mar 03 '15 at 18:49
  • I looked for your comment about addr to be string and containing some addresses seperated with comma and tried to call setRecipients method with String and it worked. It is kind a workaround but anyway, it worked. – bdogru Mar 09 '15 at 14:27