13f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler/* 23f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler * Copyright (C) 2009 The Android Open Source Project 33f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler * 43f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler * Licensed under the Apache License, Version 2.0 (the "License"); 53f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler * you may not use this file except in compliance with the License. 63f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler * You may obtain a copy of the License at 73f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler * 83f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler * http://www.apache.org/licenses/LICENSE-2.0 93f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler * 103f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler * Unless required by applicable law or agreed to in writing, software 113f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler * distributed under the License is distributed on an "AS IS" BASIS, 123f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler * See the License for the specific language governing permissions and 143f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler * limitations under the License. 153f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler */ 163f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler 173f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadlerpackage com.android.email; 183f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler 19515d830e8755d3674e04bcc60d7f85b4fa7fb202Jerry Xieimport android.content.ContentUris; 20515d830e8755d3674e04bcc60d7f85b4fa7fb202Jerry Xieimport android.content.Context; 21515d830e8755d3674e04bcc60d7f85b4fa7fb202Jerry Xieimport android.database.Cursor; 22515d830e8755d3674e04bcc60d7f85b4fa7fb202Jerry Xieimport android.net.Uri; 23515d830e8755d3674e04bcc60d7f85b4fa7fb202Jerry Xieimport android.test.ProviderTestCase2; 2489b8fdca1841efd832e05cee877ab3eaf3780aaeJerry Xieimport android.test.suitebuilder.annotation.Suppress; 25515d830e8755d3674e04bcc60d7f85b4fa7fb202Jerry Xie 2675a873be8420e50f0aeb5a77716358ee0ca66b01Marc Blankimport com.android.email.provider.EmailProvider; 2775a873be8420e50f0aeb5a77716358ee0ca66b01Marc Blankimport com.android.email.provider.ProviderTestUtils; 282193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.internet.MimeBodyPart; 292193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.internet.MimeHeader; 302193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.internet.MimeMessage; 312193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.internet.MimeUtility; 322193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.internet.TextBody; 332193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.mail.Address; 342193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.mail.BodyPart; 352193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.mail.Flag; 362193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.mail.Message; 372193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.mail.Message.RecipientType; 3831d9acbf0623872f9d4a2b3210b5970854b654c7Marc Blankimport com.android.emailcommon.mail.MessageTestUtils; 392193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.mail.MessageTestUtils.MessageBuilder; 402193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.mail.MessageTestUtils.MultipartBuilder; 4131d9acbf0623872f9d4a2b3210b5970854b654c7Marc Blankimport com.android.emailcommon.mail.MessagingException; 4231d9acbf0623872f9d4a2b3210b5970854b654c7Marc Blankimport com.android.emailcommon.mail.Part; 43a7bc0319a75184ad706bb35c049af107ac3688e6Marc Blankimport com.android.emailcommon.provider.EmailContent; 44a7bc0319a75184ad706bb35c049af107ac3688e6Marc Blankimport com.android.emailcommon.provider.EmailContent.Attachment; 458a574694606f0e5d781334d0d426fc379c51f3edMarc Blankimport com.android.emailcommon.utility.ConversionUtilities; 46515d830e8755d3674e04bcc60d7f85b4fa7fb202Jerry Xieimport com.android.emailcommon.utility.ConversionUtilities.BodyFieldData; 473f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler 483f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadlerimport java.io.IOException; 493f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadlerimport java.util.ArrayList; 50eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadlerimport java.util.Date; 513f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler 523f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler/** 533f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler * Tests of the Legacy Conversions code (used by MessagingController). 540993190cafebc107bd27a26996b5d63d4a4ede10Marc Blank * 553f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler * NOTE: It would probably make sense to rewrite this using a MockProvider, instead of the 563f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler * ProviderTestCase (which is a real provider running on a temp database). This would be more of 573f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler * a true "unit test". 580993190cafebc107bd27a26996b5d63d4a4ede10Marc Blank * 593f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler * You can run this entire test case with: 603f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler * runtest -c com.android.email.LegacyConversionsTests email 613f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler */ 6289b8fdca1841efd832e05cee877ab3eaf3780aaeJerry Xie@Suppress 633f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadlerpublic class LegacyConversionsTests extends ProviderTestCase2<EmailProvider> { 643f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler 65eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler private static final String UID = "UID.12345678"; 66eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler private static final String SENDER = "sender@android.com"; 67eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler private static final String RECIPIENT_TO = "recipient-to@android.com"; 68eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler private static final String RECIPIENT_CC = "recipient-cc@android.com"; 69eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler private static final String RECIPIENT_BCC = "recipient-bcc@android.com"; 70eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler private static final String REPLY_TO = "reply-to@android.com"; 71eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler private static final String SUBJECT = "This is the subject"; 72eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler private static final String MESSAGE_ID = "Test-Message-ID"; 73eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler private static final String MESSAGE_ID_2 = "Test-Message-ID-Second"; 74eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler 753f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler EmailProvider mProvider; 763f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler Context mProviderContext; 773f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler Context mContext; 785e91cccd4b530eb2aeace5c5bf4f3328a5b5d69dAndrew Stadler Preferences mPreferences = null; 793f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler 803f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler public LegacyConversionsTests() { 8131d9acbf0623872f9d4a2b3210b5970854b654c7Marc Blank super(EmailProvider.class, EmailContent.AUTHORITY); 823f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler } 833f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler 843f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler @Override 853f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler public void setUp() throws Exception { 863f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler super.setUp(); 873f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler mProviderContext = getMockContext(); 883f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler mContext = getContext(); 893f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler } 903f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler 913f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler /** 923f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler * TODO: basic Legacy -> Provider Message conversions 933f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler * TODO: basic Legacy -> Provider Body conversions 943f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler * TODO: rainy day tests of all kinds 953f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler */ 963f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler 973f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler /** 98eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler * Test basic conversion from Store message to Provider message 99eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler * 100eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler * TODO: Not a complete test of all fields, and some fields need special tests (e.g. flags) 101eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler * TODO: There are many special cases in the tested function, that need to be 102eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler * tested here as well. 103eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler */ 104eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler public void testUpdateMessageFields() throws MessagingException { 105eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler MimeMessage message = buildTestMessage(RECIPIENT_TO, RECIPIENT_CC, RECIPIENT_BCC, 106eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler REPLY_TO, SENDER, SUBJECT, null); 107eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler EmailContent.Message localMessage = new EmailContent.Message(); 108eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler 109eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler boolean result = LegacyConversions.updateMessageFields(localMessage, message, 1, 1); 110eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler assertTrue(result); 111eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler checkProviderMessage("testUpdateMessageFields", message, localMessage); 112eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler } 113eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler 114eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler /** 115eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler * Test basic conversion from Store message to Provider message, when the provider message 116eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler * does not have a proper message-id. 117eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler */ 118eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler public void testUpdateMessageFieldsNoMessageId() throws MessagingException { 119eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler MimeMessage message = buildTestMessage(RECIPIENT_TO, RECIPIENT_CC, RECIPIENT_BCC, 120eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler REPLY_TO, SENDER, SUBJECT, null); 121eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler EmailContent.Message localMessage = new EmailContent.Message(); 122eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler 123eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler // If the source message-id is null, the target should be left as-is 124eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler localMessage.mMessageId = MESSAGE_ID_2; 125eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler message.removeHeader("Message-ID"); 126eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler 127eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler boolean result = LegacyConversions.updateMessageFields(localMessage, message, 1, 1); 128eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler assertTrue(result); 129eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler assertEquals(MESSAGE_ID_2, localMessage.mMessageId); 130eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler } 131eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler 132eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler /** 133eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler * Build a lightweight Store message with simple field population 134eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler */ 135eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler private MimeMessage buildTestMessage(String to, String cc, String bcc, String replyTo, 136eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler String sender, String subject, String content) throws MessagingException { 137eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler MimeMessage message = new MimeMessage(); 138eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler 139eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler if (to != null) { 140eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler Address[] addresses = Address.parse(to); 141eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler message.setRecipients(RecipientType.TO, addresses); 142eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler } 143eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler if (cc != null) { 144eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler Address[] addresses = Address.parse(cc); 145eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler message.setRecipients(RecipientType.CC, addresses); 146eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler } 147eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler if (bcc != null) { 148eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler Address[] addresses = Address.parse(bcc); 149eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler message.setRecipients(RecipientType.BCC, addresses); 150eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler } 151eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler if (replyTo != null) { 152eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler Address[] addresses = Address.parse(replyTo); 153eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler message.setReplyTo(addresses); 154eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler } 155eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler if (sender != null) { 156eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler Address[] addresses = Address.parse(sender); 1575e91cccd4b530eb2aeace5c5bf4f3328a5b5d69dAndrew Stadler message.setFrom(addresses[0]); 158eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler } 159eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler if (subject != null) { 160eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler message.setSubject(subject); 161eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler } 162eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler if (content != null) { 163eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler TextBody body = new TextBody(content); 164eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler message.setBody(body); 165eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler } 166eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler 167eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler message.setUid(UID); 168eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler message.setSentDate(new Date()); 169eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler message.setInternalDate(new Date()); 170eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler message.setMessageId(MESSAGE_ID); 171eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler return message; 172eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler } 173eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler 174eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler /** 175b6756688b1bf07c50b999c9d30dd6cb224d3812bAndrew Stadler * Basic test of body parts conversion from Store message to Provider message. 176b6756688b1bf07c50b999c9d30dd6cb224d3812bAndrew Stadler * This tests that a null body part simply results in null text, and does not crash 177b6756688b1bf07c50b999c9d30dd6cb224d3812bAndrew Stadler * or return "null". 178b6756688b1bf07c50b999c9d30dd6cb224d3812bAndrew Stadler * 179b6756688b1bf07c50b999c9d30dd6cb224d3812bAndrew Stadler * TODO very incomplete, there are many permutations to be explored 180b6756688b1bf07c50b999c9d30dd6cb224d3812bAndrew Stadler */ 181b6756688b1bf07c50b999c9d30dd6cb224d3812bAndrew Stadler public void testUpdateBodyFieldsNullText() throws MessagingException { 182b6756688b1bf07c50b999c9d30dd6cb224d3812bAndrew Stadler EmailContent.Body localBody = new EmailContent.Body(); 183b6756688b1bf07c50b999c9d30dd6cb224d3812bAndrew Stadler EmailContent.Message localMessage = new EmailContent.Message(); 184b6756688b1bf07c50b999c9d30dd6cb224d3812bAndrew Stadler ArrayList<Part> viewables = new ArrayList<Part>(); 185b6756688b1bf07c50b999c9d30dd6cb224d3812bAndrew Stadler Part emptyTextPart = new MimeBodyPart(null, "text/plain"); 186b6756688b1bf07c50b999c9d30dd6cb224d3812bAndrew Stadler viewables.add(emptyTextPart); 187b6756688b1bf07c50b999c9d30dd6cb224d3812bAndrew Stadler 188b6756688b1bf07c50b999c9d30dd6cb224d3812bAndrew Stadler // a "null" body part of type text/plain should result in a null mTextContent 1896be411edd0ef5a1fb357d90c7fee22de83632be5Andrew Sapperstein final BodyFieldData data = 1906be411edd0ef5a1fb357d90c7fee22de83632be5Andrew Sapperstein ConversionUtilities.parseBodyFields(viewables); 1916be411edd0ef5a1fb357d90c7fee22de83632be5Andrew Sapperstein assertNull(data.textContent); 192b6756688b1bf07c50b999c9d30dd6cb224d3812bAndrew Stadler } 193b6756688b1bf07c50b999c9d30dd6cb224d3812bAndrew Stadler 194b6756688b1bf07c50b999c9d30dd6cb224d3812bAndrew Stadler /** 1957d738cb7e89353c51c567e466a135b54337f310dAndrew Stadler * Sunny day test of adding attachments from an IMAP/POP message. 1963f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler */ 1973f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler public void testAddAttachments() throws MessagingException, IOException { 1983f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler // Prepare a local message to add the attachments to 1993f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler final long accountId = 1; 2003f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler final long mailboxId = 1; 2017d738cb7e89353c51c567e466a135b54337f310dAndrew Stadler 2027d738cb7e89353c51c567e466a135b54337f310dAndrew Stadler // test 1: legacy message using content-type:name style for name 2033f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler final EmailContent.Message localMessage = ProviderTestUtils.setupMessage( 2043f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler "local-message", accountId, mailboxId, false, true, mProviderContext); 2057d51b7a05ba07377e3df0b07c2aaa430a8b5bc42Andy Stadler final Message legacyMessage = prepareLegacyMessageWithAttachments(2, false); 2067d738cb7e89353c51c567e466a135b54337f310dAndrew Stadler convertAndCheckcheckAddedAttachments(localMessage, legacyMessage); 2073f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler 2087d738cb7e89353c51c567e466a135b54337f310dAndrew Stadler // test 2: legacy message using content-disposition:filename style for name 2097d738cb7e89353c51c567e466a135b54337f310dAndrew Stadler final EmailContent.Message localMessage2 = ProviderTestUtils.setupMessage( 2107d738cb7e89353c51c567e466a135b54337f310dAndrew Stadler "local-message", accountId, mailboxId, false, true, mProviderContext); 2117d51b7a05ba07377e3df0b07c2aaa430a8b5bc42Andy Stadler final Message legacyMessage2 = prepareLegacyMessageWithAttachments(2, true); 2127d738cb7e89353c51c567e466a135b54337f310dAndrew Stadler convertAndCheckcheckAddedAttachments(localMessage2, legacyMessage2); 2137d738cb7e89353c51c567e466a135b54337f310dAndrew Stadler } 2143f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler 2157d738cb7e89353c51c567e466a135b54337f310dAndrew Stadler /** 2167d738cb7e89353c51c567e466a135b54337f310dAndrew Stadler * Helper for testAddAttachments 2177d738cb7e89353c51c567e466a135b54337f310dAndrew Stadler */ 2187d738cb7e89353c51c567e466a135b54337f310dAndrew Stadler private void convertAndCheckcheckAddedAttachments(final EmailContent.Message localMessage, 2197d738cb7e89353c51c567e466a135b54337f310dAndrew Stadler final Message legacyMessage) throws MessagingException, IOException { 2203f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler // Now, convert from legacy to provider and see what happens 2213f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler ArrayList<Part> viewables = new ArrayList<Part>(); 2223f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler ArrayList<Part> attachments = new ArrayList<Part>(); 2233f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler MimeUtility.collectParts(legacyMessage, viewables, attachments); 2247d51b7a05ba07377e3df0b07c2aaa430a8b5bc42Andy Stadler LegacyConversions.updateAttachments(mProviderContext, localMessage, attachments); 2253f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler 2263f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler // Read back all attachments for message and check field values 2273f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler Uri uri = ContentUris.withAppendedId(Attachment.MESSAGE_ID_URI, localMessage.mId); 2283f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler Cursor c = mProviderContext.getContentResolver().query(uri, Attachment.CONTENT_PROJECTION, 2293f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler null, null, null); 2303f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler try { 2313f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler assertEquals(2, c.getCount()); 2323f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler while (c.moveToNext()) { 2333f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler Attachment attachment = Attachment.getContent(c, Attachment.class); 234e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler if ("100".equals(attachment.mLocation)) { 23575a873be8420e50f0aeb5a77716358ee0ca66b01Marc Blank checkAttachment("attachment1Part", attachments.get(0), attachment, 23675a873be8420e50f0aeb5a77716358ee0ca66b01Marc Blank localMessage.mAccountKey); 237e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler } else if ("101".equals(attachment.mLocation)) { 23875a873be8420e50f0aeb5a77716358ee0ca66b01Marc Blank checkAttachment("attachment2Part", attachments.get(1), attachment, 23975a873be8420e50f0aeb5a77716358ee0ca66b01Marc Blank localMessage.mAccountKey); 2403f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler } else { 2413f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler fail("Unexpected attachment with location " + attachment.mLocation); 2423f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler } 2433f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler } 2443f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler } finally { 2453f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler c.close(); 2463f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler } 2473f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler } 2483f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler 2493f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler /** 250e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler * Test that only "attachment" or "inline" attachments are captured and added. 251e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler * @throws MessagingException 252e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler * @throws IOException 253e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler */ 254e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler public void testAttachmentDispositions() throws MessagingException, IOException { 255e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler // Prepare a local message to add the attachments to 256e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler final long accountId = 1; 257e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler final long mailboxId = 1; 258e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler 259e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler // Prepare the three attachments we want to test 260e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler BodyPart[] sourceAttachments = new BodyPart[3]; 261e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler BodyPart attachmentPart; 262e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler 263e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler // 1. Standard attachment 264e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler attachmentPart = MessageTestUtils.bodyPart("image/jpg", null); 265e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "image/jpg"); 266e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING, "base64"); 267e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_DISPOSITION, 268e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler "attachment;\n filename=\"file-1\";\n size=100"); 269e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler attachmentPart.setHeader(MimeHeader.HEADER_ANDROID_ATTACHMENT_STORE_DATA, "100"); 270e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler sourceAttachments[0] = attachmentPart; 271e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler 272e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler // 2. Inline attachment 273e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler attachmentPart = MessageTestUtils.bodyPart("image/gif", null); 274e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "image/gif"); 275e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING, "base64"); 276e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_DISPOSITION, 277e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler "inline;\n filename=\"file-2\";\n size=200"); 278e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler attachmentPart.setHeader(MimeHeader.HEADER_ANDROID_ATTACHMENT_STORE_DATA, "101"); 279e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler sourceAttachments[1] = attachmentPart; 280e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler 281e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler // 3. Neither (use VCALENDAR) 282e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler attachmentPart = MessageTestUtils.bodyPart("text/calendar", null); 283e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_TYPE, 284e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler "text/calendar; charset=UTF-8; method=REQUEST"); 285e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING, "7bit"); 286e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler attachmentPart.setHeader(MimeHeader.HEADER_ANDROID_ATTACHMENT_STORE_DATA, "102"); 287e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler sourceAttachments[2] = attachmentPart; 288e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler 289e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler // Prepare local message (destination) and legacy message w/attachments (source) 290e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler final EmailContent.Message localMessage = ProviderTestUtils.setupMessage( 291e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler "local-message", accountId, mailboxId, false, true, mProviderContext); 292e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler final Message legacyMessage = prepareLegacyMessageWithAttachments(sourceAttachments); 293e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler convertAndCheckcheckAddedAttachments(localMessage, legacyMessage); 294e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler 295e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler // Run the conversion and check for the converted attachments - this test asserts 296e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler // that there are two attachments numbered 100 & 101 (so will fail if it finds 102) 297e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler convertAndCheckcheckAddedAttachments(localMessage, legacyMessage); 298e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler } 299e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler 300e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler /** 3015b0a12c199198870161876996296b1262c17408eAndrew Stadler * Test that attachments aren't re-added in the DB. This supports the "partial download" 3025b0a12c199198870161876996296b1262c17408eAndrew Stadler * nature of POP messages. 3035b0a12c199198870161876996296b1262c17408eAndrew Stadler */ 3045b0a12c199198870161876996296b1262c17408eAndrew Stadler public void testAddDuplicateAttachments() throws MessagingException, IOException { 3055b0a12c199198870161876996296b1262c17408eAndrew Stadler // Prepare a local message to add the attachments to 3065b0a12c199198870161876996296b1262c17408eAndrew Stadler final long accountId = 1; 3075b0a12c199198870161876996296b1262c17408eAndrew Stadler final long mailboxId = 1; 3085b0a12c199198870161876996296b1262c17408eAndrew Stadler final EmailContent.Message localMessage = ProviderTestUtils.setupMessage( 3095b0a12c199198870161876996296b1262c17408eAndrew Stadler "local-message", accountId, mailboxId, false, true, mProviderContext); 3105b0a12c199198870161876996296b1262c17408eAndrew Stadler 3115b0a12c199198870161876996296b1262c17408eAndrew Stadler // Prepare a legacy message with attachments 3127d51b7a05ba07377e3df0b07c2aaa430a8b5bc42Andy Stadler Message legacyMessage = prepareLegacyMessageWithAttachments(2, false); 3135b0a12c199198870161876996296b1262c17408eAndrew Stadler 3145b0a12c199198870161876996296b1262c17408eAndrew Stadler // Now, convert from legacy to provider and see what happens 3155b0a12c199198870161876996296b1262c17408eAndrew Stadler ArrayList<Part> viewables = new ArrayList<Part>(); 3165b0a12c199198870161876996296b1262c17408eAndrew Stadler ArrayList<Part> attachments = new ArrayList<Part>(); 3175b0a12c199198870161876996296b1262c17408eAndrew Stadler MimeUtility.collectParts(legacyMessage, viewables, attachments); 3187d51b7a05ba07377e3df0b07c2aaa430a8b5bc42Andy Stadler LegacyConversions.updateAttachments(mProviderContext, localMessage, attachments); 3195b0a12c199198870161876996296b1262c17408eAndrew Stadler 3205b0a12c199198870161876996296b1262c17408eAndrew Stadler // Confirm two attachment objects created 3215b0a12c199198870161876996296b1262c17408eAndrew Stadler Uri uri = ContentUris.withAppendedId(Attachment.MESSAGE_ID_URI, localMessage.mId); 3225b0a12c199198870161876996296b1262c17408eAndrew Stadler assertEquals(2, EmailContent.count(mProviderContext, uri, null, null)); 3235b0a12c199198870161876996296b1262c17408eAndrew Stadler 3245b0a12c199198870161876996296b1262c17408eAndrew Stadler // Now add the attachments again and confirm there are still only two 3257d51b7a05ba07377e3df0b07c2aaa430a8b5bc42Andy Stadler LegacyConversions.updateAttachments(mProviderContext, localMessage, attachments); 3265b0a12c199198870161876996296b1262c17408eAndrew Stadler assertEquals(2, EmailContent.count(mProviderContext, uri, null, null)); 3275b0a12c199198870161876996296b1262c17408eAndrew Stadler 3285b0a12c199198870161876996296b1262c17408eAndrew Stadler // Now add a 3rd & 4th attachment and make sure the total is 4, not 2 or 6 3297d51b7a05ba07377e3df0b07c2aaa430a8b5bc42Andy Stadler legacyMessage = prepareLegacyMessageWithAttachments(4, false); 3305b0a12c199198870161876996296b1262c17408eAndrew Stadler viewables = new ArrayList<Part>(); 3315b0a12c199198870161876996296b1262c17408eAndrew Stadler attachments = new ArrayList<Part>(); 3325b0a12c199198870161876996296b1262c17408eAndrew Stadler MimeUtility.collectParts(legacyMessage, viewables, attachments); 3337d51b7a05ba07377e3df0b07c2aaa430a8b5bc42Andy Stadler LegacyConversions.updateAttachments(mProviderContext, localMessage, attachments); 3345b0a12c199198870161876996296b1262c17408eAndrew Stadler assertEquals(4, EmailContent.count(mProviderContext, uri, null, null)); 3355b0a12c199198870161876996296b1262c17408eAndrew Stadler } 3365b0a12c199198870161876996296b1262c17408eAndrew Stadler 3375b0a12c199198870161876996296b1262c17408eAndrew Stadler /** 3385b0a12c199198870161876996296b1262c17408eAndrew Stadler * Prepare a legacy message with 1+ attachments 339fd249f61dd9c5fd1e7e0abffcb09b9e285d82baeAndrew Stadler * @param numAttachments how many attachments to add 3407d738cb7e89353c51c567e466a135b54337f310dAndrew Stadler * @param filenameInDisposition False: attachment names are sent as content-type:name. True: 3417d738cb7e89353c51c567e466a135b54337f310dAndrew Stadler * attachment names are sent as content-disposition:filename. 3425b0a12c199198870161876996296b1262c17408eAndrew Stadler */ 3437d51b7a05ba07377e3df0b07c2aaa430a8b5bc42Andy Stadler private Message prepareLegacyMessageWithAttachments(int numAttachments, 3447d738cb7e89353c51c567e466a135b54337f310dAndrew Stadler boolean filenameInDisposition) throws MessagingException { 345e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler BodyPart[] attachmentParts = new BodyPart[numAttachments]; 346e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler for (int i = 0; i < numAttachments; ++i) { 3477d738cb7e89353c51c567e466a135b54337f310dAndrew Stadler // construct parameter parts for content-type:name or content-disposition:filename. 3487d738cb7e89353c51c567e466a135b54337f310dAndrew Stadler String name = ""; 3497d738cb7e89353c51c567e466a135b54337f310dAndrew Stadler String filename = ""; 3507d738cb7e89353c51c567e466a135b54337f310dAndrew Stadler String quotedName = "\"test-attachment-" + i + "\""; 3517d738cb7e89353c51c567e466a135b54337f310dAndrew Stadler if (filenameInDisposition) { 3527d738cb7e89353c51c567e466a135b54337f310dAndrew Stadler filename = ";\n filename=" + quotedName; 3537d738cb7e89353c51c567e466a135b54337f310dAndrew Stadler } else { 3547d738cb7e89353c51c567e466a135b54337f310dAndrew Stadler name = ";\n name=" + quotedName; 3557d738cb7e89353c51c567e466a135b54337f310dAndrew Stadler } 356fd249f61dd9c5fd1e7e0abffcb09b9e285d82baeAndrew Stadler 3577d51b7a05ba07377e3df0b07c2aaa430a8b5bc42Andy Stadler // generate an attachment that came from a server 3587d51b7a05ba07377e3df0b07c2aaa430a8b5bc42Andy Stadler BodyPart attachmentPart = MessageTestUtils.bodyPart("image/jpg", null); 359fd249f61dd9c5fd1e7e0abffcb09b9e285d82baeAndrew Stadler 3607d51b7a05ba07377e3df0b07c2aaa430a8b5bc42Andy Stadler // name=attachmentN size=N00 location=10N 3617d51b7a05ba07377e3df0b07c2aaa430a8b5bc42Andy Stadler attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "image/jpg" + name); 3627d51b7a05ba07377e3df0b07c2aaa430a8b5bc42Andy Stadler attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING, "base64"); 3637d51b7a05ba07377e3df0b07c2aaa430a8b5bc42Andy Stadler attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_DISPOSITION, 3647d51b7a05ba07377e3df0b07c2aaa430a8b5bc42Andy Stadler "attachment" + filename + ";\n size=" + (i+1) + "00"); 3657d51b7a05ba07377e3df0b07c2aaa430a8b5bc42Andy Stadler attachmentPart.setHeader(MimeHeader.HEADER_ANDROID_ATTACHMENT_STORE_DATA, "10" + i); 3667d51b7a05ba07377e3df0b07c2aaa430a8b5bc42Andy Stadler 3677d51b7a05ba07377e3df0b07c2aaa430a8b5bc42Andy Stadler attachmentParts[i] = attachmentPart; 3685b0a12c199198870161876996296b1262c17408eAndrew Stadler } 3695b0a12c199198870161876996296b1262c17408eAndrew Stadler 370e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler return prepareLegacyMessageWithAttachments(attachmentParts); 371e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler } 372e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler 373e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler /** 374e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler * Prepare a legacy message with 1+ attachments 375e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler * @param attachments array containing one or more attachments 376e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler */ 377e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler private Message prepareLegacyMessageWithAttachments(BodyPart[] attachments) 378e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler throws MessagingException { 379e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler // Build the multipart that holds the attachments 380e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler MultipartBuilder mpBuilder = new MultipartBuilder("multipart/mixed"); 381e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler for (int i = 0; i < attachments.length; ++i) { 382e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler mpBuilder.addBodyPart(attachments[i]); 383e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler } 384e3a17f1438e454518a58fc0841bb615344acf865Andy Stadler 3855b0a12c199198870161876996296b1262c17408eAndrew Stadler // Now build a message with them 3865b0a12c199198870161876996296b1262c17408eAndrew Stadler final Message legacyMessage = new MessageBuilder() 3875b0a12c199198870161876996296b1262c17408eAndrew Stadler .setBody(new MultipartBuilder("multipart/mixed") 3885b0a12c199198870161876996296b1262c17408eAndrew Stadler .addBodyPart(MessageTestUtils.bodyPart("text/html", null)) 3895b0a12c199198870161876996296b1262c17408eAndrew Stadler .addBodyPart(mpBuilder.buildBodyPart()) 3905b0a12c199198870161876996296b1262c17408eAndrew Stadler .build()) 3915b0a12c199198870161876996296b1262c17408eAndrew Stadler .build(); 3925b0a12c199198870161876996296b1262c17408eAndrew Stadler 3935b0a12c199198870161876996296b1262c17408eAndrew Stadler return legacyMessage; 3945b0a12c199198870161876996296b1262c17408eAndrew Stadler } 3955b0a12c199198870161876996296b1262c17408eAndrew Stadler 3965b0a12c199198870161876996296b1262c17408eAndrew Stadler /** 3975b0a12c199198870161876996296b1262c17408eAndrew Stadler * Test the stringInequal helper 3985b0a12c199198870161876996296b1262c17408eAndrew Stadler */ 3995b0a12c199198870161876996296b1262c17408eAndrew Stadler public void testStringInequal() { 4005b0a12c199198870161876996296b1262c17408eAndrew Stadler // Pairs that are "equal" 4015b0a12c199198870161876996296b1262c17408eAndrew Stadler assertFalse(LegacyConversions.stringNotEqual(null, null)); 4025b0a12c199198870161876996296b1262c17408eAndrew Stadler assertFalse(LegacyConversions.stringNotEqual(null, "")); 4035b0a12c199198870161876996296b1262c17408eAndrew Stadler assertFalse(LegacyConversions.stringNotEqual("", null)); 4045b0a12c199198870161876996296b1262c17408eAndrew Stadler assertFalse(LegacyConversions.stringNotEqual("", "")); 4055b0a12c199198870161876996296b1262c17408eAndrew Stadler assertFalse(LegacyConversions.stringNotEqual("string-equal", "string-equal")); 4065b0a12c199198870161876996296b1262c17408eAndrew Stadler // Pairs that are "inequal" 4075b0a12c199198870161876996296b1262c17408eAndrew Stadler assertTrue(LegacyConversions.stringNotEqual(null, "string-inequal")); 4085b0a12c199198870161876996296b1262c17408eAndrew Stadler assertTrue(LegacyConversions.stringNotEqual("", "string-inequal")); 4095b0a12c199198870161876996296b1262c17408eAndrew Stadler assertTrue(LegacyConversions.stringNotEqual("string-inequal", null)); 4105b0a12c199198870161876996296b1262c17408eAndrew Stadler assertTrue(LegacyConversions.stringNotEqual("string-inequal", "")); 4115b0a12c199198870161876996296b1262c17408eAndrew Stadler assertTrue(LegacyConversions.stringNotEqual("string-inequal-a", "string-inequal-b")); 4125b0a12c199198870161876996296b1262c17408eAndrew Stadler } 4135b0a12c199198870161876996296b1262c17408eAndrew Stadler 4145b0a12c199198870161876996296b1262c17408eAndrew Stadler /** 4153f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler * Compare attachment that was converted from Part (expected) to Provider Attachment (actual) 416515d830e8755d3674e04bcc60d7f85b4fa7fb202Jerry Xie * 4173f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler * TODO content URI should only be set if we also saved a file 4183f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler * TODO other data encodings 4193f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler */ 42075a873be8420e50f0aeb5a77716358ee0ca66b01Marc Blank private void checkAttachment(String tag, Part expected, EmailContent.Attachment actual, 42175a873be8420e50f0aeb5a77716358ee0ca66b01Marc Blank long accountKey) throws MessagingException { 4223f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler String contentType = MimeUtility.unfoldAndDecode(expected.getContentType()); 4237d738cb7e89353c51c567e466a135b54337f310dAndrew Stadler String contentTypeName = MimeUtility.getHeaderParameter(contentType, "name"); 4243f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler assertEquals(tag, expected.getMimeType(), actual.mMimeType); 4253f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler String disposition = expected.getDisposition(); 4263f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler String sizeString = MimeUtility.getHeaderParameter(disposition, "size"); 4277d738cb7e89353c51c567e466a135b54337f310dAndrew Stadler String dispositionFilename = MimeUtility.getHeaderParameter(disposition, "filename"); 428fd249f61dd9c5fd1e7e0abffcb09b9e285d82baeAndrew Stadler long expectedSize = (sizeString != null) ? Long.parseLong(sizeString) : 0; 4293f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler assertEquals(tag, expectedSize, actual.mSize); 4303f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler assertEquals(tag, expected.getContentId(), actual.mContentId); 431fd249f61dd9c5fd1e7e0abffcb09b9e285d82baeAndrew Stadler 4327d738cb7e89353c51c567e466a135b54337f310dAndrew Stadler // filename is either content-type:name or content-disposition:filename 4337d738cb7e89353c51c567e466a135b54337f310dAndrew Stadler String expectedName = (contentTypeName != null) ? contentTypeName : dispositionFilename; 4347d738cb7e89353c51c567e466a135b54337f310dAndrew Stadler assertEquals(tag, expectedName, actual.mFileName); 4357d738cb7e89353c51c567e466a135b54337f310dAndrew Stadler 4367d51b7a05ba07377e3df0b07c2aaa430a8b5bc42Andy Stadler // content URI should be null 437515d830e8755d3674e04bcc60d7f85b4fa7fb202Jerry Xie assertNull(tag, actual.getContentUri()); 438fd249f61dd9c5fd1e7e0abffcb09b9e285d82baeAndrew Stadler 4393f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler assertTrue(tag, 0 != actual.mMessageKey); 440fd249f61dd9c5fd1e7e0abffcb09b9e285d82baeAndrew Stadler 441fd249f61dd9c5fd1e7e0abffcb09b9e285d82baeAndrew Stadler // location is either both null or both matching 442fd249f61dd9c5fd1e7e0abffcb09b9e285d82baeAndrew Stadler String expectedPartId = null; 443fd249f61dd9c5fd1e7e0abffcb09b9e285d82baeAndrew Stadler String[] storeData = expected.getHeader(MimeHeader.HEADER_ANDROID_ATTACHMENT_STORE_DATA); 444fd249f61dd9c5fd1e7e0abffcb09b9e285d82baeAndrew Stadler if (storeData != null && storeData.length > 0) { 445fd249f61dd9c5fd1e7e0abffcb09b9e285d82baeAndrew Stadler expectedPartId = storeData[0]; 446fd249f61dd9c5fd1e7e0abffcb09b9e285d82baeAndrew Stadler } 4473f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler assertEquals(tag, expectedPartId, actual.mLocation); 4483f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler assertEquals(tag, "B", actual.mEncoding); 44975a873be8420e50f0aeb5a77716358ee0ca66b01Marc Blank assertEquals(tag, accountKey, actual.mAccountKey); 4503f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler } 4513f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler 4523f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler /** 4533f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler * TODO: Sunny day test of adding attachments from a POP message. 4543f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler */ 4553f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler 456c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler /** 457c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler * Sunny day tests of converting an original message to a legacy message 458c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler */ 459c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler public void testMakeLegacyMessage() throws MessagingException { 460c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler // Set up and store a message in the provider 461c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler long account1Id = 1; 462c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler long mailbox1Id = 1; 463c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler 464c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler // Test message 1: No body 465c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler EmailContent.Message localMessage1 = ProviderTestUtils.setupMessage("make-legacy", 466c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler account1Id, mailbox1Id, false, true, mProviderContext); 467c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler Message getMessage1 = LegacyConversions.makeMessage(mProviderContext, localMessage1); 468c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler checkLegacyMessage("no body", localMessage1, getMessage1); 469c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler 470c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler // Test message 2: Simple body 471c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler EmailContent.Message localMessage2 = ProviderTestUtils.setupMessage("make-legacy", 472c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler account1Id, mailbox1Id, true, false, mProviderContext); 473c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler localMessage2.mTextReply = null; 474c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler localMessage2.mHtmlReply = null; 475c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler localMessage2.mIntroText = null; 476c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler localMessage2.mFlags &= ~EmailContent.Message.FLAG_TYPE_MASK; 477c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler localMessage2.save(mProviderContext); 478c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler Message getMessage2 = LegacyConversions.makeMessage(mProviderContext, localMessage2); 479c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler checkLegacyMessage("simple body", localMessage2, getMessage2); 480c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler 481c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler // Test message 3: Body + replied-to text 482c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler EmailContent.Message localMessage3 = ProviderTestUtils.setupMessage("make-legacy", 483c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler account1Id, mailbox1Id, true, false, mProviderContext); 484c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler localMessage3.mFlags &= ~EmailContent.Message.FLAG_TYPE_MASK; 485c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler localMessage3.mFlags |= EmailContent.Message.FLAG_TYPE_REPLY; 486c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler localMessage3.save(mProviderContext); 487c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler Message getMessage3 = LegacyConversions.makeMessage(mProviderContext, localMessage3); 488c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler checkLegacyMessage("reply-to", localMessage3, getMessage3); 489c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler 490c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler // Test message 4: Body + forwarded text 491c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler EmailContent.Message localMessage4 = ProviderTestUtils.setupMessage("make-legacy", 492c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler account1Id, mailbox1Id, true, false, mProviderContext); 493c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler localMessage4.mFlags &= ~EmailContent.Message.FLAG_TYPE_MASK; 494c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler localMessage4.mFlags |= EmailContent.Message.FLAG_TYPE_FORWARD; 495c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler localMessage4.save(mProviderContext); 496c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler Message getMessage4 = LegacyConversions.makeMessage(mProviderContext, localMessage4); 497c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler checkLegacyMessage("forwarding", localMessage4, getMessage4); 498c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler } 499c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler 500c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler /** 501eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler * Check equality of a pair of converted messages 502eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler */ 503eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler private void checkProviderMessage(String tag, Message expect, EmailContent.Message actual) 504eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler throws MessagingException { 505eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler assertEquals(tag, expect.getUid(), actual.mServerId); 506eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler assertEquals(tag, expect.getSubject(), actual.mSubject); 507eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler assertEquals(tag, Address.pack(expect.getFrom()), actual.mFrom); 508eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler assertEquals(tag, expect.getSentDate().getTime(), actual.mTimeStamp); 509eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler assertEquals(tag, Address.pack(expect.getRecipients(RecipientType.TO)), actual.mTo); 510eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler assertEquals(tag, Address.pack(expect.getRecipients(RecipientType.CC)), actual.mCc); 511eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler assertEquals(tag, ((MimeMessage)expect).getMessageId(), actual.mMessageId); 512eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler assertEquals(tag, expect.isSet(Flag.SEEN), actual.mFlagRead); 513eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler assertEquals(tag, expect.isSet(Flag.FLAGGED), actual.mFlagFavorite); 514eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler } 515eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler 5165b0a12c199198870161876996296b1262c17408eAndrew Stadler /** 517eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler * Check equality of a pair of converted messages 518c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler */ 519c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler private void checkLegacyMessage(String tag, EmailContent.Message expect, Message actual) 520c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler throws MessagingException { 521c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler assertEquals(tag, expect.mServerId, actual.getUid()); 522eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler assertEquals(tag, expect.mServerTimeStamp, actual.getInternalDate().getTime()); 523c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler assertEquals(tag, expect.mSubject, actual.getSubject()); 524c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler assertEquals(tag, expect.mFrom, Address.pack(actual.getFrom())); 525c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler assertEquals(tag, expect.mTimeStamp, actual.getSentDate().getTime()); 526c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler assertEquals(tag, expect.mTo, Address.pack(actual.getRecipients(RecipientType.TO))); 527c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler assertEquals(tag, expect.mCc, Address.pack(actual.getRecipients(RecipientType.CC))); 528eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler assertEquals(tag, expect.mBcc, Address.pack(actual.getRecipients(RecipientType.BCC))); 529eb7752bf695b2a93854e0bb89ddbbc2236bb9aeaAndrew Stadler assertEquals(tag, expect.mReplyTo, Address.pack(actual.getReplyTo())); 530c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler assertEquals(tag, expect.mMessageId, ((MimeMessage)actual).getMessageId()); 531c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler // check flags 532c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler assertEquals(tag, expect.mFlagRead, actual.isSet(Flag.SEEN)); 533c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler assertEquals(tag, expect.mFlagFavorite, actual.isSet(Flag.FLAGGED)); 534c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler 535c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler // Check the body of the message 536c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler ArrayList<Part> viewables = new ArrayList<Part>(); 537c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler ArrayList<Part> attachments = new ArrayList<Part>(); 538c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler MimeUtility.collectParts(actual, viewables, attachments); 539c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler String get1Text = null; 540c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler String get1Html = null; 541c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler String get1TextReply = null; 542c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler String get1HtmlReply = null; 543c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler String get1TextIntro = null; 544c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler for (Part viewable : viewables) { 545c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler String text = MimeUtility.getTextFromPart(viewable); 546c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler boolean isHtml = viewable.getMimeType().equalsIgnoreCase("text/html"); 547c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler String[] headers = viewable.getHeader(MimeHeader.HEADER_ANDROID_BODY_QUOTED_PART); 548c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler if (headers != null) { 549c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler String header = headers[0]; 550c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler boolean isReply = LegacyConversions.BODY_QUOTED_PART_REPLY.equalsIgnoreCase(header); 551c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler boolean isFwd = LegacyConversions.BODY_QUOTED_PART_FORWARD.equalsIgnoreCase(header); 552c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler boolean isIntro = LegacyConversions.BODY_QUOTED_PART_INTRO.equalsIgnoreCase(header); 553c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler if (isReply || isFwd) { 554c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler if (isHtml) { 555c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler get1HtmlReply = text; 556c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler } else { 557c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler get1TextReply = text; 558c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler } 559c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler } else if (isIntro) { 560c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler get1TextIntro = text; 561c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler } 562c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler // Check flags 563c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler int replyTypeFlags = expect.mFlags & EmailContent.Message.FLAG_TYPE_MASK; 564c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler if (isReply) { 565c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler assertEquals(tag, EmailContent.Message.FLAG_TYPE_REPLY, replyTypeFlags); 566c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler } 567c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler if (isFwd) { 568c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler assertEquals(tag, EmailContent.Message.FLAG_TYPE_FORWARD, replyTypeFlags); 569c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler } 570c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler } else { 571c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler if (isHtml) { 572c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler get1Html = text; 573c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler } else { 574c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler get1Text = text; 575c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler } 576c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler } 577c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler } 578c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler assertEquals(tag, expect.mText, get1Text); 579c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler assertEquals(tag, expect.mHtml, get1Html); 580c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler assertEquals(tag, expect.mTextReply, get1TextReply); 581c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler assertEquals(tag, expect.mHtmlReply, get1HtmlReply); 582c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler assertEquals(tag, expect.mIntroText, get1TextIntro); 583c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler 584c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler // TODO Check the attachments 585c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler 586c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler// cv.put("attachment_count", attachments.size()); 587c41c47fa07a22f8a7612fb0191f152a36d95b7a5Andrew Stadler } 5883f1ac4da947f426775c9546f2e37206f58ce1a6eAndrew Stadler} 589