Home | History | Annotate | Download | only in email
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.email;
     18 
     19 import android.content.Context;
     20 import android.test.AndroidTestCase;
     21 import android.test.suitebuilder.annotation.SmallTest;
     22 
     23 import com.android.emailcommon.TempDirectory;
     24 import com.android.emailcommon.internet.MimeBodyPart;
     25 import com.android.emailcommon.internet.MimeMessage;
     26 import com.android.emailcommon.internet.MimeMultipart;
     27 import com.android.emailcommon.mail.Address;
     28 import com.android.emailcommon.mail.Message.RecipientType;
     29 import com.android.emailcommon.mail.MessagingException;
     30 import com.android.emailcommon.mail.Multipart;
     31 import com.android.emailcommon.mail.Part;
     32 import com.android.emailcommon.provider.EmailContent;
     33 import com.android.emailcommon.provider.EmailContent.Attachment;
     34 import com.android.emailcommon.utility.ConversionUtilities;
     35 import com.android.emailcommon.utility.ConversionUtilities.BodyFieldData;
     36 
     37 import java.io.File;
     38 import java.io.FileInputStream;
     39 import java.io.FileOutputStream;
     40 import java.io.InputStream;
     41 import java.io.OutputStream;
     42 import java.util.ArrayList;
     43 import java.util.Date;
     44 
     45 @SmallTest
     46 public class LegacyConversionsTest extends AndroidTestCase {
     47 
     48     @Override
     49     protected void setUp() throws Exception {
     50         super.setUp();
     51         TempDirectory.setTempDirectory(getContext());
     52     }
     53 
     54     /**
     55      * Test basic fields conversion from Store message to Provider message.
     56      */
     57     public void testUpdateMessageFields_Basic() throws MessagingException {
     58         final MimeMessage message = new MimeMessage();
     59         message.setUid("UID.12345678");
     60         message.setSentDate(new Date(1));
     61         message.setMessageId("Test-Message-ID");
     62         message.setSubject("This is the subject");
     63 
     64         final EmailContent.Message localMessage = new EmailContent.Message();
     65         final boolean result = LegacyConversions.updateMessageFields(localMessage, message, 1, 1);
     66         assertTrue(result);
     67 
     68         assertEquals(message.getUid(), localMessage.mServerId);
     69         assertEquals(message.getSubject(), localMessage.mSubject);
     70         assertEquals(message.getMessageId(), localMessage.mMessageId);
     71         assertEquals(message.getSentDate().getTime(), localMessage.mTimeStamp);
     72     }
     73 
     74     /**
     75      * Test the conversion of plain ASCII (not MIME-encoded) email addresses.
     76      */
     77     public void testUpdateMessageFields_PlainAddresses() throws MessagingException {
     78         // create plain ASCII email addresses
     79         final String fromList = "Sender <sender (at) droid.com>";
     80         final String replyToList = "Reply1 <reply1 (at) droid.com>,Reply2 <reply2 (at) droid.com>";
     81         final String toList = "ToA <toA (at) droid.com>,ToB <toB (at) droid.com>";
     82         final String ccList = "CcA <ccA (at) droid.com>,CcB <ccB (at) droid.com>";
     83         final String bccList = "BccA <bccA (at) droid.com>,Bcc2 <bccB (at) droid.com>";
     84 
     85         // parse the addresses
     86         final Address from = Address.fromHeader(fromList)[0];
     87         final Address[] replies = Address.fromHeader(replyToList);
     88         final Address[] tos = Address.fromHeader(toList);
     89         final Address[] ccs = Address.fromHeader(ccList);
     90         final Address[] bccs = Address.fromHeader(bccList);
     91 
     92         // make a message with the email addresses
     93         final MimeMessage message = new MimeMessage();
     94         message.setFrom(from);
     95         message.setReplyTo(replies);
     96         message.setRecipients(RecipientType.TO, tos);
     97         message.setRecipients(RecipientType.CC, ccs);
     98         message.setRecipients(RecipientType.BCC, bccs);
     99 
    100         // convert the message to a local message using the conversation method
    101         final EmailContent.Message localMessage = new EmailContent.Message();
    102         final boolean result = LegacyConversions.updateMessageFields(localMessage, message, 1, 1);
    103         assertTrue(result);
    104 
    105         // verify that we will store the email addresses in decoded form
    106         assertEquals(fromList, localMessage.mFrom);
    107         assertEquals(replyToList, localMessage.mReplyTo);
    108         assertEquals(toList, localMessage.mTo);
    109         assertEquals(ccList, localMessage.mCc);
    110         assertEquals(bccList, localMessage.mBcc);
    111     }
    112 
    113     /**
    114      * Test the conversion of MIME-encoded non-ASCII email addresses.
    115      */
    116     public void testUpdateMessageFields_EncodedAddresses() throws MessagingException {
    117         final String e = "=?EUC-KR?B?uvG50Ln4yKO4pg==?="; // Mime Encoded value of 
    118         final String d = "\uBE44\uBC00\uBC88\uD638\uB97C"; // Mime Decoded value of e
    119 
    120         // create the email address in encoded form
    121         String fromList = String.format("%s <sender (at) droid.com>", e);
    122         String replyToList = String.format("%s <reply1 (at) droid.com>,%s <reply2 (at) droid.com>", e, e);
    123         String toList = String.format("%s <toA (at) droid.com>,%s <toB (at) droid.com>", e, e);
    124         String ccList = String.format("%s <ccA (at) droid.com>,%s <ccB (at) droid.com>", e, e);
    125         String bccList = String.format("%s <bccA (at) droid.com>,%s <bccB (at) droid.com>", e, e);
    126 
    127         // parse the encoded addresses
    128         final Address from = Address.fromHeader(fromList)[0];
    129         final Address[] replies = Address.fromHeader(replyToList);
    130         final Address[] tos = Address.fromHeader(toList);
    131         final Address[] ccs = Address.fromHeader(ccList);
    132         final Address[] bccs = Address.fromHeader(bccList);
    133 
    134         // make a message with the email addresses
    135         final MimeMessage message = new MimeMessage();
    136         message.setFrom(from);
    137         message.setReplyTo(replies);
    138         message.setRecipients(RecipientType.TO, tos);
    139         message.setRecipients(RecipientType.CC, ccs);
    140         message.setRecipients(RecipientType.BCC, bccs);
    141 
    142         // convert the message to a local message using the conversion method
    143         final EmailContent.Message localMessage = new EmailContent.Message();
    144         final boolean result = LegacyConversions.updateMessageFields(localMessage, message, 1, 1);
    145         assertTrue(result);
    146 
    147         // verify that we will store the email addresses in decoded form
    148         String decodedFrom = String.format("%s <sender (at) droid.com>", d);
    149         String decodedReply = String.format("%s <reply1 (at) droid.com>,%s <reply2 (at) droid.com>", d, d);
    150         String decodedTo = String.format("%s <toA (at) droid.com>,%s <toB (at) droid.com>", d, d);
    151         String decodedCc = String.format("%s <ccA (at) droid.com>,%s <ccB (at) droid.com>", d, d);
    152         String decodedBcc = String.format("%s <bccA (at) droid.com>,%s <bccB (at) droid.com>", d, d);
    153 
    154         assertEquals(decodedFrom, localMessage.mFrom);
    155         assertEquals(decodedReply, localMessage.mReplyTo);
    156         assertEquals(decodedTo, localMessage.mTo);
    157         assertEquals(decodedCc, localMessage.mCc);
    158         assertEquals(decodedBcc, localMessage.mBcc);
    159     }
    160 
    161     /**
    162      * Test basic conversion from Store message to Provider message, when the provider message
    163      * does not have a proper message-id.
    164      */
    165     public void testUpdateMessageFields_NoMessageId() throws MessagingException {
    166         final MimeMessage message = new MimeMessage();
    167         // set, then remove the message id
    168         message.setMessageId("Test-Message-ID");
    169         message.removeHeader("Message-ID");
    170 
    171         // create a local message with an ID
    172         final EmailContent.Message localMessage = new EmailContent.Message();
    173         localMessage.mMessageId = "Test-Message-ID-Second";
    174 
    175         final boolean result = LegacyConversions.updateMessageFields(localMessage, message, 1, 1);
    176         assertTrue(result);
    177         assertEquals("Test-Message-ID-Second", localMessage.mMessageId);
    178     }
    179 
    180     /**
    181      * Basic test of body parts conversion from Store message to Provider message.
    182      * This tests that a null body part simply results in null text, and does not crash
    183      * or return "null".
    184      */
    185     public void testUpdateBodyFieldsNullText() throws MessagingException {
    186         ArrayList<Part> viewables = new ArrayList<Part>();
    187         viewables.add(new MimeBodyPart(null, "text/plain"));
    188 
    189         // a "null" body part of type text/plain should result in a null mTextContent
    190         final BodyFieldData data = ConversionUtilities.parseBodyFields(viewables);
    191         assertNull(data.textContent);
    192     }
    193 
    194     /**
    195      * Test adding an attachment to a message, and then parsing it back out.
    196      * @throws MessagingException
    197      */
    198     public void testAttachmentRoundTrip() throws Exception {
    199         final Context context = getContext();
    200         final MimeMultipart mp = new MimeMultipart();
    201         mp.setSubType("mixed");
    202 
    203         final long size;
    204 
    205         final File tempDir = context.getCacheDir();
    206         if (!tempDir.isDirectory() && !tempDir.mkdirs()) {
    207             fail("Could not create temporary directory");
    208         }
    209 
    210         final File tempAttachmentFile = File.createTempFile("testAttachmentRoundTrip", ".txt",
    211                 tempDir);
    212 
    213         try {
    214             final OutputStream attOut = new FileOutputStream(tempAttachmentFile);
    215             try {
    216                 attOut.write("TestData".getBytes());
    217             } finally {
    218                 attOut.close();
    219             }
    220             size = tempAttachmentFile.length();
    221             final InputStream attIn = new FileInputStream(tempAttachmentFile);
    222             LegacyConversions.addAttachmentPart(mp, "text/plain", size, "test.txt",
    223                     "testContentId", attIn);
    224         } finally {
    225             if (!tempAttachmentFile.delete()) {
    226                 fail("Setup failure: Could not clean up temp file");
    227             }
    228         }
    229 
    230         final MimeMessage outMessage = new MimeMessage();
    231         outMessage.setBody(mp);
    232 
    233         final MimeMessage inMessage;
    234 
    235         final File tempBodyFile = File.createTempFile("testAttachmentRoundTrip", ".eml",
    236                 context.getCacheDir());
    237         try {
    238             final OutputStream bodyOut = new FileOutputStream(tempBodyFile);
    239             try {
    240                 outMessage.writeTo(bodyOut);
    241             } finally {
    242                 bodyOut.close();
    243             }
    244             final InputStream bodyIn = new FileInputStream(tempBodyFile);
    245             try {
    246                 inMessage = new MimeMessage(bodyIn);
    247             } finally {
    248                 bodyIn.close();
    249             }
    250         } finally {
    251             if (!tempBodyFile.delete()) {
    252                 fail("Setup failure: Could not clean up temp file");
    253             }
    254         }
    255         final Multipart inBody = (Multipart) inMessage.getBody();
    256         final Part attPart = inBody.getBodyPart(0);
    257         final Attachment att = LegacyConversions.mimePartToAttachment(attPart);
    258         assertEquals(att.mFileName, "test.txt");
    259         assertEquals(att.mMimeType, "text/plain");
    260         assertEquals(att.mSize, size);
    261         assertEquals(att.mContentId, "testContentId");
    262     }
    263 }
    264