summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/com/android/email/LegacyConversions.java77
-rw-r--r--tests/src/com/android/email/LegacyConversionsTest.java88
2 files changed, 138 insertions, 27 deletions
diff --git a/src/com/android/email/LegacyConversions.java b/src/com/android/email/LegacyConversions.java
index 76f757634..528358497 100644
--- a/src/com/android/email/LegacyConversions.java
+++ b/src/com/android/email/LegacyConversions.java
@@ -45,6 +45,7 @@ import com.android.emailcommon.provider.Mailbox;
import com.android.emailcommon.utility.AttachmentUtilities;
import com.android.mail.providers.UIProvider;
import com.android.mail.utils.LogUtils;
+import com.google.common.annotations.VisibleForTesting;
import org.apache.commons.io.IOUtils;
@@ -184,29 +185,19 @@ public class LegacyConversions {
}
/**
- * Add a single attachment part to the message
- *
- * This will skip adding attachments if they are already found in the attachments table.
- * The heuristic for this will fail (false-positive) if two identical attachments are
- * included in a single POP3 message.
- * TODO: Fix that, by (elsewhere) simulating an mLocation value based on the attachments
- * position within the list of multipart/mixed elements. This would make every POP3 attachment
- * unique, and might also simplify the code (since we could just look at the positions, and
- * ignore the filename, etc.)
+ * Convert a MIME Part object into an Attachment object. Separated for unit testing.
*
- * TODO: Take a closer look at encoding and deal with it if necessary.
- *
- * @param context a context for file operations
- * @param localMessage the attachments will be built against this message
- * @param part a single attachment part from POP or IMAP
+ * @param part MIME part object to convert
+ * @return Populated Account object
+ * @throws MessagingException
*/
- public static void addOneAttachment(final Context context,
- final EmailContent.Message localMessage, final Part part)
- throws MessagingException, IOException {
+ @VisibleForTesting
+ protected static Attachment mimePartToAttachment(final Part part) throws MessagingException {
// Transfer fields from mime format to provider format
final String contentType = MimeUtility.unfoldAndDecode(part.getContentType());
+
String name = MimeUtility.getHeaderParameter(contentType, "name");
- if (name == null) {
+ if (TextUtils.isEmpty(name)) {
final String contentDisposition = MimeUtility.unfoldAndDecode(part.getDisposition());
name = MimeUtility.getHeaderParameter(contentDisposition, "filename");
}
@@ -214,10 +205,15 @@ public class LegacyConversions {
// Incoming attachment: Try to pull size from disposition (if not downloaded yet)
long size = 0;
final String disposition = part.getDisposition();
- if (disposition != null) {
+ if (!TextUtils.isEmpty(disposition)) {
String s = MimeUtility.getHeaderParameter(disposition, "size");
- if (s != null) {
- size = Long.parseLong(s);
+ if (!TextUtils.isEmpty(s)) {
+ try {
+ size = Long.parseLong(s);
+ } catch (final NumberFormatException e) {
+ LogUtils.d(LogUtils.TAG, e, "Could not decode size \"%s\" from attachment part",
+ size);
+ }
}
}
@@ -226,17 +222,43 @@ public class LegacyConversions {
final String[] partIds = part.getHeader(MimeHeader.HEADER_ANDROID_ATTACHMENT_STORE_DATA);
final String partId = partIds != null ? partIds[0] : null;
+ final Attachment localAttachment = new Attachment();
+
// Run the mime type through inferMimeType in case we have something generic and can do
// better using the filename extension
- final Attachment localAttachment = new Attachment();
localAttachment.mMimeType = AttachmentUtilities.inferMimeType(name, part.getMimeType());
localAttachment.mFileName = name;
- localAttachment.mSize = size; // May be reset below if file handled
+ localAttachment.mSize = size;
localAttachment.mContentId = part.getContentId();
- localAttachment.setContentUri(null); // Will be rewritten by saveAttachmentBody
- localAttachment.mMessageKey = localMessage.mId;
+ localAttachment.setContentUri(null); // Will be rewritten by saveAttachmentBody
localAttachment.mLocation = partId;
- localAttachment.mEncoding = "B"; // TODO - convert other known encodings
+ localAttachment.mEncoding = "B"; // TODO - convert other known encodings
+
+ return localAttachment;
+ }
+
+ /**
+ * Add a single attachment part to the message
+ *
+ * This will skip adding attachments if they are already found in the attachments table.
+ * The heuristic for this will fail (false-positive) if two identical attachments are
+ * included in a single POP3 message.
+ * TODO: Fix that, by (elsewhere) simulating an mLocation value based on the attachments
+ * position within the list of multipart/mixed elements. This would make every POP3 attachment
+ * unique, and might also simplify the code (since we could just look at the positions, and
+ * ignore the filename, etc.)
+ *
+ * TODO: Take a closer look at encoding and deal with it if necessary.
+ *
+ * @param context a context for file operations
+ * @param localMessage the attachments will be built against this message
+ * @param part a single attachment part from POP or IMAP
+ */
+ public static void addOneAttachment(final Context context,
+ final EmailContent.Message localMessage, final Part part)
+ throws MessagingException, IOException {
+ final Attachment localAttachment = mimePartToAttachment(part);
+ localAttachment.mMessageKey = localMessage.mId;
localAttachment.mAccountKey = localMessage.mAccountKey;
if (DEBUG_ATTACHMENTS) {
@@ -469,7 +491,8 @@ public class LegacyConversions {
* @param contentId as referenced from cid: uris in the message body (if applicable)
* @param content unencoded bytes
*/
- private static void addAttachmentPart(final Multipart mp, final String contentType,
+ @VisibleForTesting
+ protected static void addAttachmentPart(final Multipart mp, final String contentType,
final Long contentSize, final String filename, final String contentId,
final InputStream content) throws MessagingException {
final Base64Body body = new Base64Body(content);
diff --git a/tests/src/com/android/email/LegacyConversionsTest.java b/tests/src/com/android/email/LegacyConversionsTest.java
index d3e7dcd6a..1656f4b3d 100644
--- a/tests/src/com/android/email/LegacyConversionsTest.java
+++ b/tests/src/com/android/email/LegacyConversionsTest.java
@@ -16,23 +16,41 @@
package com.android.email;
+import android.content.Context;
import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import com.android.emailcommon.TempDirectory;
import com.android.emailcommon.internet.MimeBodyPart;
import com.android.emailcommon.internet.MimeMessage;
+import com.android.emailcommon.internet.MimeMultipart;
import com.android.emailcommon.mail.Address;
import com.android.emailcommon.mail.Message.RecipientType;
import com.android.emailcommon.mail.MessagingException;
+import com.android.emailcommon.mail.Multipart;
import com.android.emailcommon.mail.Part;
import com.android.emailcommon.provider.EmailContent;
+import com.android.emailcommon.provider.EmailContent.Attachment;
import com.android.emailcommon.utility.ConversionUtilities;
import com.android.emailcommon.utility.ConversionUtilities.BodyFieldData;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
+@SmallTest
public class LegacyConversionsTest extends AndroidTestCase {
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ TempDirectory.setTempDirectory(getContext());
+ }
+
/**
* Test basic fields conversion from Store message to Provider message.
*/
@@ -172,4 +190,74 @@ public class LegacyConversionsTest extends AndroidTestCase {
final BodyFieldData data = ConversionUtilities.parseBodyFields(viewables);
assertNull(data.textContent);
}
+
+ /**
+ * Test adding an attachment to a message, and then parsing it back out.
+ * @throws MessagingException
+ */
+ public void testAttachmentRoundTrip() throws Exception {
+ final Context context = getContext();
+ final MimeMultipart mp = new MimeMultipart();
+ mp.setSubType("mixed");
+
+ final long size;
+
+ final File tempDir = context.getCacheDir();
+ if (!tempDir.isDirectory() && !tempDir.mkdirs()) {
+ fail("Could not create temporary directory");
+ }
+
+ final File tempAttachmentFile = File.createTempFile("testAttachmentRoundTrip", ".txt",
+ tempDir);
+
+ try {
+ final OutputStream attOut = new FileOutputStream(tempAttachmentFile);
+ try {
+ attOut.write("TestData".getBytes());
+ } finally {
+ attOut.close();
+ }
+ size = tempAttachmentFile.length();
+ final InputStream attIn = new FileInputStream(tempAttachmentFile);
+ LegacyConversions.addAttachmentPart(mp, "text/plain", size, "test.txt",
+ "testContentId", attIn);
+ } finally {
+ if (!tempAttachmentFile.delete()) {
+ fail("Setup failure: Could not clean up temp file");
+ }
+ }
+
+ final MimeMessage outMessage = new MimeMessage();
+ outMessage.setBody(mp);
+
+ final MimeMessage inMessage;
+
+ final File tempBodyFile = File.createTempFile("testAttachmentRoundTrip", ".eml",
+ context.getCacheDir());
+ try {
+ final OutputStream bodyOut = new FileOutputStream(tempBodyFile);
+ try {
+ outMessage.writeTo(bodyOut);
+ } finally {
+ bodyOut.close();
+ }
+ final InputStream bodyIn = new FileInputStream(tempBodyFile);
+ try {
+ inMessage = new MimeMessage(bodyIn);
+ } finally {
+ bodyIn.close();
+ }
+ } finally {
+ if (!tempBodyFile.delete()) {
+ fail("Setup failure: Could not clean up temp file");
+ }
+ }
+ final Multipart inBody = (Multipart) inMessage.getBody();
+ final Part attPart = inBody.getBodyPart(0);
+ final Attachment att = LegacyConversions.mimePartToAttachment(attPart);
+ assertEquals(att.mFileName, "test.txt");
+ assertEquals(att.mMimeType, "text/plain");
+ assertEquals(att.mSize, size);
+ assertEquals(att.mContentId, "testContentId");
+ }
}