Test encode/decode of attachments

b/15089448

Change-Id: Ifd2afcfb36c9820c5d64ebbcc3230603b2a27089
This commit is contained in:
Tony Mantler 2014-05-21 10:25:08 -07:00
parent 2fbd8c269c
commit 5a93b8f7c6
2 changed files with 145 additions and 34 deletions

View File

@ -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;
@ -183,6 +184,59 @@ public class LegacyConversions {
}
}
/**
* Convert a MIME Part object into an Attachment object. Separated for unit testing.
*
* @param part MIME part object to convert
* @return Populated Account object
* @throws MessagingException
*/
@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 (TextUtils.isEmpty(name)) {
final String contentDisposition = MimeUtility.unfoldAndDecode(part.getDisposition());
name = MimeUtility.getHeaderParameter(contentDisposition, "filename");
}
// Incoming attachment: Try to pull size from disposition (if not downloaded yet)
long size = 0;
final String disposition = part.getDisposition();
if (!TextUtils.isEmpty(disposition)) {
String s = MimeUtility.getHeaderParameter(disposition, "size");
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);
}
}
}
// Get partId for unloaded IMAP attachments (if any)
// This is only provided (and used) when we have structure but not the actual attachment
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
localAttachment.mMimeType = AttachmentUtilities.inferMimeType(name, part.getMimeType());
localAttachment.mFileName = name;
localAttachment.mSize = size;
localAttachment.mContentId = part.getContentId();
localAttachment.setContentUri(null); // Will be rewritten by saveAttachmentBody
localAttachment.mLocation = partId;
localAttachment.mEncoding = "B"; // TODO - convert other known encodings
return localAttachment;
}
/**
* Add a single attachment part to the message
*
@ -203,40 +257,8 @@ public class LegacyConversions {
public static void addOneAttachment(final Context context,
final EmailContent.Message localMessage, final Part part)
throws MessagingException, IOException {
// Transfer fields from mime format to provider format
final String contentType = MimeUtility.unfoldAndDecode(part.getContentType());
String name = MimeUtility.getHeaderParameter(contentType, "name");
if (name == null) {
final String contentDisposition = MimeUtility.unfoldAndDecode(part.getDisposition());
name = MimeUtility.getHeaderParameter(contentDisposition, "filename");
}
// Incoming attachment: Try to pull size from disposition (if not downloaded yet)
long size = 0;
final String disposition = part.getDisposition();
if (disposition != null) {
String s = MimeUtility.getHeaderParameter(disposition, "size");
if (s != null) {
size = Long.parseLong(s);
}
}
// Get partId for unloaded IMAP attachments (if any)
// This is only provided (and used) when we have structure but not the actual attachment
final String[] partIds = part.getHeader(MimeHeader.HEADER_ANDROID_ATTACHMENT_STORE_DATA);
final String partId = partIds != null ? partIds[0] : null;
// 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.mContentId = part.getContentId();
localAttachment.setContentUri(null); // Will be rewritten by saveAttachmentBody
final Attachment localAttachment = mimePartToAttachment(part);
localAttachment.mMessageKey = localMessage.mId;
localAttachment.mLocation = partId;
localAttachment.mEncoding = "B"; // TODO - convert other known encodings
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);

View File

@ -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");
}
}