commits@javamail.java.net

[javamail~mercurial:262] Add SMTPSenderFailedException to indicate problems with sender address.

From: <shannon_at_kenai.com>
Date: Thu, 4 Feb 2010 00:13:33 +0000

Project: javamail
Repository: mercurial
Revision: 262
Author: shannon
Date: 2010-02-03 23:00:42 UTC
Link:

Log Message:
------------
Add mail.mime.contentypehandler System property, to clean Content-Type.
Updated MailHandlerTest from Jason; use JDK 5 and JUnit 4.
@Override doesn't work for interfaces in JDK 1.5.
Add mail.mime.allowencodedmessages System property, to work around bug
in Microsoft Outlook.
Add SASL support to SMTP provider.
javax.mail.internet.MimeMessage.addFrom() violates RFC2822 - bug 5057742
Improve POP3 locking - make some fields volatile and make some methods private.
Fxies and improvements to mbox to allow it to pass the TCK.
Significantly improve mbox performance. Now faster than mailx!
Allow property name to wrap.
Fix typos in javadocs.
Remove deprecated <aggregate> attribute.
Updates from Jason:

MailHandler fixed empty multipart bug.
MailHandler create descriptive error string for Message.writeTo exceptions.
MailHandlerTest check for empty multiparts.
MailHandlerTest test for MailHandler subclass.
MailHandlerTest check that pushFilter, comparator allow for null.
MailHandlerTest upgrade to JUnit 4.5
Add SMTPSenderFailedException to indicate problems with sender address.


Revisions:
----------
249
250
251
252
253
254
255
256
257
258
259
260
261
262


Modified Paths:
---------------
doc/release/CHANGES.txt
mail/src/main/java/javax/mail/internet/MimeBodyPart.java
mail/src/main/java/javax/mail/internet/MimeMessage.java
mail/src/main/java/javax/mail/internet/package.html
mail/src/test/java/com/sun/mail/test/ClassLoaderSuite.java
mail/src/test/java/com/sun/mail/util/logging/MailHandlerTest.java
mail/src/main/java/javax/mail/internet/MimePartDataSource.java
mail/src/main/java/com/sun/mail/smtp/SMTPTransport.java
mail/src/main/java/com/sun/mail/smtp/package.html
mail/src/main/java/com/sun/mail/util/ASCIIUtility.java
pom.xml
mail/src/main/java/com/sun/mail/pop3/POP3Folder.java
mbox/src/main/java/com/sun/mail/mbox/MboxFolder.java
mbox/src/main/java/com/sun/mail/mbox/MboxMessage.java
mbox/src/main/java/com/sun/mail/mbox/MboxStore.java
mbox/src/main/java/com/sun/mail/mbox/SolarisMailbox.java
mbox/src/main/java/com/sun/mail/mbox/UNIXFile.java
mail/src/main/java/com/sun/mail/imap/package.html
mail/src/main/java/com/sun/mail/util/MailSSLSocketFactory.java
javadoc/pom.xml
mail/src/main/java/com/sun/mail/util/logging/MailHandler.java


Added Paths:
------------
mail/src/main/java/com/sun/mail/util/MimeUtil.java
mail/src/test/java/com/sun/mail/util/ContentTypeCleaner.java
mail/src/test/java/com/sun/mail/util/MimeUtilTestSuite.java
mail/src/test/java/javax/mail/internet/AllowEncodedMessages.java
mail/src/test/java/javax/mail/internet/MimeMessageTestSuite.java
mail/src/main/java/com/sun/mail/smtp/SMTPSaslAuthenticator.java
mail/src/main/java/com/sun/mail/smtp/SaslAuthenticator.java
mail/src/test/java/javax/mail/internet/AddFromTest.java
mbox/src/main/java/com/sun/mail/mbox/MessageLoader.java
mbox/src/main/java/com/sun/mail/mbox/TempFile.java
mail/src/main/java/com/sun/mail/smtp/SMTPSenderFailedException.java


Diffs:
------
diff -r bdb9049c8238 -r b55a9080af1e doc/release/CHANGES.txt
--- a/doc/release/CHANGES.txt Fri Jan 15 17:36:36 2010 -0800
+++ b/doc/release/CHANGES.txt Wed Jan 20 13:04:25 2010 -0800
@@ -30,6 +30,7 @@
 <no id> add mail.pop3.filecache.enable property for caching messages in tmp file
 <no id> add mail.mime.ignorewhitespacelines property, default false
 <no id> add support for IMAP UNSELECT command
+<no id> add mail.mime.contentypehandler System property, to clean Content-Type
 
 
                   CHANGES IN THE 1.4.3 RELEASE

diff -r bdb9049c8238 -r b55a9080af1e mail/src/main/java/com/sun/mail/util/MimeUtil.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mail/src/main/java/com/sun/mail/util/MimeUtil.java Wed Jan 20 13:04:25 2010 -0800
@@ -0,0 +1,115 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License"). You
+ * may not use this file except in compliance with the License. You can obtain
+ * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
+ * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
+ * Sun designates this particular file as subject to the "Classpath" exception
+ * as provided by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the License
+ * Header, with the fields enclosed by brackets [] replaced by your own
+ * identifying information: "Portions Copyrighted [year]
+ * [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above. However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+
+package com.sun.mail.util;
+
+import java.lang.reflect.*;
+import java.security.*;
+
+import javax.mail.internet.MimePart;
+
+/**
+ * General MIME-related utility methods.
+ *
+ * @author Bill Shannon
+ * @since JavaMail 1.4.4
+ */
+public class MimeUtil {
+
+ private static final Method cleanContentType;
+
+ static {
+ Method meth = null;
+ try {
+ String cth = System.getProperty("mail.mime.contenttypehandler");
+ if (cth != null) {
+ ClassLoader cl = getContextClassLoader();
+ Class clsHandler = null;
+ if (cl != null) {
+ try {
+ clsHandler = Class.forName(cth, false, cl);
+ } catch (ClassNotFoundException cex) { }
+ }
+ if (clsHandler == null)
+ clsHandler = Class.forName(cth);
+ meth = clsHandler.getMethod("cleanContentType",
+ new Class[] { MimePart.class, String.class });
+ }
+ } catch (Exception ex) {
+ // ignore it
+ } finally {
+ cleanContentType = meth;
+ }
+ }
+
+ // No one should instantiate this class.
+ private MimeUtil() {
+ }
+
+ /**
+ * If a Content-Type handler has been specified,
+ * call it to clean up the Content-Type value.
+ */
+ public static String cleanContentType(MimePart mp, String contentType) {
+ if (cleanContentType != null) {
+ try {
+ return (String)cleanContentType.invoke(null,
+ new Object[] { mp, contentType });
+ } catch (Exception ex) {
+ return contentType;
+ }
+ } else
+ return contentType;
+ }
+
+ /**
+ * Convenience method to get our context class loader.
+ * Assert any privileges we might have and then call the
+ * Thread.getContextClassLoader method.
+ */
+ private static ClassLoader getContextClassLoader() {
+ return (ClassLoader)
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ ClassLoader cl = null;
+ try {
+ cl = Thread.currentThread().getContextClassLoader();
+ } catch (SecurityException ex) { }
+ return cl;
+ }
+ });
+ }
+}

diff -r bdb9049c8238 -r b55a9080af1e mail/src/main/java/javax/mail/internet/MimeBodyPart.java
--- a/mail/src/main/java/javax/mail/internet/MimeBodyPart.java Fri Jan 15 17:36:36 2010 -0800
+++ b/mail/src/main/java/javax/mail/internet/MimeBodyPart.java Wed Jan 20 13:04:25 2010 -0800
@@ -255,9 +255,9 @@
      */
     public String getContentType() throws MessagingException {
         String s = getHeader("Content-Type", null);
+ s = MimeUtil.cleanContentType(this, s);
         if (s == null)
             s = "text/plain";
-
         return s;
     }
 
@@ -1132,6 +1132,7 @@
         if (filename == null) {
             // Still no filename ? Try the "name" ContentType parameter
             s = part.getHeader("Content-Type", null);
+ s = MimeUtil.cleanContentType(part, s);
             if (s != null) {
                 try {
                     ContentType ct = new ContentType(s);
@@ -1172,6 +1173,7 @@
          */
         if (setContentTypeFileName) {
             s = part.getHeader("Content-Type", null);
+ s = MimeUtil.cleanContentType(part, s);
             if (s != null) {
                 try {
                     ContentType cType = new ContentType(s);

diff -r bdb9049c8238 -r b55a9080af1e mail/src/main/java/javax/mail/internet/MimeMessage.java
--- a/mail/src/main/java/javax/mail/internet/MimeMessage.java Fri Jan 15 17:36:36 2010 -0800
+++ b/mail/src/main/java/javax/mail/internet/MimeMessage.java Wed Jan 20 13:04:25 2010 -0800
@@ -939,6 +939,7 @@
      */
     public String getContentType() throws MessagingException {
         String s = getHeader("Content-Type", null);
+ s = MimeUtil.cleanContentType(this, s);
         if (s == null)
             return "text/plain";
         return s;

diff -r bdb9049c8238 -r b55a9080af1e mail/src/main/java/javax/mail/internet/package.html
--- a/mail/src/main/java/javax/mail/internet/package.html Fri Jan 15 17:36:36 2010 -0800
+++ b/mail/src/main/java/javax/mail/internet/package.html Wed Jan 20 13:04:25 2010 -0800
@@ -401,6 +401,30 @@
 </TR>
 
 <TR>
+<TD>mail.mime.contenttypehandler</TD>
+<TD>String</TD>
+<TD>
+In some cases JavaMail is unable to process messages with an invalid
+Content-Type header. The header may have incorrect syntax or other
+problems. This property specifies the name of a class that will be
+used to clean up the Content-Type header value before JavaMail uses it.
+The class must have a method with this signature:
+<CODE>public static String cleanContentType(MimePart mp, String contentType)</CODE>
+Whenever JavaMail accesses the Content-Type header of a message, it
+will pass the value to this method and use the returned value instead.
+The value may be null if the Content-Type header isn't present.
+Returning null will cause the default Content-Type to be used.
+The MimePart may be used to access other headers of the message part
+to determine how to correct the Content-Type.
+Note that the Content-Type handler doesn't affect the
+<CODE>getHeader</CODE> method, which still returns the raw header value.
+Note also that the handler doesn't affect the IMAP provider; the IMAP
+server is responsible for returning pre-parsed, syntactically correct
+Content-Type information.
+</TD>
+</TR>
+
+<TR>
 <TD>mail.alternates</TD>
 <TD>String</TD>
 <TD>

diff -r bdb9049c8238 -r b55a9080af1e mail/src/test/java/com/sun/mail/test/ClassLoaderSuite.java
--- a/mail/src/test/java/com/sun/mail/test/ClassLoaderSuite.java Fri Jan 15 17:36:36 2010 -0800
+++ b/mail/src/test/java/com/sun/mail/test/ClassLoaderSuite.java Wed Jan 20 13:04:25 2010 -0800
@@ -1,7 +1,7 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009-2010 Sun Microsystems, Inc. All rights reserved.
  *
  * The contents of this file are subject to the terms of either the GNU
  * General Public License Version 2 only ("GPL") or the Common Development
@@ -44,8 +44,11 @@
 import java.util.ArrayList;
 
 import org.junit.runners.Suite;
+import org.junit.runners.ParentRunner;
 import org.junit.runners.model.InitializationError;
 import org.junit.runners.model.RunnerBuilder;
+import org.junit.runner.Runner;
+import org.junit.runner.notification.RunNotifier;
 
 /**
  * A special test suite that loads each of the test classes
@@ -103,6 +106,9 @@
                                     throws ClassNotFoundException {
             Class<?> c = null;
             try {
+ c = findLoadedClass(name);
+ if (c != null)
+ return c;
                 c = findClass(name);
                 if (resolve)
                     resolveClass(c);
@@ -123,6 +129,25 @@
     }
 
     /**
+ * Set the thread's context class loader to the class loader
+ * for the test class.
+ */
+ @Override
+ protected void runChild(Runner runner, RunNotifier notifier) {
+ // XXX - is it safe to assume it's always a ParentRunner?
+ ParentRunner pr = (ParentRunner)runner;
+ ClassLoader cl = null;
+ try {
+ cl = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(
+ pr.getTestClass().getJavaClass().getClassLoader());
+ super.runChild(runner, notifier);
+ } finally {
+ Thread.currentThread().setContextClassLoader(cl);
+ }
+ }
+
+ /**
      * Get the value of the SuiteClasses annotation.
      */
     private static Class<?>[] getSuiteClasses(Class<?> klass)

diff -r bdb9049c8238 -r b55a9080af1e mail/src/test/java/com/sun/mail/util/ContentTypeCleaner.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mail/src/test/java/com/sun/mail/util/ContentTypeCleaner.java Wed Jan 20 13:04:25 2010 -0800
@@ -0,0 +1,128 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License"). You
+ * may not use this file except in compliance with the License. You can obtain
+ * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
+ * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
+ * Sun designates this particular file as subject to the "Classpath" exception
+ * as provided by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the License
+ * Header, with the fields enclosed by brackets [] replaced by your own
+ * identifying information: "Portions Copyrighted [year]
+ * [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above. However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+
+package com.sun.mail.util;
+
+import java.io.OutputStream;
+import java.io.StringBufferInputStream;
+import java.util.Properties;
+
+import javax.mail.Session;
+import javax.mail.MessagingException;
+import javax.mail.BodyPart;
+import javax.mail.internet.MimePart;
+import javax.mail.internet.MimeMessage;
+import javax.mail.internet.MimeMultipart;
+
+import org.junit.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test the "mail.mime.contenttypehandler" property.
+ */
+public class ContentTypeCleaner {
+
+ private static Session s = Session.getInstance(new Properties());
+
+ @BeforeClass
+ public static void before() {
+ System.out.println("ContentTypeCleaner");
+ System.setProperty("mail.mime.contenttypehandler",
+ ContentTypeCleaner.class.getName());
+ }
+
+ @Test
+ public void testGarbage() throws Exception {
+ MimeMessage m = createMessage();
+ MimeMultipart mp = (MimeMultipart)m.getContent();
+ BodyPart bp = mp.getBodyPart(0);
+ assertEquals("text/plain", bp.getContentType());
+ assertEquals("first part\n", bp.getContent());
+ }
+
+ @Test
+ public void testValid() throws Exception {
+ MimeMessage m = createMessage();
+ MimeMultipart mp = (MimeMultipart)m.getContent();
+ BodyPart bp = mp.getBodyPart(1);
+ assertEquals("text/plain; charset=iso-8859-1", bp.getContentType());
+ assertEquals("second part\n", bp.getContent());
+ }
+
+ @Test
+ public void testEmpty() throws Exception {
+ MimeMessage m = createMessage();
+ MimeMultipart mp = (MimeMultipart)m.getContent();
+ BodyPart bp = mp.getBodyPart(2);
+ assertEquals("text/plain", bp.getContentType());
+ assertEquals("third part\n", bp.getContent());
+ }
+
+ public static String cleanContentType(MimePart mp, String contentType) {
+ if (contentType == null)
+ return null;
+ if (contentType.equals("complete garbage"))
+ return "text/plain";
+ return contentType;
+ }
+
+ private static MimeMessage createMessage() throws MessagingException {
+ String content =
+ "Mime-Version: 1.0\n" +
+ "Subject: Example\n" +
+ "Content-Type: multipart/mixed; boundary=\"-\"\n" +
+ "\n" +
+ "preamble\n" +
+ "---\n" +
+ "Content-Type: complete garbage\n" +
+ "\n" +
+ "first part\n" +
+ "\n" +
+ "---\n" +
+ "Content-Type: text/plain; charset=iso-8859-1\n" +
+ "\n" +
+ "second part\n" +
+ "\n" +
+ "---\n" +
+ "\n" +
+ "third part\n" +
+ "\n" +
+ "-----\n";
+
+ return new MimeMessage(s, new StringBufferInputStream(content));
+ }
+}

diff -r bdb9049c8238 -r b55a9080af1e mail/src/test/java/com/sun/mail/util/MimeUtilTestSuite.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mail/src/test/java/com/sun/mail/util/MimeUtilTestSuite.java Wed Jan 20 13:04:25 2010 -0800
@@ -0,0 +1,54 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License"). You
+ * may not use this file except in compliance with the License. You can obtain
+ * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
+ * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
+ * Sun designates this particular file as subject to the "Classpath" exception
+ * as provided by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the License
+ * Header, with the fields enclosed by brackets [] replaced by your own
+ * identifying information: "Portions Copyrighted [year]
+ * [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above. However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+
+package com.sun.mail.util;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite.SuiteClasses;
+
+import com.sun.mail.test.ClassLoaderSuite;
+import com.sun.mail.test.ClassLoaderSuite.TestClass;
+
+/**
+ * Suite of MimeUtil tests that need to be run in a separate class loader.
+ */
+_at_RunWith(ClassLoaderSuite.class)
+_at_TestClass(MimeUtil.class)
+_at_SuiteClasses( {
+ ContentTypeCleaner.class
+})
+public class MimeUtilTestSuite {
+}


diff -r b55a9080af1e -r f54627376385 mail/src/test/java/com/sun/mail/util/logging/MailHandlerTest.java
--- a/mail/src/test/java/com/sun/mail/util/logging/MailHandlerTest.java Wed Jan 20 13:04:25 2010 -0800
+++ b/mail/src/test/java/com/sun/mail/util/logging/MailHandlerTest.java Wed Jan 20 13:24:57 2010 -0800
@@ -34,7 +34,6 @@
  * only if the new code is made subject to such option by the copyright
  * holder.
  */
-
 package com.sun.mail.util.logging;
 
 import java.lang.reflect.*;
@@ -46,24 +45,29 @@
 import java.util.logging.*;
 import javax.mail.*;
 import javax.mail.internet.*;
-import junit.framework.TestCase;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.junit.Assert.*;
 
 /**
  * Test case for the MailHandler spec.
  * @author Jason Mehrens
  */
-public class MailHandlerTest extends TestCase {
+public class MailHandlerTest {
 
- public MailHandlerTest(String testName) {
- super(testName);
+ @BeforeClass
+ public static void setUpClass() throws Exception {
+ assertTrue(MailHandlerTest.class.desiredAssertionStatus());
     }
 
- protected void setUp() throws Exception {
- super.setUp();
+ @AfterClass
+ public static void tearDownClass() throws Exception {
+ assertTrue(MailHandlerTest.class.desiredAssertionStatus());
     }
 
+ @Test
     public void testIsLoggable() {
- //System.out.println("isLoggable");
         Level[] lvls = getAllLevels();
         if (lvls.length > 0) {
             LogRecord record = new LogRecord(Level.INFO, "");
@@ -123,9 +127,8 @@
         assertEquals(em.exceptions.isEmpty(), true);
     }
 
+ @Test
     public void testPublish() {
- //System.out.println("publish");
-
         MailHandler instance = createHandlerWithRecords();
         InternalErrorManager em = (InternalErrorManager) instance.getErrorManager();
         assertEquals(em.exceptions.isEmpty(), true);
@@ -138,11 +141,12 @@
         instance = createHandlerWithRecords();
         instance.setErrorManager(new MessageErrorManager(instance) {
 
+ @Override
             protected void error(MimeMessage message, Throwable t, int code) {
                 try {
                     assertTrue(null != message.getSentDate());
- assertTrue(message.getHeader("X-Priority") == null ||
- message.getHeader("X-Priority").length == 0);
+ assertTrue(message.getHeader("X-Priority") == null
+ || message.getHeader("X-Priority").length == 0);
                     message.saveChanges();
                 } catch (MessagingException ME) {
                     fail(ME.toString());
@@ -179,6 +183,7 @@
         return instance;
     }
 
+ @Test
     public void testBadFormatters() {
         MailHandler instance = new MailHandler();
         instance.setLevel(Level.ALL);
@@ -202,6 +207,7 @@
         assertEquals(true, !em.exceptions.isEmpty());
     }
 
+ @Test
     public void testBadFilters() {
         LogRecord record = new LogRecord(Level.INFO, "");
         ConsoleHandler console = new ConsoleHandler();
@@ -250,8 +256,8 @@
         assertEquals(true, !em.exceptions.isEmpty());
     }
 
+ @Test
     public void testPushInsidePush() {
- //System.out.println("PushInsidePush");
         Level[] lvls = getAllLevels();
 
         MailHandler instance = new MailHandler(lvls.length + 2);
@@ -268,7 +274,9 @@
 
         instance.setFormatter(new SimpleFormatter() {
 
+ @Override
             public String getHead(Handler h) {
+ assert h instanceof MailHandler : h;
                 try {
                     h.flush();
                 } catch (Throwable T) {
@@ -277,7 +285,9 @@
                 return super.getHead(h);
             }
 
+ @Override
             public String getTail(Handler h) {
+ assert h instanceof MailHandler : h;
                 final Filter filter = h.getFilter();
                 try {
                     h.setFilter(filter);
@@ -319,7 +329,9 @@
 
         Formatter push = new SimpleFormatter() {
 
+ @Override
             public String getHead(Handler h) {
+ assert h instanceof MailHandler : h;
                 try {
                     ((MailHandler) h).push();
                 } catch (Throwable T) {
@@ -328,7 +340,9 @@
                 return super.getHead(h);
             }
 
+ @Override
             public String getTail(Handler h) {
+ assert h instanceof MailHandler : h;
                 try {
                     ((MailHandler) h).push();
                 } catch (Throwable T) {
@@ -340,7 +354,9 @@
 
         Formatter atFor = new SimpleFormatter() {
 
+ @Override
             public String getHead(Handler h) {
+ assert h instanceof MailHandler : h;
                 MailHandler mh = (MailHandler) h;
                 Formatter[] f = mh.getAttachmentFormatters();
                 try {
@@ -353,6 +369,7 @@
                 return super.getHead(h);
             }
 
+ @Override
             public String getTail(Handler h) {
                 getHead(h);
                 return super.getTail(h);
@@ -361,7 +378,9 @@
 
         Formatter atName = new SimpleFormatter() {
 
+ @Override
             public String getHead(Handler h) {
+ assert h instanceof MailHandler : h;
                 MailHandler mh = (MailHandler) h;
                 Formatter[] f = mh.getAttachmentNames();
                 try {
@@ -374,6 +393,7 @@
                 return super.getHead(h);
             }
 
+ @Override
             public String getTail(Handler h) {
                 getHead(h);
                 return super.getTail(h);
@@ -382,7 +402,9 @@
 
         Formatter atFilter = new SimpleFormatter() {
 
+ @Override
             public String getHead(Handler h) {
+ assert h instanceof MailHandler;
                 MailHandler mh = (MailHandler) h;
                 Filter[] f = mh.getAttachmentFilters();
                 try {
@@ -395,6 +417,7 @@
                 return super.getHead(h);
             }
 
+ @Override
             public String getTail(Handler h) {
                 getHead(h);
                 return super.getTail(h);
@@ -403,7 +426,9 @@
 
         Formatter nameComp = new Formatter() {
 
+ @Override
             public String getHead(Handler h) {
+ assert h instanceof MailHandler : h;
                 MailHandler mh = (MailHandler) h;
                 Comparator c = mh.getComparator();
                 try {
@@ -416,10 +441,12 @@
                 return super.getHead(h);
             }
 
+ @Override
             public String format(LogRecord r) {
                 return "";
             }
 
+ @Override
             public String getTail(Handler h) {
                 getHead(h);
                 return "name.txt";
@@ -428,7 +455,9 @@
 
         Formatter nameMail = new Formatter() {
 
+ @Override
             public String getHead(Handler h) {
+ assert h instanceof MailHandler : h;
                 MailHandler mh = (MailHandler) h;
                 Properties props = mh.getMailProperties();
                 try {
@@ -441,10 +470,12 @@
                 return super.getHead(h);
             }
 
+ @Override
             public String format(LogRecord r) {
                 return "";
             }
 
+ @Override
             public String getTail(Handler h) {
                 getHead(h);
                 return "name.txt";
@@ -453,7 +484,9 @@
 
         Formatter nameSub = new Formatter() {
 
+ @Override
             public String getHead(Handler h) {
+ assert h instanceof MailHandler : h;
                 MailHandler mh = (MailHandler) h;
                 Formatter f = mh.getSubject();
                 try {
@@ -466,10 +499,12 @@
                 return super.getHead(h);
             }
 
+ @Override
             public String format(LogRecord r) {
                 return "";
             }
 
+ @Override
             public String getTail(Handler h) {
                 getHead(h);
                 return "name.txt";
@@ -478,7 +513,9 @@
 
         Formatter nameAuth = new Formatter() {
 
+ @Override
             public String getHead(Handler h) {
+ assert h instanceof MailHandler : h;
                 MailHandler mh = (MailHandler) h;
                 Authenticator a = mh.getAuthenticator();
                 try {
@@ -491,10 +528,12 @@
                 return super.getHead(h);
             }
 
+ @Override
             public String format(LogRecord r) {
                 return "";
             }
 
+ @Override
             public String getTail(Handler h) {
                 getHead(h);
                 return "name.txt";
@@ -514,13 +553,14 @@
         }
     }
 
+ @Test
     public void testPush() {
- //System.out.println("push");
         MailHandler instance = new MailHandler();
         InternalErrorManager em = new InternalErrorManager();
         instance.setErrorManager(em);
         instance.push();
         assertEquals(true, em.exceptions.isEmpty());
+ instance.close();
 
         instance = createHandlerWithRecords();
         em = (InternalErrorManager) instance.getErrorManager();
@@ -528,6 +568,7 @@
 
         assertEquals(1, em.exceptions.size());
         assertEquals(true, em.exceptions.get(0) instanceof MessagingException);
+ instance.close();
 
         //Test for valid message.
         instance = createHandlerWithRecords();
@@ -536,14 +577,15 @@
         instance.close();
     }
 
+ @Test
     public void testFlush() {
- //System.out.println("flush");
         MailHandler instance = new MailHandler();
         InternalErrorManager em = new InternalErrorManager();
         instance.setErrorManager(em);
         instance.flush();
 
         assertEquals(true, em.exceptions.isEmpty());
+ instance.close();
 
         instance = createHandlerWithRecords();
         em = (InternalErrorManager) instance.getErrorManager();
@@ -551,16 +593,18 @@
 
         assertEquals(1, em.exceptions.size());
         assertEquals(true, em.exceptions.get(0) instanceof MessagingException);
+ instance.close();
 
         //Test for valid message.
         instance = createHandlerWithRecords();
         instance.setErrorManager(new MessageErrorManager(instance) {
 
+ @Override
             protected void error(MimeMessage message, Throwable t, int code) {
                 try {
                     assertTrue(null != message.getSentDate());
- assertTrue(message.getHeader("X-Priority") == null ||
- message.getHeader("X-Priority").length == 0);
+ assertTrue(message.getHeader("X-Priority") == null
+ || message.getHeader("X-Priority").length == 0);
                     message.saveChanges();
                 } catch (MessagingException ME) {
                     fail(ME.toString());
@@ -571,8 +615,8 @@
         instance.close();
     }
 
+ @Test
     public void testClose() {
- //System.out.println("close");
         LogRecord record = new LogRecord(Level.INFO, "");
         MailHandler instance = new MailHandler();
         InternalErrorManager em = new InternalErrorManager();
@@ -606,11 +650,12 @@
         instance = createHandlerWithRecords();
         instance.setErrorManager(new MessageErrorManager(instance) {
 
+ @Override
             protected void error(MimeMessage message, Throwable t, int code) {
                 try {
                     assertTrue(null != message.getSentDate());
- assertTrue(message.getHeader("X-Priority") == null ||
- message.getHeader("X-Priority").length == 0);
+ assertTrue(message.getHeader("X-Priority") == null
+ || message.getHeader("X-Priority").length == 0);
                     message.saveChanges();
                 } catch (MessagingException ME) {
                     fail(ME.toString());
@@ -620,8 +665,8 @@
         instance.close();
     }
 
- public void testLevel() {
- //System.out.println("Level");
+ @Test
+ public void testLevel() {
         MailHandler instance = new MailHandler();
         InternalErrorManager em = new InternalErrorManager();
         instance.setErrorManager(em);
@@ -650,8 +695,8 @@
         assertEquals(true, em.exceptions.isEmpty());
     }
 
+ @Test
     public void testPushLevel() {
- //System.out.println("PushLevel");
         MailHandler instance = new MailHandler();
         InternalErrorManager em = new InternalErrorManager();
         instance.setErrorManager(em);
@@ -680,12 +725,19 @@
         assertEquals(true, em.exceptions.isEmpty());
     }
 
+ @Test
     public void testPushFilter() {
- //System.out.println("PushFilter");
         MailHandler instance = new MailHandler();
         InternalErrorManager em = new InternalErrorManager();
         instance.setErrorManager(em);
 
+ try {
+ instance.setPushFilter(null);
+ } catch (RuntimeException RE) {
+ fail(RE.toString());
+ }
+ assertNull(instance.getPushFilter());
+
         instance.setPushFilter(BooleanFilter.TRUE);
         assertEquals(BooleanFilter.TRUE, instance.getPushFilter());
 
@@ -700,12 +752,19 @@
         instance.close();
     }
 
+ @Test
     public void testComparator() {
- //System.out.println("Comparator");
         MailHandler instance = new MailHandler();
         InternalErrorManager em = new InternalErrorManager();
         instance.setErrorManager(em);
 
+ try {
+ instance.setComparator(null);
+ } catch (RuntimeException RE) {
+ fail(RE.toString());
+ }
+ assertNull(instance.getComparator());
+
         Comparator uselessComparator = new UselessComparator();
         Comparator result = instance.getComparator();
         assertEquals(false, uselessComparator.equals(result));
@@ -716,11 +775,11 @@
         assertEquals(true, uselessComparator.equals(result));
 
         assertEquals(true, em.exceptions.isEmpty());
+ instance.close();
     }
 
+ @Test
     public void testCapacity() {
- //System.out.println("Capacity");
-
         try {
             new MailHandler(-1);
             fail("Negative capacity was allowed.");
@@ -756,11 +815,11 @@
         result = instance.getCapacity();
         assertEquals(expResult, result);
         assertEquals(true, em.exceptions.isEmpty());
+ instance.close();
     }
 
+ @Test
     public void testAuthenticator() {
- //System.out.println("Authenticator");
-
         Authenticator auth = new EmptyAuthenticator();
 
         MailHandler instance = new MailHandler();
@@ -768,6 +827,12 @@
         instance.setErrorManager(em);
 
         try {
+ instance.setAuthenticator(null);
+ } catch (RuntimeException RE) {
+ fail(RE.toString());
+ }
+
+ try {
             instance.setAuthenticator(instance.getAuthenticator());
         } catch (RuntimeException RE) {
             fail(RE.toString());
@@ -791,8 +856,8 @@
         assertEquals(true, em.exceptions.get(0) instanceof MessagingException);
     }
 
+ @Test
     public void testMailProperties() {
- //System.out.println("MailProperties");
         Properties props = new Properties();
         MailHandler instance = new MailHandler();
         InternalErrorManager em = new InternalErrorManager();
@@ -833,8 +898,8 @@
         assertEquals(false, em.exceptions.isEmpty());
     }
 
+ @Test
     public void testAttachmentFilters() {
- //System.out.println("AttachmentFilters");
         MailHandler instance = new MailHandler();
         InternalErrorManager em = new InternalErrorManager();
         instance.setErrorManager(em);
@@ -926,10 +991,11 @@
         }
 
         assertEquals(em.exceptions.isEmpty(), true);
+ instance.close();
     }
 
+ @Test
     public void testAttachmentFormatters() {
- //System.out.println("AttachmentFormatters");
         MailHandler instance = new MailHandler();
 
         InternalErrorManager em = new InternalErrorManager();
@@ -981,10 +1047,11 @@
         }
 
         assertEquals(em.exceptions.isEmpty(), true);
+ instance.close();
     }
 
+ @Test
     public void testAttachmentNames_StringArr() {
- //System.out.println("AttachmentNames");
         Formatter[] names = null;
         MailHandler instance = new MailHandler();
         InternalErrorManager em = new InternalErrorManager();
@@ -1053,8 +1120,8 @@
         assertEquals(true, em.exceptions.isEmpty());
     }
 
+ @Test
     public void testAttachmentNames_FormatterArr() {
- //System.out.println("AttachmentNames");
         Formatter[] formatters = null;
         MailHandler instance = new MailHandler();
         InternalErrorManager em = new InternalErrorManager();
@@ -1094,10 +1161,11 @@
         assertEquals(formatters[0].equals(instance.getAttachmentNames()[0]), false);
 
         assertEquals(em.exceptions.isEmpty(), true);
+ instance.close();
     }
 
+ @Test
     public void testSubject_String() {
- //System.out.println("Subject");
         String subject = "Test subject.";
         MailHandler instance = new MailHandler();
         InternalErrorManager em = new InternalErrorManager();
@@ -1117,10 +1185,11 @@
         assertEquals(subject, instance.getSubject().toString());
 
         assertEquals(em.exceptions.isEmpty(), true);
+ instance.close();
     }
 
+ @Test
     public void testSubject_Formatter() {
- //System.out.println("Subject");
         Formatter format = new SimpleFormatter();
         MailHandler instance = new MailHandler();
         InternalErrorManager em = new InternalErrorManager();
@@ -1141,13 +1210,15 @@
 
 
         assertEquals(true, em.exceptions.isEmpty());
+ instance.close();
     }
 
+ @Test
     public void testReportError() {
- //System.out.println("reportError");
         MailHandler instance = new MailHandler();
         instance.setErrorManager(new ErrorManager() {
 
+ @Override
             public void error(String msg, Exception ex, int code) {
                 assertNull(msg);
             }
@@ -1159,19 +1230,20 @@
 
         instance.setErrorManager(new ErrorManager() {
 
+ @Override
             public void error(String msg, Exception ex, int code) {
                 assertEquals(msg.indexOf(Level.SEVERE.getName()), 0);
             }
         });
 
         instance.reportError("simple message.", null, ErrorManager.GENERIC_FAILURE);
-
-
+ instance.close();
 
         //Test for valid message.
         instance = createHandlerWithRecords();
         instance.setErrorManager(new MessageErrorManager(instance) {
 
+ @Override
             protected void error(MimeMessage message, Throwable t, int code) {
                 try {
                     assertTrue(message.getHeader("X-Mailer")[0].startsWith(MailHandler.class.getName()));
@@ -1185,24 +1257,8 @@
         instance.close();
     }
 
+ @Test
     public void testSecurityManager() {
- class LogSecurityManager extends SecurityManager {
-
- boolean secure = false;
-
- public void checkPermission(java.security.Permission perm) {
- if (secure) {
- super.checkPermission(perm);
- }
- }
-
- public void checkPermission(java.security.Permission perm, Object context) {
- if (secure) {
- super.checkPermission(perm, context);
- }
- }
- }
-
         final LogSecurityManager manager = new LogSecurityManager();
         System.setSecurityManager(manager);
 
@@ -1363,11 +1419,13 @@
         }
         manager.secure = false;
         System.setSecurityManager(null);
+ h.close();
     }
 
     /**
      * Test must run last.
      */
+ @Test
     public void testZInit() {
         assertNull(System.getProperty("java.util.logging.config.class"));
 
@@ -1396,7 +1454,7 @@
                 v = cfg.createNewFile();
                 assertTrue(v);
 
- System.getProperties().remove(key);
+ System.clearProperty(key);
                 LogManager.getLogManager().readConfiguration();
             }
         } catch (IOException IOE) {
@@ -1422,13 +1480,13 @@
             props.put(p.concat(".encoding"), "UTF-8");
 
             props.put(p.concat(".attachment.filters"),
- "null, " + ThrowFilter.class.getName() + ", " +
- ThrowFilter.class.getName());
+ "null, " + ThrowFilter.class.getName() + ", "
+ + ThrowFilter.class.getName());
 
             props.put(p.concat(".attachment.formatters"),
- SimpleFormatter.class.getName() + ", " +
- XMLFormatter.class.getName() + ", " +
- SimpleFormatter.class.getName());
+ SimpleFormatter.class.getName() + ", "
+ + XMLFormatter.class.getName() + ", "
+ + SimpleFormatter.class.getName());
 
             props.put(p.concat(".attachment.names"), "msg.txt, " + SimpleFormatter.class.getName() + ", error.txt");
 
@@ -1464,7 +1522,7 @@
         assertTrue(em.exceptions.isEmpty());
 
         for (int i = 0; i < em.exceptions.size(); i++) {
- System.out.println(em.exceptions.get(i));
+ fail(String.valueOf(em.exceptions.get(i)));
         }
 
         h.close();
@@ -1507,16 +1565,16 @@
             props.put(p.concat(".pushFilter"), "InvalidPushFilter");
             props.put(p.concat(".comparator"), "InvalidComparator");
             props.put(p.concat(".encoding"), "MailHandler-ENC");
- props.put(p.concat(".attachment.filters"), "null, " +
- "InvalidAttachFilter1, " + ThrowFilter.class.getName());
+ props.put(p.concat(".attachment.filters"), "null, "
+ + "InvalidAttachFilter1, " + ThrowFilter.class.getName());
 
             props.put(p.concat(".attachment.formatters"),
- "InvalidAttachFormatter0, " +
- ThrowComparator.class.getName() + ", " +
- XMLFormatter.class.getName());
+ "InvalidAttachFormatter0, "
+ + ThrowComparator.class.getName() + ", "
+ + XMLFormatter.class.getName());
 
- props.put(p.concat(".attachment.names"), "msg.txt, " +
- ThrowComparator.class.getName() + ", " + XMLFormatter.class.getName());
+ props.put(p.concat(".attachment.names"), "msg.txt, "
+ + ThrowComparator.class.getName() + ", " + XMLFormatter.class.getName());
             props.store(out, "Mail handler test file.");
         } finally {
             out.close();
@@ -1548,9 +1606,9 @@
             h = new MailHandler();
             System.err.flush();
             result = oldErrors.toString().trim();
- int index = result.indexOf(ErrorManager.class.getName() + ": " +
- ErrorManager.OPEN_FAILURE + ": " + Level.SEVERE.getName() +
- ": InvalidErrorManager");
+ int index = result.indexOf(ErrorManager.class.getName() + ": "
+ + ErrorManager.OPEN_FAILURE + ": " + Level.SEVERE.getName()
+ + ": InvalidErrorManager");
             assertTrue(index > -1);
             assertTrue(result.indexOf("java.lang.ClassNotFoundException: InvalidErrorManager") > index);
             oldErrors.reset();
@@ -1589,8 +1647,8 @@
         Field[] fields = Level.class.getFields();
         List a = new ArrayList(fields.length);
         for (int i = 0; i < fields.length; i++) {
- if (Modifier.isStatic(fields[i].getModifiers()) &&
- Level.class.isAssignableFrom(fields[i].getType())) {
+ if (Modifier.isStatic(fields[i].getModifiers())
+ && Level.class.isAssignableFrom(fields[i].getType())) {
                 try {
                     a.add(fields[i].get(null));
                 } catch (IllegalArgumentException ex) {
@@ -1614,6 +1672,7 @@
             this.h = h;
         }
 
+ @Override
         public final void error(String msg, Exception ex, int code) {
             super.error(msg, ex, code);
             MimeMessage message = null;
@@ -1641,6 +1700,7 @@
             super(h);
         }
 
+ @Override
         protected void error(MimeMessage message, Throwable t, int code) {
             try {
                 assertTrue(null != message.getSentDate());
@@ -1657,13 +1717,16 @@
 
     public static class ThrowFilter implements Filter {
 
+ @Override
         public boolean isLoggable(LogRecord record) {
             throw new RuntimeException(record.toString());
         }
     }
 
- public static final class ThrowComparator implements Comparator {
+ public static final class ThrowComparator implements Comparator, Serializable {
+ private static final long serialVersionUID = 8493707928829966353L;
 
+ @Override
         public int compare(Object o1, Object o2) {
             throw new RuntimeException();
         }
@@ -1671,21 +1734,26 @@
 
     public static final class ThrowFormatter extends Formatter {
 
+ @Override
         public String format(LogRecord record) {
             throw new RuntimeException("format");
         }
 
+ @Override
         public String getHead(Handler h) {
             throw new RuntimeException("head");
         }
 
+ @Override
         public String getTail(Handler h) {
             throw new RuntimeException("head");
         }
     }
 
- public static class UselessComparator implements Comparator {
+ public static class UselessComparator implements Comparator, Serializable {
+ private static final long serialVersionUID = 7973575043680596722L;
 
+ @Override
         public int compare(Object o1, Object o2) {
             return o1.toString().compareTo(o2.toString());
         }
@@ -1705,6 +1773,7 @@
             this.value = v;
         }
 
+ @Override
         public boolean isLoggable(LogRecord r) {
             return value;
         }
@@ -1714,6 +1783,7 @@
 
         final List exceptions = new ArrayList();
 
+ @Override
         public void error(String msg, Exception ex, int code) {
             exceptions.add(ex);
         }
@@ -1721,6 +1791,7 @@
 
     public static final class ThrowAuthenticator extends javax.mail.Authenticator {
 
+ @Override
         protected PasswordAuthentication getPasswordAuthentication() {
             throw new RuntimeException();
         }
@@ -1728,8 +1799,31 @@
 
     public static final class EmptyAuthenticator extends javax.mail.Authenticator {
 
+ @Override
         protected PasswordAuthentication getPasswordAuthentication() {
             return new PasswordAuthentication("", "");
         }
     }
+
+ private static final class LogSecurityManager extends SecurityManager {
+
+ boolean secure = false;
+
+ LogSecurityManager() {
+ }
+
+ @Override
+ public void checkPermission(java.security.Permission perm) {
+ if (secure) {
+ super.checkPermission(perm);
+ }
+ }
+
+ @Override
+ public void checkPermission(java.security.Permission perm, Object context) {
+ if (secure) {
+ super.checkPermission(perm, context);
+ }
+ }
+ }
 }


diff -r f54627376385 -r 49a32449db68 mail/src/test/java/com/sun/mail/util/logging/MailHandlerTest.java
--- a/mail/src/test/java/com/sun/mail/util/logging/MailHandlerTest.java Wed Jan 20 13:24:57 2010 -0800
+++ b/mail/src/test/java/com/sun/mail/util/logging/MailHandlerTest.java Thu Jan 21 10:35:40 2010 -0800
@@ -1717,7 +1717,7 @@
 
     public static class ThrowFilter implements Filter {
 
- @Override
+ //_at_Override
         public boolean isLoggable(LogRecord record) {
             throw new RuntimeException(record.toString());
         }
@@ -1726,7 +1726,7 @@
     public static final class ThrowComparator implements Comparator, Serializable {
         private static final long serialVersionUID = 8493707928829966353L;
 
- @Override
+ //_at_Override
         public int compare(Object o1, Object o2) {
             throw new RuntimeException();
         }
@@ -1753,7 +1753,7 @@
     public static class UselessComparator implements Comparator, Serializable {
         private static final long serialVersionUID = 7973575043680596722L;
 
- @Override
+ //_at_Override
         public int compare(Object o1, Object o2) {
             return o1.toString().compareTo(o2.toString());
         }
@@ -1773,7 +1773,7 @@
             this.value = v;
         }
 
- @Override
+ //_at_Override
         public boolean isLoggable(LogRecord r) {
             return value;
         }


diff -r 49a32449db68 -r 1f36c05158ee doc/release/CHANGES.txt
--- a/doc/release/CHANGES.txt Thu Jan 21 10:35:40 2010 -0800
+++ b/doc/release/CHANGES.txt Thu Jan 21 14:06:03 2010 -0800
@@ -31,6 +31,7 @@
 <no id> add mail.mime.ignorewhitespacelines property, default false
 <no id> add support for IMAP UNSELECT command
 <no id> add mail.mime.contentypehandler System property, to clean Content-Type
+<no id> add mail.mime.allowencodedmessages System property
 
 
                   CHANGES IN THE 1.4.3 RELEASE

diff -r 49a32449db68 -r 1f36c05158ee mail/src/main/java/javax/mail/internet/MimePartDataSource.java
--- a/mail/src/main/java/javax/mail/internet/MimePartDataSource.java Thu Jan 21 10:35:40 2010 -0800
+++ b/mail/src/main/java/javax/mail/internet/MimePartDataSource.java Thu Jan 21 14:06:03 2010 -0800
@@ -1,7 +1,7 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 1997-2010 Sun Microsystems, Inc. All rights reserved.
  *
  * The contents of this file are subject to the terms of either the GNU
  * General Public License Version 2 only ("GPL") or the Common Development
@@ -135,7 +135,11 @@
              * If it's one of these types, ignore the encoding.
              */
             ContentType cType = new ContentType(type);
- if (cType.match("multipart/*") || cType.match("message/*"))
+ if (cType.match("multipart/*"))
+ return null;
+ if (cType.match("message/*") &&
+ !PropUtil.getBooleanSystemProperty(
+ "mail.mime.allowencodedmessages", false))
                 return null;
         } catch (ParseException pex) {
             // ignore it

diff -r 49a32449db68 -r 1f36c05158ee mail/src/main/java/javax/mail/internet/package.html
--- a/mail/src/main/java/javax/mail/internet/package.html Thu Jan 21 10:35:40 2010 -0800
+++ b/mail/src/main/java/javax/mail/internet/package.html Thu Jan 21 14:06:03 2010 -0800
@@ -401,6 +401,20 @@
 </TR>
 
 <TR>
+<TD>mail.mime.allowencodedmessages</TD>
+<TD>boolean</TD>
+<TD>
+The MIME spec does not allow body parts of type message/* to be encoded.
+The Content-Transfer-Encoding header is ignored in this case.
+Some versions of Microsoft Outlook will incorrectly encode message
+attachments. Setting this System property to <code>"true"</code> will
+cause the Content-Transfer-Encoding header to be honored for message
+attachments.
+The default value of this property is false.
+</TD>
+</TR>
+
+<TR>
 <TD>mail.mime.contenttypehandler</TD>
 <TD>String</TD>
 <TD>

diff -r 49a32449db68 -r 1f36c05158ee mail/src/test/java/javax/mail/internet/AllowEncodedMessages.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mail/src/test/java/javax/mail/internet/AllowEncodedMessages.java Thu Jan 21 14:06:03 2010 -0800
@@ -0,0 +1,101 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License"). You
+ * may not use this file except in compliance with the License. You can obtain
+ * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
+ * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
+ * Sun designates this particular file as subject to the "Classpath" exception
+ * as provided by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the License
+ * Header, with the fields enclosed by brackets [] replaced by your own
+ * identifying information: "Portions Copyrighted [year]
+ * [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of th
[truncated due to length]