Announcement Announcement Module
Collapse
No announcement yet.
Problems sending MIME multipart mails Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Problems sending MIME multipart mails

    I created a simple bundle that sends a mail. I tried three different types:

    the org.springframework.mail.SimpleMailMessage is working OK.

    An MimeMessage without multipart is also OK.

    But when I created an MimeMessage with multipart. I get the following error when sending:

    Code:
    	public void sendMultipartMimeMail() {
    		MimeMessage message = m_mailSender.createMimeMessage();
    
    		try {
    			MimeMessageHelper helper;
    			helper = new MimeMessageHelper(message, true);
    			helper.setSubject("Mail");
    			helper.setText("You've got mail!", "<font color=\"red\">You've got</font> <font color=\"blue\">mail!</font>");
    			helper.setTo(m_mailAddress);
    			helper.setFrom(m_mailAddress);
    		} catch (MessagingException e) {
    			e.printStackTrace();
    		}
    		
    		m_mailSender.send(message);
    	}
    Code:
    org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.mail.MailSendException; nested exceptions (1) are:
    Failed message 1: javax.mail.MessagingException: IOException while sending message;
      nested exception is:
    	javax.activation.UnsupportedDataTypeException: no object DCH for MIME type multipart/mixed; 
    	boundary="----=_Part_0_22448089.1237451893603"
    	org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:583)
    	org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:501)
    	javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
    	javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
    I run from an Eclipse project with the dm server plugin on a fresh installed dmserver.
    Am I missing something?

  • #2
    What version of JDK you are using. I am assuming 1.6 and if I remember correctly Java Activation Framework is distributed with 1.6 (not in 1.5) which couses some class loading issue that results in this error.
    Could you possibly package your bundle(s) in the most stripped down version that replicates such scenario and attach it so we can take a look at it?
    Thanks

    Comment


    • #3
      Thanks for the reply.
      My JDK is 1.6u10 and SpringDM Server is version 1.0.2

      I attached the sources in a zip.

      Please fill in your host and email-address in hellomail-context.xml
      After compile and deploy there are three urls to check:
      http://localhost:8080/mail_web/simplemail.html (Simple)
      http://localhost:8080/mail_web/mimemail.html (Mime, no multipart)
      http://localhost:8080/mail_web/mimempmail.html (Mime, multipart)

      The first two work on my machine. The last one does not (see first post)

      Thanks in advance!

      Comment


      • #4
        OK,
        Here is how you solve it (short version)
        Change:
        Code:
        Import-Package: javax.mail,javax.mail.internet
        to
        Code:
        Import-Bundle: com.springsource.javax.mail;version="[1.4.0,1.4.0]"
        And here is some explanation.
        This error message are produced by JavaMail and is misleading. The real issue is that you have mismatched pair of activation.jar files available to your System bundle.
        Since you are using JDK 1.6 javax.activation package is available from your JRE (on my MAC it is classes.jar). In Spring DMServer it is also available in the Activation Bundle located in the lib directory under com.sprigsource.javax.activation-1.1.0.jar. This is done so if you run for example on JDK 1.5 which does not come with javax.activation, then the activation classes will be loaded from the Activation Bundle.
        What adds to the problem is that javax.activation package is exported twice as part of the org.osgi.framework.system.packages property (versioned and unversioned) which sort of like two instances of the exporter for the same package (OSGi actually creates two instances of ExportedPackage object).
        Code:
        org.osgi.framework.system.packages = \
         . . . . .
         javax.activation,\
         javax.activation;version="1.1.0",\
        What adds to the confusion is that because it is exported via org.osgi.framework.system.package the requests to load any activation classes will be delegated to the bootstrap loader anyway. (here is the result of the custom command i have in OSGi console showing which bundle can load the class)
        Code:
        osgi> wb javax.activation.DataHandler
        Package 'javax.activation' for javax.activation.DataHandler class is exported by:
        	org.eclipse.osgi-[0]: Bundle-Version: 3.4.2.R34x_v20080826-1230
        	org.eclipse.osgi-[0]: Bundle-Version: 3.4.2.R34x_v20080826-1230
        Class 'javax.activation.DataHandler' is visible by bundle [0] via bootstrap loader
        Class 'javax.activation.DataHandler' is visible by bundle [0] via bootstrap loader
         . . . . .
        So my guess it is a wiring problem between multiple exporters, when you need to be wired to the same exporter of Activation packages as you Mail bundle.

        Comment


        • #5
          Thanks for the explenation.

          It works for the demo bundle.

          But in our application it does not work yet..
          Could it be some classloading problem?

          Comment


          • #6
            Of course it could, anything is possible, but without details it is hard to speculate.

            Comment


            • #7
              Hmm.. OK

              I'll guess I will strip our application until it is working again and then rebuild it until it fails.

              Thanks for your help! I'm a step futher now.

              Comment


              • #8
                Issue found!

                I found the problem. We are using Wicket in our frontend.

                The fact is (I still have to find out why) that when calling the service that sends the mail the classloader context of the thread is com.springsource.server.servlet.tomcat.loader.Osgi WebappClassLoader I guess this classloader doesn't know about the javax.mail bundle

                Adding this line in the service solves the problem:
                Code:
                Thread.currentThread().setContextClassLoader(MailServiceImpl.class.getClassLoader());
                Ofcourse this is a very dirty way to solve it, but it explains what is going wrong. I will have to find a way to correct the classloadingcontext before calling the service.

                Comment


                • #9
                  Well, although i did figure out how to fix it, this issue was still bothering me, so I did a bit more digging and now I know exactly what is happening, so I am retracting (partially) what I said before (although it did fix the problem)
                  Many enterprise libraries utilize dynamic class loading capabilities of Java. In your particular case the classes in question belong to com.sun.mail.handlers.* package (e.g., com.sun.mail.handlers.multipart_mixed). These classes are loaded by Activation framework via couple of different means. The first attempt is via the ThreadContext class loader (TCCL). Here is the excerpt from MailcapCommandMap.getDataContentHandler(String name) method of Activation framework where name is "com.sun.mail.handlers.multipart_mixed"
                  Code:
                  ClassLoader cld = null;
                  // First try the "application's" class loader.
                  cld = SecuritySupport.getContextClassLoader();
                  . . . . 
                  cl = cld.loadClass(name);
                  The returned class loader is the class loader for the current bundle which is your bundle that sends email, which means that your bundle becomes responsible to locate this class. Since you are not explicitly importing the package com.sun.mail.handlers (and why should you? . . you don't care, know or should know. . .), this class can not be loaded by your bundle since it is not visible which results in CNFE. So, Activation framework catches CNFE and attempts to load the class via Class.forName(..)
                  Code:
                  . . . .
                  } catch (Exception ex) {
                  	// if anything goes wrong, do it the old way
                  	cl = Class.forName(name);
                  }
                  Well, although com.sun.* packages directed to be loaded by a bootstrap loader via bootdelegation option within the dmServer profile configuration, this particular one is not visible to the bootstrap loader either, since it is not on the boot class-path resulting in another CNFE, which is unfortunately swallowed by Activation code and converted to a simple hard-to-spot log message:
                  Code:
                  } catch (ClassNotFoundException e) {
                  	if (LogSupport.isLoggable())
                  	LogSupport.log("Can't load DCH " + name, e);
                  This results in the DataContentHandler for your MIME type being null which is the root of your exception.
                  So where are those classes?
                  Well com.sun.mail.handler package is explicitly exported by the JavaMail bundle just like javax.mail and javax.mail.internet. But in case of javax.mail.* packages which you are explicitly using and thus have to import, you do not have direct dependency on com.sun.mail.handlers package so you are not importing it explicitly so your bundle simply doesn't see it.
                  Now, when you use Import-Bundle directive instead of Import-Package, dmServer pipeline will dynamically expand Import-Bundle directive into Import-Package directive importing all packages exported by the underlying bundle, which results in the dynamically generated runtime version of the MANIFEST for your bundle which now contains an explicit Import-Package com.sun.mail.handlers
                  You can clearly see it if you execute "headers <bundle_id>" command in the OSGi console.
                  For example:
                  Here is what your runtime MANIFEST will look like if you have Import-Bundle: com.springsource.javax.mail (cut down for simplicity):
                  Code:
                  . . .
                  Import-Package = org.springframework.asm;bundle-version="2.5.6.A";bundle-symbolic-name="org.springframework.core";version="2.5.6.A",org.springframework.orm.jpa;bundle-version="2.5.6.A";bundle-symbolic-name="org.springframe. . . .com.sun.mail.handlers;bundle-symbolic-name="com.springsource.javax.mail";bundle-version="1.4.0"; . . . . . .
                  And if you execute the same command when your bundle is deployed with Import-Package: javax.mail,javax.mail.internet you will not see com.sun.mail.handlers in your dynamically generated Import-Package header.

                  So IMHO, the root issue is really in the Activation framework which doesn't handle the exception properly. If you saw CNFE on com.sun.mail.handlers.multipart_mixed, things would be much simpler to figure out and fix :-)
                  Cheers!
                  Last edited by oleg.zhurakousky; Mar 21st, 2009, 11:24 AM.

                  Comment


                  • #10
                    UnsupportedDataTypeException

                    Hi Oleg,
                    I am also facing similar kind problem. In my case ,I have extracted the source code of mail.jar and activation.jar with my application. I want my application to refer to my extracted activation not to the one that is distributed with jre1.6.What is your suggestion to overcome this problem?

                    Thanks in advance,
                    Champak

                    Comment


                    • #11
                      Java mail is not part of the JDK so you are OK there
                      Java activation was folded into JDK 1.6 so I am not sure that's possible unless you physically start messing with JVM distribution and remove data from their JAR files. In any event I haven't tried that.

                      Comment


                      • #12
                        Hi Oleg,
                        I apologize as I missed out about java activation on previous post.I also have the source code of javax.activation package on this application.On top of that , I also have another jar having javax.activation in my application.
                        But this probleam happens only with jre1.6 as we have our application running both on 1.5 and 1.6. This may be a consequence of class load reslove problem as you discussed with your earlier reply.
                        I am trying with the import bundle of your other solution.Please let me know of any other solution.I will also publish the the result of my import bundle solution.

                        Comment


                        • #13
                          I'm still having this problem... I thought I got passed it but it's still happening:
                          Code:
                          javax.mail.MessagingException: IOException while sending message;
                            nested exception is:
                                  javax.activation.UnsupportedDataTypeException: no object DCH for MIME type text/plain; charset=us-ascii
                                  at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:625)
                                  at org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:403)
                                  at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:308)
                                  at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:297)
                                  at com.nbs.alerter.impl.AlertServiceImpl.sendAlert(AlertServiceImpl.java:108)
                                  at com.nbs.alerter.impl.AlertServiceImpl.access$3(AlertServiceImpl.java:96)
                                  at com.nbs.alerter.impl.AlertServiceImpl$MailThread.run(AlertServiceImpl.java:173)
                                  at java.lang.Thread.run(Thread.java:619)
                          Caused by: javax.activation.UnsupportedDataTypeException: no object DCH for MIME type text/plain; charset=us-ascii
                                  at javax.activation.ObjectDataContentHandler.writeTo(DataHandler.java:870)
                                  at javax.activation.DataHandler.writeTo(DataHandler.java:301)
                                  at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:1350)
                                  at javax.mail.internet.MimeMessage.writeTo(MimeMessage.java:1683)
                                  at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:585)
                                  ... 7 more
                          This is on Java 6. I'm deploying the application as separate bundles w/o a PAR. Only one bundle is sending out the emails and that's the bundle that has the imports:
                          Code:
                          Import-Library: org.springframework.spring;version="[2.5.6.A,2.5.6.A]"
                          Import-Package: org.apache.commons.logging;version="[1.1.1,1.1.1]"
                          Import-Bundle: com.springsource.javax.mail;version="[1.4.0,1.4.0]"
                          What could be the problem? I was playing around with the imports before I saw this thread, but I didn't get anywhere.

                          Comment


                          • #14
                            This problem went away when I upgraded to a newer update of the Java 6 JDK

                            Comment

                            Working...
                            X