From 074159f442591e1f640bd7a947286d4293bee1f7 Mon Sep 17 00:00:00 2001 From: Joe Steele Date: Mon, 2 Sep 2013 19:55:10 -0400 Subject: [PATCH] Unit test for recursive 8bit -> 7bit message conversion --- tests/src/com/fsck/k9/mail/MessageTest.java | 380 ++++++++++++++++++++ 1 file changed, 380 insertions(+) create mode 100644 tests/src/com/fsck/k9/mail/MessageTest.java diff --git a/tests/src/com/fsck/k9/mail/MessageTest.java b/tests/src/com/fsck/k9/mail/MessageTest.java new file mode 100644 index 000000000..175d4eb5d --- /dev/null +++ b/tests/src/com/fsck/k9/mail/MessageTest.java @@ -0,0 +1,380 @@ +package com.fsck.k9.mail; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import org.apache.commons.io.IOUtils; +import org.apache.james.mime4j.codec.Base64InputStream; +import org.apache.james.mime4j.util.MimeUtil; + +import android.test.AndroidTestCase; + +import com.fsck.k9.mail.Message.RecipientType; +import com.fsck.k9.mail.internet.BinaryTempFileBody; +import com.fsck.k9.mail.internet.BinaryTempFileMessageBody; +import com.fsck.k9.mail.internet.MimeBodyPart; +import com.fsck.k9.mail.internet.MimeHeader; +import com.fsck.k9.mail.internet.MimeMessage; +import com.fsck.k9.mail.internet.MimeMultipart; +import com.fsck.k9.mail.internet.MimeUtility; +import com.fsck.k9.mail.internet.TextBody; + +public class MessageTest extends AndroidTestCase { + + private static final String EIGHT_BIT_RESULT = + "From: from@example.com\r\n" + + "To: to@example.com\r\n" + + "Subject: Test Message\r\n" + + "Date: Wed, 28 Aug 2013 08:51:09 -0400\r\n" + + "MIME-Version: 1.0\r\n" + + "Content-Type: multipart/mixed; boundary=\"----Boundary103\"\r\n" + + "Content-Transfer-Encoding: 8bit\r\n" + + "\r\n" + + "------Boundary103\r\n" + + "Content-Type: text/plain;\n" + + " charset=utf-8\r\n" + + "Content-Transfer-Encoding: 8bit\r\n" + + "\r\n" + + "Testing.\r\n" + + "This is a text body with some greek characters.\r\n" + + "αβγδεζηθ\r\n" + + "End of test.\r\n" + + "\r\n" + + "------Boundary103\r\n" + + "Content-Type: text/plain;\n" + + " charset=utf-8\r\n" + + "Content-Transfer-Encoding: quoted-printable\r\n" + + "\r\n" + + "Testing=2E\r\n" + + "This is a text body with some greek characters=2E\r\n" + + "=CE=B1=CE=B2=CE=B3=CE=B4=CE=B5=CE=B6=CE=B7=CE=B8\r\n" + + "End of test=2E\r\n" + + "\r\n" + + "------Boundary103\r\n" + + "Content-Type: application/octet-stream\r\n" + + "Content-Transfer-Encoding: base64\r\n" + + "\r\n" + + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\r\n" + + "\r\n" + + "------Boundary103\r\n" + + "Content-Type: message/rfc822\r\n" + + "Content-Disposition: attachment\r\n" + + "Content-Transfer-Encoding: 8bit\r\n" + + "\r\n" + + "From: from@example.com\r\n" + + "To: to@example.com\r\n" + + "Subject: Test Message\r\n" + + "Date: Wed, 28 Aug 2013 08:51:09 -0400\r\n" + + "MIME-Version: 1.0\r\n" + + "Content-Type: multipart/mixed; boundary=\"----Boundary102\"\r\n" + + "Content-Transfer-Encoding: 8bit\r\n" + + "\r\n" + + "------Boundary102\r\n" + + "Content-Type: text/plain;\n" + + " charset=utf-8\r\n" + + "Content-Transfer-Encoding: 8bit\r\n" + + "\r\n" + + "Testing.\r\n" + + "This is a text body with some greek characters.\r\n" + + "αβγδεζηθ\r\n" + + "End of test.\r\n" + + "\r\n" + + "------Boundary102\r\n" + + "Content-Type: text/plain;\n" + + " charset=utf-8\r\n" + + "Content-Transfer-Encoding: quoted-printable\r\n" + + "\r\n" + + "Testing=2E\r\n" + + "This is a text body with some greek characters=2E\r\n" + + "=CE=B1=CE=B2=CE=B3=CE=B4=CE=B5=CE=B6=CE=B7=CE=B8\r\n" + + "End of test=2E\r\n" + + "\r\n" + + "------Boundary102\r\n" + + "Content-Type: application/octet-stream\r\n" + + "Content-Transfer-Encoding: base64\r\n" + + "\r\n" + + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\r\n" + + "\r\n" + + "------Boundary102\r\n" + + "Content-Type: message/rfc822\r\n" + + "Content-Disposition: attachment\r\n" + + "Content-Transfer-Encoding: 8bit\r\n" + + "\r\n" + + "From: from@example.com\r\n" + + "To: to@example.com\r\n" + + "Subject: Test Message\r\n" + + "Date: Wed, 28 Aug 2013 08:51:09 -0400\r\n" + + "MIME-Version: 1.0\r\n" + + "Content-Type: multipart/mixed; boundary=\"----Boundary101\"\r\n" + + "Content-Transfer-Encoding: 8bit\r\n" + + "\r\n" + + "------Boundary101\r\n" + + "Content-Type: text/plain;\n" + + " charset=utf-8\r\n" + + "Content-Transfer-Encoding: 8bit\r\n" + + "\r\n" + + "Testing.\r\n" + + "This is a text body with some greek characters.\r\n" + + "αβγδεζηθ\r\n" + + "End of test.\r\n" + + "\r\n" + + "------Boundary101\r\n" + + "Content-Type: text/plain;\n" + + " charset=utf-8\r\n" + + "Content-Transfer-Encoding: quoted-printable\r\n" + + "\r\n" + + "Testing=2E\r\n" + + "This is a text body with some greek characters=2E\r\n" + + "=CE=B1=CE=B2=CE=B3=CE=B4=CE=B5=CE=B6=CE=B7=CE=B8\r\n" + + "End of test=2E\r\n" + + "\r\n" + + "------Boundary101\r\n" + + "Content-Type: application/octet-stream\r\n" + + "Content-Transfer-Encoding: base64\r\n" + + "\r\n" + + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\r\n" + + "\r\n" + + "------Boundary101--\r\n" + + "\r\n" + + "------Boundary102--\r\n" + + "\r\n" + + "------Boundary103--\r\n"; + + private static final String SEVEN_BIT_RESULT = + "From: from@example.com\r\n" + + "To: to@example.com\r\n" + + "Subject: Test Message\r\n" + + "Date: Wed, 28 Aug 2013 08:51:09 -0400\r\n" + + "MIME-Version: 1.0\r\n" + + "Content-Type: multipart/mixed; boundary=\"----Boundary103\"\r\n" + + "Content-Transfer-Encoding: 7bit\r\n" + + "\r\n" + + "------Boundary103\r\n" + + "Content-Type: text/plain;\n" + + " charset=utf-8\r\n" + + "Content-Transfer-Encoding: quoted-printable\r\n" + + "\r\n" + + "Testing=2E\r\n" + + "This is a text body with some greek characters=2E\r\n" + + "=CE=B1=CE=B2=CE=B3=CE=B4=CE=B5=CE=B6=CE=B7=CE=B8\r\n" + + "End of test=2E\r\n" + + "\r\n" + + "------Boundary103\r\n" + + "Content-Type: text/plain;\n" + + " charset=utf-8\r\n" + + "Content-Transfer-Encoding: quoted-printable\r\n" + + "\r\n" + + "Testing=2E\r\n" + + "This is a text body with some greek characters=2E\r\n" + + "=CE=B1=CE=B2=CE=B3=CE=B4=CE=B5=CE=B6=CE=B7=CE=B8\r\n" + + "End of test=2E\r\n" + + "\r\n" + + "------Boundary103\r\n" + + "Content-Type: application/octet-stream\r\n" + + "Content-Transfer-Encoding: base64\r\n" + + "\r\n" + + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\r\n" + + "\r\n" + + "------Boundary103\r\n" + + "Content-Type: message/rfc822\r\n" + + "Content-Disposition: attachment\r\n" + + "Content-Transfer-Encoding: 7bit\r\n" + + "\r\n" + + "From: from@example.com\r\n" + + "To: to@example.com\r\n" + + "Subject: Test Message\r\n" + + "Date: Wed, 28 Aug 2013 08:51:09 -0400\r\n" + + "MIME-Version: 1.0\r\n" + + "Content-Type: multipart/mixed; boundary=\"----boundary102\"\r\n" + + "Content-Transfer-Encoding: 7bit\r\n" + + "\r\n" + + "------boundary102\r\n" + + "Content-Type: text/plain; charset=utf-8\r\n" + + "Content-Transfer-Encoding: quoted-printable\r\n" + + "\r\n" + + "Testing=2E\r\n" + + "This is a text body with some greek characters=2E\r\n" + + "=CE=B1=CE=B2=CE=B3=CE=B4=CE=B5=CE=B6=CE=B7=CE=B8\r\n" + + "End of test=2E\r\n" + + "\r\n" + + "------boundary102\r\n" + + "Content-Type: text/plain; charset=utf-8\r\n" + + "Content-Transfer-Encoding: quoted-printable\r\n" + + "\r\n" + + "Testing=2E\r\n" + + "This is a text body with some greek characters=2E\r\n" + + "=CE=B1=CE=B2=CE=B3=CE=B4=CE=B5=CE=B6=CE=B7=CE=B8\r\n" + + "End of test=2E\r\n" + + "\r\n" + + "------boundary102\r\n" + + "Content-Type: application/octet-stream\r\n" + + "Content-Transfer-Encoding: base64\r\n" + + "\r\n" + + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\r\n" + + "\r\n" + + "------boundary102\r\n" + + "Content-Type: message/rfc822\r\n" + + "Content-Disposition: attachment\r\n" + + "Content-Transfer-Encoding: 7bit\r\n" + + "\r\n" + + "From: from@example.com\r\n" + + "To: to@example.com\r\n" + + "Subject: Test Message\r\n" + + "Date: Wed, 28 Aug 2013 08:51:09 -0400\r\n" + + "MIME-Version: 1.0\r\n" + + "Content-Type: multipart/mixed; boundary=\"----boundary101\"\r\n" + + "Content-Transfer-Encoding: 7bit\r\n" + + "\r\n" + + "------boundary101\r\n" + + "Content-Type: text/plain; charset=utf-8\r\n" + + "Content-Transfer-Encoding: quoted-printable\r\n" + + "\r\n" + + "Testing=2E\r\n" + + "This is a text body with some greek characters=2E\r\n" + + "=CE=B1=CE=B2=CE=B3=CE=B4=CE=B5=CE=B6=CE=B7=CE=B8\r\n" + + "End of test=2E\r\n" + + "\r\n" + + "------boundary101\r\n" + + "Content-Type: text/plain; charset=utf-8\r\n" + + "Content-Transfer-Encoding: quoted-printable\r\n" + + "\r\n" + + "Testing=2E\r\n" + + "This is a text body with some greek characters=2E\r\n" + + "=CE=B1=CE=B2=CE=B3=CE=B4=CE=B5=CE=B6=CE=B7=CE=B8\r\n" + + "End of test=2E\r\n" + + "\r\n" + + "------boundary101\r\n" + + "Content-Type: application/octet-stream\r\n" + + "Content-Transfer-Encoding: base64\r\n" + + "\r\n" + + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\r\n" + + "\r\n" + + "------boundary101--\r\n" + + "\r\n" + + "------boundary102--\r\n" + + "\r\n" + + "------Boundary103--\r\n"; + + private int mMimeBoundary; + + public MessageTest() { + super(); + } + + public void testMessage() throws MessagingException, IOException { + MimeMessage message; + ByteArrayOutputStream out; + + BinaryTempFileBody.setTempDirectory(getContext().getCacheDir()); + + mMimeBoundary = 101; + message = nestedMessage(nestedMessage(sampleMessage())); + out = new ByteArrayOutputStream(); + message.writeTo(out); + assertEquals(EIGHT_BIT_RESULT, out.toString()); + + mMimeBoundary = 101; + message = nestedMessage(nestedMessage(sampleMessage())); + message.setUsing7bitTransport(); + out = new ByteArrayOutputStream(); + message.writeTo(out); + assertEquals(SEVEN_BIT_RESULT, out.toString()); + } + + private MimeMessage nestedMessage(MimeMessage subMessage) + throws MessagingException, IOException { + BinaryTempFileMessageBody tempMessageBody = new BinaryTempFileMessageBody(); + tempMessageBody.setEncoding(MimeUtil.ENC_8BIT); + + OutputStream out = tempMessageBody.getOutputStream(); + try { + subMessage.writeTo(out); + } finally { + out.close(); + } + + MimeBodyPart bodyPart = new MimeBodyPart(tempMessageBody, "message/rfc822"); + bodyPart.setHeader(MimeHeader.HEADER_CONTENT_DISPOSITION, "attachment"); + bodyPart.setEncoding(MimeUtil.ENC_8BIT); + + MimeMessage parentMessage = sampleMessage(); + ((Multipart) parentMessage.getBody()).addBodyPart(bodyPart); + + return parentMessage; + } + + private MimeMessage sampleMessage() throws MessagingException, IOException { + MimeMessage message = new MimeMessage(); + message.setFrom(new Address("from@example.com")); + message.setRecipient(RecipientType.TO, new Address("to@example.com")); + message.setSubject("Test Message"); + message.setHeader("Date", "Wed, 28 Aug 2013 08:51:09 -0400"); + message.setEncoding(MimeUtil.ENC_8BIT); + + NonRandomMimeMultipartTest multipartBody = new NonRandomMimeMultipartTest(); + multipartBody.setSubType("mixed"); + multipartBody.addBodyPart(textBodyPart(MimeUtil.ENC_8BIT)); + multipartBody.addBodyPart(textBodyPart(MimeUtil.ENC_QUOTED_PRINTABLE)); + multipartBody.addBodyPart(binaryBodyPart()); + message.setBody(multipartBody); + + return message; + } + + private MimeBodyPart binaryBodyPart() throws IOException, + MessagingException { + String encodedTestString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + + "abcdefghijklmnopqrstuvwxyz0123456789+/"; + + BinaryTempFileBody tempFileBody = new BinaryTempFileBody(); + + InputStream in = new Base64InputStream(new ByteArrayInputStream( + encodedTestString.getBytes("UTF-8"))); + + OutputStream out = tempFileBody.getOutputStream(); + try { + IOUtils.copy(in, out); + } finally { + out.close(); + } + + MimeBodyPart bodyPart = new MimeBodyPart(tempFileBody, + "application/octet-stream"); + bodyPart.setEncoding(MimeUtil.ENC_BASE64); + + return bodyPart; + } + + private MimeBodyPart textBodyPart(String encoding) + throws MessagingException { + TextBody textBody = new TextBody( + "Testing.\r\n" + + "This is a text body with some greek characters.\r\n" + + "αβγδεζηθ\r\n" + + "End of test.\r\n"); + textBody.setCharset("utf-8"); + MimeBodyPart bodyPart = new MimeBodyPart(textBody, "text/plain"); + MimeUtility.setCharset("utf-8", bodyPart); + bodyPart.setEncoding(encoding); + return bodyPart; + } + + private class NonRandomMimeMultipartTest extends MimeMultipart { + + public NonRandomMimeMultipartTest() throws MessagingException { + super(); + } + + @Override + public String generateBoundary() { + StringBuilder sb = new StringBuilder(); + sb.append("----Boundary"); + sb.append(Integer.toString(mMimeBoundary++)); + return sb.toString(); + } + + } + +}