Project: javamail
Repository: mercurial
Revision: 878
Author: shannon
Date: 2016-11-08 23:27:35 UTC
Link:
Log Message:
------------
use of YoungerTerm/OlderTerm on server without WITHIN support fails - bug 8550
MailHandler support for non-multipart messages - Bug K8540
MailHandlerTest test for content type of single body part.
(From Jason)
Revisions:
----------
877
878
Modified Paths:
---------------
doc/release/CHANGES.txt
gimap/src/main/java/com/sun/mail/gimap/protocol/GmailProtocol.java
gimap/src/main/java/com/sun/mail/gimap/protocol/GmailSearchSequence.java
mail/src/main/java/com/sun/mail/imap/protocol/IMAPProtocol.java
mail/src/main/java/com/sun/mail/imap/protocol/SearchSequence.java
mail/src/main/java/com/sun/mail/util/logging/MailHandler.java
mail/src/test/java/com/sun/mail/util/logging/MailHandlerTest.java
Added Paths:
------------
mail/src/test/java/com/sun/mail/imap/IMAPSearchTest.java
Diffs:
------
diff -r d0e30f93a591 -r 8757f3b67c17 doc/release/CHANGES.txt
--- a/doc/release/CHANGES.txt Wed Nov 02 13:11:51 2016 -0700
+++ b/doc/release/CHANGES.txt Tue Nov 08 15:12:17 2016 -0800
@@ -38,6 +38,7 @@
K 8486 Protocol#command method call readResponse after IOException is thrown
K 8487 Possible NPE in Status.<init> line 96
K 8492 MailHandler should support 'login' verify type.
+K 8550 use of YoungerTerm/OlderTerm on server without WITHIN support fails
CHANGES IN THE 1.5.6 RELEASE
diff -r d0e30f93a591 -r 8757f3b67c17 gimap/src/main/java/com/sun/mail/gimap/protocol/GmailProtocol.java
--- a/gimap/src/main/java/com/sun/mail/gimap/protocol/GmailProtocol.java Wed Nov 02 13:11:51 2016 -0700
+++ b/gimap/src/main/java/com/sun/mail/gimap/protocol/GmailProtocol.java Tue Nov 08 15:12:17 2016 -0800
@@ -1,7 +1,7 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
- * Copyright (c) 1997-2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997-2016 Oracle and/or its affiliates. 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
@@ -206,7 +206,7 @@
*/
protected SearchSequence getSearchSequence() {
if (searchSequence == null)
- searchSequence = new GmailSearchSequence();
+ searchSequence = new GmailSearchSequence(this);
return searchSequence;
}
}
diff -r d0e30f93a591 -r 8757f3b67c17 gimap/src/main/java/com/sun/mail/gimap/protocol/GmailSearchSequence.java
--- a/gimap/src/main/java/com/sun/mail/gimap/protocol/GmailSearchSequence.java Wed Nov 02 13:11:51 2016 -0700
+++ b/gimap/src/main/java/com/sun/mail/gimap/protocol/GmailSearchSequence.java Tue Nov 08 15:12:17 2016 -0800
@@ -1,7 +1,7 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
- * Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997-2016 Oracle and/or its affiliates. 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
@@ -58,6 +58,10 @@
*/
public class GmailSearchSequence extends SearchSequence {
+ public GmailSearchSequence(IMAPProtocol p) {
+ super(p);
+ }
+
public Argument generateSequence(SearchTerm term, String charset)
throws SearchException, IOException {
if (term instanceof GmailMsgIdTerm)
diff -r d0e30f93a591 -r 8757f3b67c17 mail/src/main/java/com/sun/mail/imap/protocol/IMAPProtocol.java
--- a/mail/src/main/java/com/sun/mail/imap/protocol/IMAPProtocol.java Wed Nov 02 13:11:51 2016 -0700
+++ b/mail/src/main/java/com/sun/mail/imap/protocol/IMAPProtocol.java Tue Nov 08 15:12:17 2016 -0800
@@ -2605,7 +2605,7 @@
*/
protected SearchSequence getSearchSequence() {
if (searchSequence == null)
- searchSequence = new SearchSequence();
+ searchSequence = new SearchSequence(this);
return searchSequence;
}
diff -r d0e30f93a591 -r 8757f3b67c17 mail/src/main/java/com/sun/mail/imap/protocol/SearchSequence.java
--- a/mail/src/main/java/com/sun/mail/imap/protocol/SearchSequence.java Wed Nov 02 13:11:51 2016 -0700
+++ b/mail/src/main/java/com/sun/mail/imap/protocol/SearchSequence.java Tue Nov 08 15:12:17 2016 -0800
@@ -1,7 +1,7 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
- * Copyright (c) 1997-2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997-2016 Oracle and/or its affiliates. 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
@@ -59,9 +59,29 @@
* support for additional product-specific search terms.
*
* @author John Mani
+ * @author Bill Shannon
*/
public class SearchSequence {
+ private IMAPProtocol protocol; // for hasCapability checks; may be null
+
+ /**
+ * Create a SearchSequence for this IMAPProtocol.
+ *
+ * @param p the IMAPProtocol object for the server
+ * @since JavaMail 1.6.0
+ */
+ public SearchSequence(IMAPProtocol p) {
+ protocol = p;
+ }
+
+ /**
+ * Create a SearchSequence.
+ */
+ @Deprecated
+ public SearchSequence() {
+ }
+
/**
* Generate the IMAP search sequence for the given search expression.
*
@@ -486,6 +506,8 @@
* @since JavaMail 1.5.1
*/
protected Argument older(OlderTerm term) throws SearchException {
+ if (protocol != null && !protocol.hasCapability("WITHIN"))
+ throw new SearchException("Server doesn't support OLDER searches");
Argument result = new Argument();
result.writeAtom("OLDER");
result.writeNumber(term.getInterval());
@@ -501,6 +523,8 @@
* @since JavaMail 1.5.1
*/
protected Argument younger(YoungerTerm term) throws SearchException {
+ if (protocol != null && !protocol.hasCapability("WITHIN"))
+ throw new SearchException("Server doesn't support YOUNGER searches");
Argument result = new Argument();
result.writeAtom("YOUNGER");
result.writeNumber(term.getInterval());
@@ -517,6 +541,8 @@
*/
protected Argument modifiedSince(ModifiedSinceTerm term)
throws SearchException {
+ if (protocol != null && !protocol.hasCapability("CONDSTORE"))
+ throw new SearchException("Server doesn't support MODSEQ searches");
Argument result = new Argument();
result.writeAtom("MODSEQ");
result.writeNumber(term.getModSeq());
diff -r d0e30f93a591 -r 8757f3b67c17 mail/src/test/java/com/sun/mail/imap/IMAPSearchTest.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mail/src/test/java/com/sun/mail/imap/IMAPSearchTest.java Tue Nov 08 15:12:17 2016 -0800
@@ -0,0 +1,116 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright (c) 2009-2016 Oracle and/or its affiliates. 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_1_1.html
+ * or packager/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 packager/legal/LICENSE.txt.
+ *
+ * GPL Classpath Exception:
+ * Oracle designates this particular file as subject to the "Classpath"
+ * exception as provided by Oracle in the GPL Version 2 section of the License
+ * file that accompanied this code.
+ *
+ * Modifications:
+ * If applicable, add the following below the License Header, with the fields
+ * enclosed by brackets [] replaced by your own identifying information:
+ * "Portions Copyright [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.imap;
+
+import java.io.IOException;
+import java.util.Properties;
+
+import javax.mail.Folder;
+import javax.mail.Session;
+import javax.mail.Store;
+import javax.mail.Message;
+import javax.mail.search.*;
+
+import com.sun.mail.test.TestServer;
+
+import org.junit.Test;
+import org.junit.Rule;
+import org.junit.rules.Timeout;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+/**
+ * Test the search method.
+ */
+public final class IMAPSearchTest {
+
+ // timeout the test in case of deadlock
+ @Rule
+ public Timeout deadlockTimeout = Timeout.seconds(20);
+
+ @Test
+ public void testWithinNotSupported() {
+ TestServer server = null;
+ try {
+ server = new TestServer(new IMAPHandler() {
+ @Override
+ public void search(String line) throws IOException {
+ bad("WITHIN not supported");
+ }
+ });
+ server.start();
+
+ final Properties properties = new Properties();
+ properties.setProperty("mail.imap.host", "localhost");
+ properties.setProperty("mail.imap.port", "" + server.getPort());
+ properties.setProperty("mail.imap.throwsearchexception", "true");
+ final Session session = Session.getInstance(properties);
+ //session.setDebug(true);
+
+ final Store store = session.getStore("imap");
+ Folder folder = null;
+ try {
+ store.connect("test", "test");
+ folder = store.getFolder("INBOX");
+ folder.open(Folder.READ_ONLY);
+ Message[] msgs = folder.search(new YoungerTerm(1));
+ fail("search didn't fail");
+ } catch (SearchException ex) {
+ // success!
+ } catch (Exception ex) {
+ System.out.println(ex);
+ //ex.printStackTrace();
+ fail(ex.toString());
+ } finally {
+ if (folder != null)
+ folder.close(false);
+ store.close();
+ }
+ } catch (final Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ } finally {
+ if (server != null) {
+ server.quit();
+ }
+ }
+ }
+}
diff -r 8757f3b67c17 -r f627c0ed80b9 doc/release/CHANGES.txt
--- a/doc/release/CHANGES.txt Tue Nov 08 15:12:17 2016 -0800
+++ b/doc/release/CHANGES.txt Tue Nov 08 15:27:35 2016 -0800
@@ -38,6 +38,7 @@
K 8486 Protocol#command method call readResponse after IOException is thrown
K 8487 Possible NPE in Status.<init> line 96
K 8492 MailHandler should support 'login' verify type.
+K 8540 MailHandler support for non-multipart messages
K 8550 use of YoungerTerm/OlderTerm on server without WITHIN support fails
diff -r 8757f3b67c17 -r f627c0ed80b9 mail/src/main/java/com/sun/mail/util/logging/MailHandler.java
--- a/mail/src/main/java/com/sun/mail/util/logging/MailHandler.java Tue Nov 08 15:12:17 2016 -0800
+++ b/mail/src/main/java/com/sun/mail/util/logging/MailHandler.java Tue Nov 08 15:27:35 2016 -0800
@@ -298,17 +298,18 @@
*
* <p>
* <b>Attachments:</b>
- * This <tt>Handler</tt> allows multiple attachments per each email.
- * The attachment order maps directly to the array index order in this
- * <tt>Handler</tt> with zero index being the first attachment. The number of
- * attachment formatters controls the number of attachments per email and
- * the content type of each attachment. The attachment filters determine if a
- * <tt>LogRecord</tt> will be included in an attachment. If an attachment
- * filter is <tt>null</tt> then all records are included for that attachment.
- * Attachments without content will be omitted from email message. The
- * attachment name formatters create the file name for an attachment.
- * Custom attachment name formatters can be used to generate an attachment name
- * based on the contents of the attachment.
+ * This <tt>Handler</tt> allows multiple attachments per each email message.
+ * The presence of an attachment formatter will change the content type of the
+ * email message to a multi-part message. The attachment order maps directly to
+ * the array index order in this <tt>Handler</tt> with zero index being the
+ * first attachment. The number of attachment formatters controls the number of
+ * attachments per email and the content type of each attachment. The
+ * attachment filters determine if a <tt>LogRecord</tt> will be included in an
+ * attachment. If an attachment filter is <tt>null</tt> then all records are
+ * included for that attachment. Attachments without content will be omitted
+ * from email message. The attachment name formatters create the file name for
+ * an attachment. Custom attachment name formatters can be used to generate an
+ * attachment name based on the contents of the attachment.
*
* <p>
* <b>Push Level and Push Filter:</b>
@@ -1825,7 +1826,7 @@
* @param type the mime type or null, meaning text/plain.
* @throws MessagingException if there is a problem.
*/
- private void setContent(MimeBodyPart part, CharSequence buf, String type) throws MessagingException {
+ private void setContent(MimePart part, CharSequence buf, String type) throws MessagingException {
final String charset = getEncodingName();
if (type != null && !"text/plain".equalsIgnoreCase(type)) {
type = contentWithEncoding(type, charset);
@@ -1853,7 +1854,7 @@
final ContentType ct = new ContentType(type);
ct.setParameter("charset", MimeUtility.mimeCharset(encoding));
encoding = ct.toString(); //See javax.mail.internet.ContentType.
- if (!isEmpty(encoding)) {
+ if (!isEmpty(encoding)) { //Support pre K5687.
type = encoding;
}
} catch (final MessagingException ME) {
@@ -2826,7 +2827,6 @@
initSession();
}
MimeMessage msg = new MimeMessage(session);
- msg.setDescription(descriptionFrom(comparator, pushLevel, pushFilter));
/**
* Parts are lazily created when an attachment performs a getHead
@@ -2839,12 +2839,19 @@
* The buffers are lazily created when the part requires a getHead.
*/
StringBuilder[] buffers = new StringBuilder[parts.length];
-
StringBuilder buf = null;
+ final MimePart body;
+ if (parts.length == 0) {
+ msg.setDescription(descriptionFrom(
+ getFormatter(), getFilter(), subjectFormatter));
+ body = msg;
+ } else {
+ msg.setDescription(descriptionFrom(
+ comparator, pushLevel, pushFilter));
+ body = createBodyPart();
+ }
appendSubject(msg, head(subjectFormatter));
-
- final MimeBodyPart body = createBodyPart();
final Formatter bodyFormat = getFormatter();
final Filter bodyFilter = getFilter();
@@ -2897,7 +2904,8 @@
}
if (formatted) {
- if (locale != null && !locale.equals(lastLocale)) {
+ if (body != msg && locale != null
+ && !locale.equals(lastLocale)) {
appendContentLang(msg, locale);
}
} else { //Belongs to no mime part.
@@ -2937,19 +2945,22 @@
appendSubject(msg, tail(subjectFormatter, ""));
- MimeMultipart multipart = new MimeMultipart();
String contentType = contentTypeOf(buf);
String altType = contentTypeOf(bodyFormat);
setContent(body, buf, altType == null ? contentType : altType);
- multipart.addBodyPart(body);
-
- for (int i = 0; i < parts.length; ++i) {
- if (parts[i] != null) {
- multipart.addBodyPart(parts[i]);
+ if (body != msg) {
+ final MimeMultipart multipart = new MimeMultipart();
+ //assert body instanceof BodyPart : body;
+ multipart.addBodyPart((BodyPart) body);
+
+ for (int i = 0; i < parts.length; ++i) {
+ if (parts[i] != null) {
+ multipart.addBodyPart(parts[i]);
+ }
}
+ msg.setContent(multipart);
}
- msg.setContent(multipart);
return msg;
}
@@ -3180,6 +3191,7 @@
try { //Verify that the DataHandler can be loaded.
Object ccl = getAndSetContextClassLoader(MAILHANDLER_LOADER);
try {
+ //Always load the multipart classes.
MimeMultipart multipart = new MimeMultipart();
MimeBodyPart[] ambp = new MimeBodyPart[atn.length];
final MimeBodyPart body;
diff -r 8757f3b67c17 -r f627c0ed80b9 mail/src/test/java/com/sun/mail/util/logging/MailHandlerTest.java
--- a/mail/src/test/java/com/sun/mail/util/logging/MailHandlerTest.java Tue Nov 08 15:12:17 2016 -0800
+++ b/mail/src/test/java/com/sun/mail/util/logging/MailHandlerTest.java Tue Nov 08 15:27:35 2016 -0800
@@ -2582,9 +2582,23 @@
}
@Test
- public void testContentTypeOverride() throws Exception {
+ public void testContentTypeNestedMultiFormatter() throws Exception {
String expected = "application/xml; charset=us-ascii";
- String type = getInlineContentType(new XMLFormatter());
+ String type = getInlineMultiContentType(new CollectorFormatter("{0}{1}{2}",
+ new XMLFormatter(), new SeverityComparator()));
+ assertEquals(expected, type);
+
+
+ expected = "text/plain; charset=us-ascii";
+ type = getInlineMultiContentType(new CollectorFormatter("{0}{1}{2}",
+ new CompactFormatter(), new SeverityComparator()));
+ assertEquals(expected, type);
+ }
+
+ @Test
+ public void testContentTypeMultiOverride() throws Exception {
+ String expected = "application/xml; charset=us-ascii";
+ String type = getInlineMultiContentType(new XMLFormatter());
assertEquals(expected, type);
MimetypesFileTypeMap m = new MimetypesFileTypeMap();
@@ -2592,20 +2606,23 @@
final FileTypeMap old = FileTypeMap.getDefaultFileTypeMap();
FileTypeMap.setDefaultFileTypeMap(m);
try {
- type = getInlineContentType(new XMLFormatter());
+ type = getInlineMultiContentType(new XMLFormatter());
assertEquals("text/plain; charset=us-ascii", type);
} finally {
FileTypeMap.setDefaultFileTypeMap(old);
}
- type = getInlineContentType(new XMLFormatter());
+ type = getInlineMultiContentType(new XMLFormatter());
assertEquals(expected, type);
}
- private String getInlineContentType(Formatter f) throws Exception {
+ private String getInlineMultiContentType(Formatter f) throws Exception {
final String[] value = new String[1];
MailHandler instance = new MailHandler(createInitProperties(""));
+ instance.setAttachmentFormatters(new SimpleFormatter());
+ instance.setAttachmentFilters(BooleanFilter.FALSE);
instance.setEncoding("us-ascii");
+
MessageErrorManager em = new MessageErrorManager(instance.getMailProperties()) {
@Override
@@ -2614,6 +2631,9 @@
MimeMultipart multi = (MimeMultipart) msg.getContent();
BodyPart body = multi.getBodyPart(0);
assertEquals(Part.INLINE, body.getDisposition());
+ String desc = msg.getDescription();
+ assertTrue(desc.contains("Sorted using"));
+ assertTrue(desc.contains("pushed when"));
value[0] = body.getContentType();
} catch (Throwable E) {
dump(E);
@@ -2633,6 +2653,57 @@
}
@Test
+ public void testContentTypeOverride() throws Exception {
+ String expected = "application/xml; charset=us-ascii";
+ String type = getInlineContentType(new XMLFormatter());
+ assertEquals(expected, type);
+
+ MimetypesFileTypeMap m = new MimetypesFileTypeMap();
+ m.addMimeTypes("text/plain txt TXT XMLFormatter");
+ final FileTypeMap old = FileTypeMap.getDefaultFileTypeMap();
+ FileTypeMap.setDefaultFileTypeMap(m);
+ try {
+ type = getInlineContentType(new XMLFormatter());
+ assertEquals("text/plain; charset=us-ascii", type);
+ } finally {
+ FileTypeMap.setDefaultFileTypeMap(old);
+ }
+
+ type = getInlineContentType(new XMLFormatter());
+ assertEquals(expected, type);
+ }
+
+ private String getInlineContentType(Formatter f) throws Exception {
+ final String[] value = new String[1];
+ MailHandler instance = new MailHandler(createInitProperties(""));
+ instance.setEncoding("us-ascii");
+ MessageErrorManager em = new MessageErrorManager(instance.getMailProperties()) {
+
+ @Override
+ protected void error(MimeMessage msg, Throwable t, int code) {
+ try {
+ String desc = msg.getDescription();
+ assertTrue(desc.contains("filtered with"));
+ assertTrue(desc.contains("named by"));
+ value[0] = msg.getContentType();
+ } catch (Throwable E) {
+ dump(E);
+ fail(E.toString());
+ }
+ }
+ };
+ instance.setErrorManager(em);
+ Properties props = createInitProperties("");
+ props.put("mail.to", "localhost_at_localdomain");
+ instance.setMailProperties(props);
+ instance.setFormatter(f);
+ instance.publish(new LogRecord(Level.SEVERE, "test"));
+ instance.close();
+
+ return value[0];
+ }
+
+ @Test
public void testAcceptLang() throws Exception {
class LangManager extends MessageErrorManager {
@@ -2746,6 +2817,8 @@
}
MailHandler target = new MailHandler(createInitProperties(""));
+ target.setAttachmentFormatters(new SimpleFormatter());
+ target.setAttachmentFilters(BooleanFilter.FALSE);
Properties props = new Properties();
props.put("motd", "Hello MailHandler!");
@@ -2858,12 +2931,17 @@
cl = Locale.US;
target = new MailHandler(createInitProperties(""));
+ target.setAttachmentFormatters(new SimpleFormatter());
+ target.setAttachmentFilters(BooleanFilter.FALSE);
+
target.setErrorManager(new Infer(target.getMailProperties(), Locale.ENGLISH));
logPrefix = p + '.' + f.getName() + cl;
testContentLangInfer(target, logPrefix, bundleName, cl);
cl = Locale.UK;
target = new MailHandler(createInitProperties(""));
+ target.setAttachmentFormatters(new SimpleFormatter());
+ target.setAttachmentFilters(BooleanFilter.FALSE);
target.setErrorManager(new Infer(target.getMailProperties(), Locale.ENGLISH));
logPrefix = p + '.' + f.getName() + cl;
testContentLangInfer(target, logPrefix, bundleName, cl);