Loading src/com/fsck/k9/mail/internet/MimeMessage.java +11 −31 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import org.apache.james.mime4j.stream.Field; import org.apache.james.mime4j.stream.MimeConfig; import org.apache.james.mime4j.util.MimeUtil; import com.fsck.k9.BuildConfig; import com.fsck.k9.mail.Address; import com.fsck.k9.mail.Body; import com.fsck.k9.mail.BodyPart; Loading Loading @@ -62,20 +63,6 @@ public class MimeMessage extends Message { } /** * Parse the given InputStream using Apache Mime4J to build a MimeMessage. * Nested messages will not be recursively parsed. * * @param in * @throws IOException * @throws MessagingException * * @see #MimeMessage(InputStream in, boolean recurse) */ public MimeMessage(InputStream in) throws IOException, MessagingException { parse(in); } /** * Parse the given InputStream using Apache Mime4J to build a MimeMessage. * Loading @@ -88,11 +75,15 @@ public class MimeMessage extends Message { parse(in, recurse); } protected void parse(InputStream in) throws IOException, MessagingException { /** * Parse the given InputStream using Apache Mime4J to build a MimeMessage. * Does not recurse through nested bodyparts. */ public final void parse(InputStream in) throws IOException, MessagingException { parse(in, false); } protected void parse(InputStream in, boolean recurse) throws IOException, MessagingException { private void parse(InputStream in, boolean recurse) throws IOException, MessagingException { mHeader.clear(); mFrom = null; mTo = null; Loading Loading @@ -121,8 +112,8 @@ public class MimeMessage extends Message { try { parser.parse(new EOLConvertingInputStream(in)); } catch (MimeException me) { //TODO wouldn't a MessagingException be better? throw new Error(me); } } Loading Loading @@ -482,7 +473,7 @@ public class MimeMessage extends Message { } } class MimeMessageBuilder implements ContentHandler { private class MimeMessageBuilder implements ContentHandler { private final LinkedList<Object> stack = new LinkedList<Object>(); public MimeMessageBuilder() { Loading Loading @@ -519,9 +510,6 @@ public class MimeMessage extends Message { expect(Part.class); } public void endHeader() { expect(Part.class); } Loading Loading @@ -571,16 +559,6 @@ public class MimeMessage extends Message { stack.removeFirst(); } public void epilogue(InputStream is) throws IOException { expect(MimeMultipart.class); StringBuilder sb = new StringBuilder(); int b; while ((b = is.read()) != -1) { sb.append((char)b); } // ((Multipart) stack.peek()).setEpilogue(sb.toString()); } public void preamble(InputStream is) throws IOException { expect(MimeMultipart.class); StringBuilder sb = new StringBuilder(); Loading @@ -589,7 +567,9 @@ public class MimeMessage extends Message { sb.append((char)b); } ((MimeMultipart)stack.peek()).setPreamble(sb.toString()); } public void epilogue(InputStream is) throws IOException { } public void raw(InputStream is) throws IOException { Loading tests/src/com/fsck/k9/mail/internet/MimeMessageParseTest.java 0 → 100644 +236 −0 Original line number Diff line number Diff line package com.fsck.k9.mail.internet; import java.io.ByteArrayInputStream; import java.io.File; import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import org.apache.commons.io.IOUtils; import com.fsck.k9.mail.Address; import com.fsck.k9.mail.Body; import com.fsck.k9.mail.BodyPart; import com.fsck.k9.mail.Message.RecipientType; import com.fsck.k9.mail.Multipart; import com.fsck.k9.mail.internet.MimeMessage; import android.test.AndroidTestCase; public class MimeMessageParseTest extends AndroidTestCase { static { BinaryTempFileBody.setTempDirectory(new File(System.getProperty("java.io.tmpdir"))); } private static ByteArrayInputStream toStream(String rawMailData) throws Exception { return new ByteArrayInputStream(rawMailData.getBytes("ISO-8859-1")); } private static MimeMessage parseWithoutRecurse(InputStream data) throws Exception { return new MimeMessage(data, false); } private static MimeMessage parseWithRecurse(InputStream data) throws Exception { return new MimeMessage(data, true); } private static void checkAddresses(Address[] actual, String... expected) { for (int i = 0; i < actual.length; i++) { assertEquals(actual[i].toEncodedString(), expected[i]); } assertEquals(expected.length, actual.length); } private static String printStream(InputStream stream) throws Exception { return IOUtils.toString(stream, "ISO-8859-1"); } private static List<Body> getLeafParts(Body body) { if (body instanceof Multipart) { List<Body> ret = new ArrayList<Body>(); for (BodyPart child : ((Multipart) body).getBodyParts()) { ret.addAll(getLeafParts(child.getBody())); } return ret; } else { return Collections.singletonList(body); } } private static void checkLeafParts(MimeMessage msg, String... expectedParts) throws Exception { List<String> actual = new ArrayList<String>(); for (Body leaf : getLeafParts(msg.getBody())) { actual.add(printStream(leaf.getInputStream())); } assertEquals(Arrays.asList(expectedParts), actual); } public static void testSinglePart7BitNoRecurse() throws Exception { MimeMessage msg = parseWithoutRecurse(toStream( "From: <adam@example.org>\r\n" + "To: <eva@example.org>\r\n" + "Subject: Testmail\r\n" + "MIME-Version: 1.0\r\n" + "Content-type: text/plain\r\n" + "Content-Transfer-Encoding: 7bit\r\n" + "\r\n" + "this is some test text.")); checkAddresses(msg.getFrom(), "adam@example.org"); checkAddresses(msg.getRecipients(RecipientType.TO), "eva@example.org"); assertEquals("Testmail", msg.getSubject()); assertEquals("text/plain", msg.getContentType()); assertEquals("this is some test text.", printStream(msg.getBody().getInputStream())); } public static void testSinglePart8BitRecurse() throws Exception { MimeMessage msg = parseWithRecurse(toStream( "From: <adam@example.org>\r\n" + "To: <eva@example.org>\r\n" + "Subject: Testmail\r\n" + "MIME-Version: 1.0\r\n" + "Content-type: text/plain; encoding=ISO-8859-1\r\n" + "Content-Transfer-Encoding: 8bit\r\n" + "\r\n" + "gefährliche Umlaute")); checkAddresses(msg.getFrom(), "adam@example.org"); checkAddresses(msg.getRecipients(RecipientType.TO), "eva@example.org"); assertEquals("Testmail", msg.getSubject()); assertEquals("text/plain; encoding=ISO-8859-1", msg.getContentType()); assertEquals("gefährliche Umlaute", printStream(msg.getBody().getInputStream())); } public static void testSinglePartBase64NoRecurse() throws Exception { MimeMessage msg = parseWithoutRecurse(toStream( "From: <adam@example.org>\r\n" + "To: <eva@example.org>\r\n" + "Subject: Testmail\r\n" + "MIME-Version: 1.0\r\n" + "Content-type: text/plain\r\n" + "Content-Transfer-Encoding: base64\r\n" + "\r\n" + "dGhpcyBpcyBzb21lIG1vcmUgdGVzdCB0ZXh0Lg==\r\n")); checkAddresses(msg.getFrom(), "adam@example.org"); checkAddresses(msg.getRecipients(RecipientType.TO), "eva@example.org"); assertEquals("Testmail", msg.getSubject()); assertEquals("text/plain", msg.getContentType()); assertEquals("this is some more test text.", printStream(msg.getBody().getInputStream())); } public static void testMultipartSingleLayerNoRecurse() throws Exception { MimeMessage msg = parseWithoutRecurse(toStream( "From: <x@example.org>\r\n" + "To: <y@example.org>\r\n" + "Subject: Testmail 2\r\n" + "MIME-Version: 1.0\n" + "Content-Type: multipart/mixed; boundary=frontier\n" + "\n" + "This is a message with multiple parts in MIME format.\n" + "--frontier\n" + "Content-Type: text/plain\n" + "\n" + "This is the body of the message.\n" + "--frontier\n" + "Content-Type: application/octet-stream\n" + "Content-Transfer-Encoding: base64\n" + "\n" + "PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg\n" + "Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg=\n" + "--frontier--")); checkAddresses(msg.getFrom(), "x@example.org"); checkAddresses(msg.getRecipients(RecipientType.TO), "y@example.org"); assertEquals("Testmail 2", msg.getSubject()); assertEquals("multipart/mixed; boundary=frontier", msg.getContentType()); checkLeafParts(msg, "This is the body of the message.", "<html>\n" + " <head>\n" + " </head>\n" + " <body>\n" + " <p>This is the body of the message.</p>\n" + " </body>\n" + "</html>\n" + ""); } public static void testMultipartSingleLayerRecurse() throws Exception { MimeMessage msg = parseWithRecurse(toStream( "From: <x@example.org>\r\n" + "To: <y@example.org>\r\n" + "Subject: Testmail 2\r\n" + "MIME-Version: 1.0\n" + "Content-Type: multipart/mixed; boundary=frontier\n" + "\n" + "This is a message with multiple parts in MIME format.\n" + "--frontier\n" + "Content-Type: text/plain\n" + "\n" + "This is the body of the message.\n" + "--frontier\n" + "Content-Type: application/octet-stream\n" + "Content-Transfer-Encoding: base64\n" + "\n" + "PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg\n" + "Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg=\n" + "--frontier--")); checkAddresses(msg.getFrom(), "x@example.org"); checkAddresses(msg.getRecipients(RecipientType.TO), "y@example.org"); assertEquals("Testmail 2", msg.getSubject()); assertEquals("multipart/mixed; boundary=frontier", msg.getContentType()); checkLeafParts(msg, "This is the body of the message.", "<html>\n" + " <head>\n" + " </head>\n" + " <body>\n" + " <p>This is the body of the message.</p>\n" + " </body>\n" + "</html>\n" + ""); } public static void testMultipartTwoLayersRecurse() throws Exception { MimeMessage msg = parseWithRecurse(toStream( "From: <x@example.org>\r\n" + "To: <y@example.org>\r\n" + "Subject: Testmail 2\r\n" + "MIME-Version: 1.0\n" + "Content-Type: multipart/mixed; boundary=1\n" + "\n" + "This is a message with multiple parts in MIME format.\n" + "--1\n" + "Content-Type: text/plain\n" + "\n" + "some text in the first part\n" + "--1\n" + "Content-Type: multipart/alternative; boundary=2\n" + "\n" + "--2\n" + "Content-Type: text/plain\n" + "\n" + "alternative 1\n" + "--2\n" + "Content-Type: text/plain\n" + "\n" + "alternative 2\n" + "--2--\n" + "--1--")); checkAddresses(msg.getFrom(), "x@example.org"); checkAddresses(msg.getRecipients(RecipientType.TO), "y@example.org"); assertEquals("Testmail 2", msg.getSubject()); assertEquals("multipart/mixed; boundary=1", msg.getContentType()); checkLeafParts(msg, "some text in the first part", "alternative 1", "alternative 2"); } } Loading
src/com/fsck/k9/mail/internet/MimeMessage.java +11 −31 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import org.apache.james.mime4j.stream.Field; import org.apache.james.mime4j.stream.MimeConfig; import org.apache.james.mime4j.util.MimeUtil; import com.fsck.k9.BuildConfig; import com.fsck.k9.mail.Address; import com.fsck.k9.mail.Body; import com.fsck.k9.mail.BodyPart; Loading Loading @@ -62,20 +63,6 @@ public class MimeMessage extends Message { } /** * Parse the given InputStream using Apache Mime4J to build a MimeMessage. * Nested messages will not be recursively parsed. * * @param in * @throws IOException * @throws MessagingException * * @see #MimeMessage(InputStream in, boolean recurse) */ public MimeMessage(InputStream in) throws IOException, MessagingException { parse(in); } /** * Parse the given InputStream using Apache Mime4J to build a MimeMessage. * Loading @@ -88,11 +75,15 @@ public class MimeMessage extends Message { parse(in, recurse); } protected void parse(InputStream in) throws IOException, MessagingException { /** * Parse the given InputStream using Apache Mime4J to build a MimeMessage. * Does not recurse through nested bodyparts. */ public final void parse(InputStream in) throws IOException, MessagingException { parse(in, false); } protected void parse(InputStream in, boolean recurse) throws IOException, MessagingException { private void parse(InputStream in, boolean recurse) throws IOException, MessagingException { mHeader.clear(); mFrom = null; mTo = null; Loading Loading @@ -121,8 +112,8 @@ public class MimeMessage extends Message { try { parser.parse(new EOLConvertingInputStream(in)); } catch (MimeException me) { //TODO wouldn't a MessagingException be better? throw new Error(me); } } Loading Loading @@ -482,7 +473,7 @@ public class MimeMessage extends Message { } } class MimeMessageBuilder implements ContentHandler { private class MimeMessageBuilder implements ContentHandler { private final LinkedList<Object> stack = new LinkedList<Object>(); public MimeMessageBuilder() { Loading Loading @@ -519,9 +510,6 @@ public class MimeMessage extends Message { expect(Part.class); } public void endHeader() { expect(Part.class); } Loading Loading @@ -571,16 +559,6 @@ public class MimeMessage extends Message { stack.removeFirst(); } public void epilogue(InputStream is) throws IOException { expect(MimeMultipart.class); StringBuilder sb = new StringBuilder(); int b; while ((b = is.read()) != -1) { sb.append((char)b); } // ((Multipart) stack.peek()).setEpilogue(sb.toString()); } public void preamble(InputStream is) throws IOException { expect(MimeMultipart.class); StringBuilder sb = new StringBuilder(); Loading @@ -589,7 +567,9 @@ public class MimeMessage extends Message { sb.append((char)b); } ((MimeMultipart)stack.peek()).setPreamble(sb.toString()); } public void epilogue(InputStream is) throws IOException { } public void raw(InputStream is) throws IOException { Loading
tests/src/com/fsck/k9/mail/internet/MimeMessageParseTest.java 0 → 100644 +236 −0 Original line number Diff line number Diff line package com.fsck.k9.mail.internet; import java.io.ByteArrayInputStream; import java.io.File; import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import org.apache.commons.io.IOUtils; import com.fsck.k9.mail.Address; import com.fsck.k9.mail.Body; import com.fsck.k9.mail.BodyPart; import com.fsck.k9.mail.Message.RecipientType; import com.fsck.k9.mail.Multipart; import com.fsck.k9.mail.internet.MimeMessage; import android.test.AndroidTestCase; public class MimeMessageParseTest extends AndroidTestCase { static { BinaryTempFileBody.setTempDirectory(new File(System.getProperty("java.io.tmpdir"))); } private static ByteArrayInputStream toStream(String rawMailData) throws Exception { return new ByteArrayInputStream(rawMailData.getBytes("ISO-8859-1")); } private static MimeMessage parseWithoutRecurse(InputStream data) throws Exception { return new MimeMessage(data, false); } private static MimeMessage parseWithRecurse(InputStream data) throws Exception { return new MimeMessage(data, true); } private static void checkAddresses(Address[] actual, String... expected) { for (int i = 0; i < actual.length; i++) { assertEquals(actual[i].toEncodedString(), expected[i]); } assertEquals(expected.length, actual.length); } private static String printStream(InputStream stream) throws Exception { return IOUtils.toString(stream, "ISO-8859-1"); } private static List<Body> getLeafParts(Body body) { if (body instanceof Multipart) { List<Body> ret = new ArrayList<Body>(); for (BodyPart child : ((Multipart) body).getBodyParts()) { ret.addAll(getLeafParts(child.getBody())); } return ret; } else { return Collections.singletonList(body); } } private static void checkLeafParts(MimeMessage msg, String... expectedParts) throws Exception { List<String> actual = new ArrayList<String>(); for (Body leaf : getLeafParts(msg.getBody())) { actual.add(printStream(leaf.getInputStream())); } assertEquals(Arrays.asList(expectedParts), actual); } public static void testSinglePart7BitNoRecurse() throws Exception { MimeMessage msg = parseWithoutRecurse(toStream( "From: <adam@example.org>\r\n" + "To: <eva@example.org>\r\n" + "Subject: Testmail\r\n" + "MIME-Version: 1.0\r\n" + "Content-type: text/plain\r\n" + "Content-Transfer-Encoding: 7bit\r\n" + "\r\n" + "this is some test text.")); checkAddresses(msg.getFrom(), "adam@example.org"); checkAddresses(msg.getRecipients(RecipientType.TO), "eva@example.org"); assertEquals("Testmail", msg.getSubject()); assertEquals("text/plain", msg.getContentType()); assertEquals("this is some test text.", printStream(msg.getBody().getInputStream())); } public static void testSinglePart8BitRecurse() throws Exception { MimeMessage msg = parseWithRecurse(toStream( "From: <adam@example.org>\r\n" + "To: <eva@example.org>\r\n" + "Subject: Testmail\r\n" + "MIME-Version: 1.0\r\n" + "Content-type: text/plain; encoding=ISO-8859-1\r\n" + "Content-Transfer-Encoding: 8bit\r\n" + "\r\n" + "gefährliche Umlaute")); checkAddresses(msg.getFrom(), "adam@example.org"); checkAddresses(msg.getRecipients(RecipientType.TO), "eva@example.org"); assertEquals("Testmail", msg.getSubject()); assertEquals("text/plain; encoding=ISO-8859-1", msg.getContentType()); assertEquals("gefährliche Umlaute", printStream(msg.getBody().getInputStream())); } public static void testSinglePartBase64NoRecurse() throws Exception { MimeMessage msg = parseWithoutRecurse(toStream( "From: <adam@example.org>\r\n" + "To: <eva@example.org>\r\n" + "Subject: Testmail\r\n" + "MIME-Version: 1.0\r\n" + "Content-type: text/plain\r\n" + "Content-Transfer-Encoding: base64\r\n" + "\r\n" + "dGhpcyBpcyBzb21lIG1vcmUgdGVzdCB0ZXh0Lg==\r\n")); checkAddresses(msg.getFrom(), "adam@example.org"); checkAddresses(msg.getRecipients(RecipientType.TO), "eva@example.org"); assertEquals("Testmail", msg.getSubject()); assertEquals("text/plain", msg.getContentType()); assertEquals("this is some more test text.", printStream(msg.getBody().getInputStream())); } public static void testMultipartSingleLayerNoRecurse() throws Exception { MimeMessage msg = parseWithoutRecurse(toStream( "From: <x@example.org>\r\n" + "To: <y@example.org>\r\n" + "Subject: Testmail 2\r\n" + "MIME-Version: 1.0\n" + "Content-Type: multipart/mixed; boundary=frontier\n" + "\n" + "This is a message with multiple parts in MIME format.\n" + "--frontier\n" + "Content-Type: text/plain\n" + "\n" + "This is the body of the message.\n" + "--frontier\n" + "Content-Type: application/octet-stream\n" + "Content-Transfer-Encoding: base64\n" + "\n" + "PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg\n" + "Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg=\n" + "--frontier--")); checkAddresses(msg.getFrom(), "x@example.org"); checkAddresses(msg.getRecipients(RecipientType.TO), "y@example.org"); assertEquals("Testmail 2", msg.getSubject()); assertEquals("multipart/mixed; boundary=frontier", msg.getContentType()); checkLeafParts(msg, "This is the body of the message.", "<html>\n" + " <head>\n" + " </head>\n" + " <body>\n" + " <p>This is the body of the message.</p>\n" + " </body>\n" + "</html>\n" + ""); } public static void testMultipartSingleLayerRecurse() throws Exception { MimeMessage msg = parseWithRecurse(toStream( "From: <x@example.org>\r\n" + "To: <y@example.org>\r\n" + "Subject: Testmail 2\r\n" + "MIME-Version: 1.0\n" + "Content-Type: multipart/mixed; boundary=frontier\n" + "\n" + "This is a message with multiple parts in MIME format.\n" + "--frontier\n" + "Content-Type: text/plain\n" + "\n" + "This is the body of the message.\n" + "--frontier\n" + "Content-Type: application/octet-stream\n" + "Content-Transfer-Encoding: base64\n" + "\n" + "PGh0bWw+CiAgPGhlYWQ+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPHA+VGhpcyBpcyB0aGUg\n" + "Ym9keSBvZiB0aGUgbWVzc2FnZS48L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg=\n" + "--frontier--")); checkAddresses(msg.getFrom(), "x@example.org"); checkAddresses(msg.getRecipients(RecipientType.TO), "y@example.org"); assertEquals("Testmail 2", msg.getSubject()); assertEquals("multipart/mixed; boundary=frontier", msg.getContentType()); checkLeafParts(msg, "This is the body of the message.", "<html>\n" + " <head>\n" + " </head>\n" + " <body>\n" + " <p>This is the body of the message.</p>\n" + " </body>\n" + "</html>\n" + ""); } public static void testMultipartTwoLayersRecurse() throws Exception { MimeMessage msg = parseWithRecurse(toStream( "From: <x@example.org>\r\n" + "To: <y@example.org>\r\n" + "Subject: Testmail 2\r\n" + "MIME-Version: 1.0\n" + "Content-Type: multipart/mixed; boundary=1\n" + "\n" + "This is a message with multiple parts in MIME format.\n" + "--1\n" + "Content-Type: text/plain\n" + "\n" + "some text in the first part\n" + "--1\n" + "Content-Type: multipart/alternative; boundary=2\n" + "\n" + "--2\n" + "Content-Type: text/plain\n" + "\n" + "alternative 1\n" + "--2\n" + "Content-Type: text/plain\n" + "\n" + "alternative 2\n" + "--2--\n" + "--1--")); checkAddresses(msg.getFrom(), "x@example.org"); checkAddresses(msg.getRecipients(RecipientType.TO), "y@example.org"); assertEquals("Testmail 2", msg.getSubject()); assertEquals("multipart/mixed; boundary=1", msg.getContentType()); checkLeafParts(msg, "some text in the first part", "alternative 1", "alternative 2"); } }