SmtpSenderUnitTests.java revision daf869cf60de75bc91ed3aef6ac0bff1fe371733
196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project/* 296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * 496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * you may not use this file except in compliance with the License. 696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * You may obtain a copy of the License at 796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * 896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * 1096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 1196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 1296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * See the License for the specific language governing permissions and 1496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * limitations under the License. 1596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 1696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 1796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectpackage com.android.email.mail.transport; 1896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 19c849936a36424645af73dc307b19778a89d6ee84Makoto Onukiimport com.android.email.DBTestHelper; 2096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport com.android.email.mail.Transport; 21c849936a36424645af73dc307b19778a89d6ee84Makoto Onukiimport com.android.email.provider.EmailProvider; 222193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.mail.Address; 232193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.mail.MessagingException; 24daf869cf60de75bc91ed3aef6ac0bff1fe371733Todd Kennedyimport com.android.emailcommon.provider.EmailContent.Account; 25a7bc0319a75184ad706bb35c049af107ac3688e6Marc Blankimport com.android.emailcommon.provider.EmailContent.Attachment; 26a7bc0319a75184ad706bb35c049af107ac3688e6Marc Blankimport com.android.emailcommon.provider.EmailContent.Body; 27daf869cf60de75bc91ed3aef6ac0bff1fe371733Todd Kennedyimport com.android.emailcommon.provider.EmailContent.HostAuth; 28a7bc0319a75184ad706bb35c049af107ac3688e6Marc Blankimport com.android.emailcommon.provider.EmailContent.Message; 2996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 30c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadlerimport org.apache.commons.io.IOUtils; 31c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 32c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadlerimport android.content.Context; 33c849936a36424645af73dc307b19778a89d6ee84Makoto Onukiimport android.test.AndroidTestCase; 3496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport android.test.suitebuilder.annotation.SmallTest; 3596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 36c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadlerimport java.io.ByteArrayInputStream; 37c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadlerimport java.io.File; 38c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadlerimport java.io.FileOutputStream; 39c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadlerimport java.io.IOException; 40c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadlerimport java.io.InputStream; 41c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadlerimport java.io.OutputStream; 42f4dac9f266906a84f4710d8af5d4a24f2290b1baMakoto Onukiimport java.net.InetAddress; 43f4dac9f266906a84f4710d8af5d4a24f2290b1baMakoto Onukiimport java.net.UnknownHostException; 44f4dac9f266906a84f4710d8af5d4a24f2290b1baMakoto Onukiimport java.util.regex.Pattern; 4596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 4696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project/** 4796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * This is a series of unit tests for the SMTP Sender class. These tests must be locally 4896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * complete - no server(s) required. 49c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler * 50c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler * These tests can be run with the following command: 51c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler * runtest -c com.android.email.mail.transport.SmtpSenderUnitTests email 5296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 5396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project@SmallTest 54c849936a36424645af73dc307b19778a89d6ee84Makoto Onukipublic class SmtpSenderUnitTests extends AndroidTestCase { 55c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 56c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler EmailProvider mProvider; 57c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler Context mProviderContext; 58c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler Context mContext; 59f4dac9f266906a84f4710d8af5d4a24f2290b1baMakoto Onuki private static final String LOCAL_ADDRESS = "1.2.3.4"; 6096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 6196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /* These values are provided by setUp() */ 6296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project private SmtpSender mSender = null; 63c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 64c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler /* Simple test string and its base64 equivalent */ 65c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler private final static String TEST_STRING = "Hello, world"; 66c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler private final static String TEST_STRING_BASE64 = "SGVsbG8sIHdvcmxk"; 67c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 6896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /** 6996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Setup code. We generate a lightweight SmtpSender for testing. 7096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 7196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project @Override 7296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project protected void setUp() throws Exception { 7396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project super.setUp(); 74c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki mProviderContext = DBTestHelper.ProviderContextSetupHelper.getProviderContext( 75c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki getContext()); 76c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mContext = getContext(); 77c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki 78daf869cf60de75bc91ed3aef6ac0bff1fe371733Todd Kennedy HostAuth testAuth = new HostAuth(); 79daf869cf60de75bc91ed3aef6ac0bff1fe371733Todd Kennedy Account testAccount = new Account(); 80daf869cf60de75bc91ed3aef6ac0bff1fe371733Todd Kennedy 81daf869cf60de75bc91ed3aef6ac0bff1fe371733Todd Kennedy testAuth.setLogin("user", "password"); 82daf869cf60de75bc91ed3aef6ac0bff1fe371733Todd Kennedy testAuth.setConnection("smtp", "server", 999); 83daf869cf60de75bc91ed3aef6ac0bff1fe371733Todd Kennedy testAccount.mHostAuthSend = testAuth; 84daf869cf60de75bc91ed3aef6ac0bff1fe371733Todd Kennedy mSender = (SmtpSender) SmtpSender.newInstance(testAccount, mProviderContext); 8596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 8696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 8796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /** 8896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Confirms simple non-SSL non-TLS login 8996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 90f4dac9f266906a84f4710d8af5d4a24f2290b1baMakoto Onuki public void testSimpleLogin() throws Exception { 91c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki 9296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project MockTransport mockTransport = openAndInjectMockTransport(); 93c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki 9496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // try to open it 9596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project setupOpen(mockTransport, null); 9696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mSender.open(); 9796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 98c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki 9996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /** 10096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * TODO: Test with SSL negotiation (faked) 10196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * TODO: Test with SSL required but not supported 10296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * TODO: Test with TLS negotiation (faked) 10396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * TODO: Test with TLS required but not supported 10496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * TODO: Test other capabilities. 10596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * TODO: Test AUTH LOGIN 10696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 107c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki 10896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /** 10996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Test: Open and send a single message (sunny day) 11096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 111f4dac9f266906a84f4710d8af5d4a24f2290b1baMakoto Onuki public void testSendMessageWithBody() throws Exception { 11296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project MockTransport mockTransport = openAndInjectMockTransport(); 113c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 11496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // Since SmtpSender.sendMessage() does a close then open, we need to preset for the open 11596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mockTransport.expectClose(); 11696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project setupOpen(mockTransport, null); 11796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 118c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler Message message = setupSimpleMessage(); 119c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler message.save(mProviderContext); 120c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 121c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler Body body = new Body(); 122c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler body.mMessageKey = message.mId; 123c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler body.mTextContent = TEST_STRING; 124c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler body.save(mProviderContext); 125c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 126c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // prepare for the message traffic we'll see 127c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // TODO The test is a bit fragile, as we are order-dependent (and headers are not) 128c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler expectSimpleMessage(mockTransport); 129c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("Content-Type: text/plain; charset=utf-8"); 130c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("Content-Transfer-Encoding: base64"); 131c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(""); 132c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(TEST_STRING_BASE64); 133c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("\r\n\\.", "250 2.0.0 kv2f1a00C02Rf8w3Vv mail accepted for delivery"); 134c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 135c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // Now trigger the transmission 136c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mSender.sendMessage(message.mId); 137c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler } 138c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 139c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler /** 140c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler * Test: Open and send a single message with an empty attachment (no file) (sunny day) 141c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler */ 142c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler public void testSendMessageWithEmptyAttachment() throws MessagingException, IOException { 143c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler MockTransport mockTransport = openAndInjectMockTransport(); 144c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 145c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // Since SmtpSender.sendMessage() does a close then open, we need to preset for the open 146c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expectClose(); 147c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler setupOpen(mockTransport, null); 148c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 149c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler Message message = setupSimpleMessage(); 150c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler message.save(mProviderContext); 151c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 152c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // Creates an attachment with a bogus file (so we get headers only) 153c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler Attachment attachment = setupSimpleAttachment(mProviderContext, message.mId, false); 154c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler attachment.save(mProviderContext); 155c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 156c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler expectSimpleMessage(mockTransport); 157c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("Content-Type: multipart/mixed; boundary=\".*"); 158c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(""); 159c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("----.*"); 160c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler expectSimpleAttachment(mockTransport, attachment); 161c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(""); 162c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("----.*--"); 163c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("\r\n\\.", "250 2.0.0 kv2f1a00C02Rf8w3Vv mail accepted for delivery"); 164c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 165c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // Now trigger the transmission 166c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mSender.sendMessage(message.mId); 167c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler } 168c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 169c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler /** 170c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler * Test: Open and send a single message with an attachment (sunny day) 171c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler */ 172c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler public void testSendMessageWithAttachment() throws MessagingException, IOException { 173c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler MockTransport mockTransport = openAndInjectMockTransport(); 174c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 175c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // Since SmtpSender.sendMessage() does a close then open, we need to preset for the open 176c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expectClose(); 177c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler setupOpen(mockTransport, null); 178c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 179c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler Message message = setupSimpleMessage(); 180c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler message.save(mProviderContext); 181c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 182c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // Creates an attachment with a real file 183c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler Attachment attachment = setupSimpleAttachment(mProviderContext, message.mId, true); 184c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler attachment.save(mProviderContext); 185c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 186c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler expectSimpleMessage(mockTransport); 187c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("Content-Type: multipart/mixed; boundary=\".*"); 188c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(""); 189c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("----.*"); 190c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler expectSimpleAttachment(mockTransport, attachment); 191c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(""); 192c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("----.*--"); 193c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("\r\n\\.", "250 2.0.0 kv2f1a00C02Rf8w3Vv mail accepted for delivery"); 194c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 195c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // Now trigger the transmission 196c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mSender.sendMessage(message.mId); 197c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler } 198c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 199c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler /** 200c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler * Test: Open and send a single message with two attachments 201c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler */ 202c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler public void testSendMessageWithTwoAttachments() throws MessagingException, IOException { 203c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler MockTransport mockTransport = openAndInjectMockTransport(); 204c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 205c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // Since SmtpSender.sendMessage() does a close then open, we need to preset for the open 206c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expectClose(); 207c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler setupOpen(mockTransport, null); 208c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 209c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler Message message = setupSimpleMessage(); 210c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler message.save(mProviderContext); 211c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 212c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // Creates an attachment with a real file 213c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler Attachment attachment = setupSimpleAttachment(mProviderContext, message.mId, true); 214c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler attachment.save(mProviderContext); 215c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 216c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // Creates an attachment with a real file 217c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler Attachment attachment2 = setupSimpleAttachment(mProviderContext, message.mId, true); 218c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler attachment2.save(mProviderContext); 219c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 220c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler expectSimpleMessage(mockTransport); 221c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("Content-Type: multipart/mixed; boundary=\".*"); 222c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(""); 223c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("----.*"); 224c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler expectSimpleAttachment(mockTransport, attachment); 225c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(""); 226c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("----.*"); 227c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler expectSimpleAttachment(mockTransport, attachment2); 228c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(""); 229c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("----.*--"); 230c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("\r\n\\.", "250 2.0.0 kv2f1a00C02Rf8w3Vv mail accepted for delivery"); 231c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 232c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // Now trigger the transmission 233c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mSender.sendMessage(message.mId); 234c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler } 235c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 236c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler /** 237c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler * Test: Open and send a single message with body & attachment (sunny day) 238c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler */ 239c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler public void testSendMessageWithBodyAndAttachment() throws MessagingException, IOException { 240c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler MockTransport mockTransport = openAndInjectMockTransport(); 241c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 242c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // Since SmtpSender.sendMessage() does a close then open, we need to preset for the open 243c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expectClose(); 244c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler setupOpen(mockTransport, null); 245c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 246c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler Message message = setupSimpleMessage(); 247c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler message.save(mProviderContext); 248c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 249c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler Body body = new Body(); 250c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler body.mMessageKey = message.mId; 251c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler body.mTextContent = TEST_STRING; 252c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler body.save(mProviderContext); 253c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 254c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler Attachment attachment = setupSimpleAttachment(mProviderContext, message.mId, true); 255c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler attachment.save(mProviderContext); 256c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 25796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // prepare for the message traffic we'll see 258c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler expectSimpleMessage(mockTransport); 259c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("Content-Type: multipart/mixed; boundary=\".*"); 260c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(""); 261c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("----.*"); 262c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("Content-Type: text/plain; charset=utf-8"); 263c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("Content-Transfer-Encoding: base64"); 264c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(""); 265c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(TEST_STRING_BASE64); 266c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("----.*"); 267c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler expectSimpleAttachment(mockTransport, attachment); 268c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(""); 269c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("----.*--"); 270c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("\r\n\\.", "250 2.0.0 kv2f1a00C02Rf8w3Vv mail accepted for delivery"); 271c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 272c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // Now trigger the transmission 273c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mSender.sendMessage(message.mId); 274c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler } 275c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 276c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler /** 277c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler * Prepare to send a simple message (see setReceiveSimpleMessage) 278c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler */ 279c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler private Message setupSimpleMessage() { 280c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler Message message = new Message(); 281c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler message.mTimeStamp = System.currentTimeMillis(); 282c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler message.mFrom = Address.parseAndPack("Jones@Registry.Org"); 283c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler message.mTo = Address.parseAndPack("Smith@Registry.Org"); 284c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler message.mMessageId = "1234567890"; 285c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler return message; 286c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler } 287c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 288c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler /** 289c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler * Prepare to receive a simple message (see setupSimpleMessage) 290c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler */ 291c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler private void expectSimpleMessage(MockTransport mockTransport) { 292c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki mockTransport.expect("MAIL FROM: <Jones@Registry.Org>", 29396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project "250 2.1.0 <Jones@Registry.Org> sender ok"); 29496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mockTransport.expect("RCPT TO: <Smith@Registry.Org>", 29596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project "250 2.1.5 <Smith@Registry.Org> recipient ok"); 29696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mockTransport.expect("DATA", "354 enter mail, end with . on a line by itself"); 297c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("Date: .*"); 298c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("Message-ID: .*"); 299c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("From: Jones@Registry.Org"); 300c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("To: Smith@Registry.Org"); 3016bcccf628413d40696980d0d86c7ab2b4f831952Andrew Stadler mockTransport.expect("MIME-Version: 1.0"); 302c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler } 30396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 304c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler /** 305c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler * Prepare to send a simple attachment 306c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler */ 307c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler private Attachment setupSimpleAttachment(Context context, long messageId, boolean withBody) 308c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler throws IOException { 309c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler Attachment attachment = new Attachment(); 310c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler attachment.mFileName = "the file.jpg"; 311c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler attachment.mMimeType = "image/jpg"; 312c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler attachment.mSize = 0; 313c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler attachment.mContentId = null; 314c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler attachment.mContentUri = "content://com.android.email/1/1"; 315c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler attachment.mMessageKey = messageId; 316c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler attachment.mLocation = null; 317c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler attachment.mEncoding = null; 318c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 319c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler if (withBody) { 320c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // Is there an easier way to set up a temp file? 321c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler InputStream inStream = new ByteArrayInputStream(TEST_STRING.getBytes()); 322c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler File cacheDir = context.getCacheDir(); 323c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler File tmpFile = File.createTempFile("setupSimpleAttachment", "tmp", cacheDir); 324c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler OutputStream outStream = new FileOutputStream(tmpFile); 325c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 326c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler IOUtils.copy(inStream, outStream); 327c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler attachment.mContentUri = "file://" + tmpFile.getAbsolutePath(); 328c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler } 329c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 330c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler return attachment; 33196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 332c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 333c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler /** 334c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler * Prepare to receive a simple attachment (note, no multipart support here) 335c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler */ 336c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler private void expectSimpleAttachment(MockTransport mockTransport, Attachment attachment) { 337c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("Content-Type: " + attachment.mMimeType + ";"); 338c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(" name=\"" + attachment.mFileName + "\""); 339c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("Content-Transfer-Encoding: base64"); 340c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("Content-Disposition: attachment;"); 341c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(" filename=\"" + attachment.mFileName + "\";"); 342c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(" size=" + Long.toString(attachment.mSize)); 343c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(""); 344c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler if (attachment.mContentUri != null && attachment.mContentUri.startsWith("file://")) { 345c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(TEST_STRING_BASE64); 346c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler } 347c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler } 348c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 34996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /** 350b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler * Test: Recover from a server closing early (or returning an empty string) 351b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler */ 352f4dac9f266906a84f4710d8af5d4a24f2290b1baMakoto Onuki public void testEmptyLineResponse() throws Exception { 353b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler MockTransport mockTransport = openAndInjectMockTransport(); 354c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki 355b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler // Since SmtpSender.sendMessage() does a close then open, we need to preset for the open 356b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler mockTransport.expectClose(); 357c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki 358b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler // Load up just the bare minimum to expose the error 359b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler mockTransport.expect(null, "220 MockTransport 2000 Ready To Assist You Peewee"); 360f4dac9f266906a84f4710d8af5d4a24f2290b1baMakoto Onuki mockTransport.expect("EHLO " + Pattern.quote(LOCAL_ADDRESS), ""); 361c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki 362b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler // Now trigger the transmission 363b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler // Note, a null message is sufficient here, as we won't even get past open() 364b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler try { 365c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mSender.sendMessage(-1); 366b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler fail("Should not be able to send with failed open()"); 367b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler } catch (MessagingException me) { 368b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler // good - expected 369b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler // TODO maybe expect a particular exception? 370b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler } 371b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler } 372c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki 373b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler /** 37496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Set up a basic MockTransport. open it, and inject it into mStore 37596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 376f4dac9f266906a84f4710d8af5d4a24f2290b1baMakoto Onuki private MockTransport openAndInjectMockTransport() throws UnknownHostException { 37796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // Create mock transport and inject it into the SmtpSender that's already set up 37896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project MockTransport mockTransport = new MockTransport(); 379e4a7cc440f081ef9c4375a2bd2f82680cc11b152Andrew Stadler mockTransport.setSecurity(Transport.CONNECTION_SECURITY_NONE, false); 38096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mSender.setTransport(mockTransport); 381f4dac9f266906a84f4710d8af5d4a24f2290b1baMakoto Onuki mockTransport.setMockLocalAddress(InetAddress.getByName(LOCAL_ADDRESS)); 38296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return mockTransport; 38396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 384c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki 38596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /** 38696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Helper which stuffs the mock with enough strings to satisfy a call to SmtpSender.open() 387c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki * 38896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * @param mockTransport the mock transport we're using 38996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * @param capabilities if non-null, comma-separated list of capabilities 39096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 39196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project private void setupOpen(MockTransport mockTransport, String capabilities) { 39296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mockTransport.expect(null, "220 MockTransport 2000 Ready To Assist You Peewee"); 39396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mockTransport.expect("EHLO .*", "250-10.20.30.40 hello"); 39496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (capabilities == null) { 39596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mockTransport.expect(null, "250-HELP"); 39696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mockTransport.expect(null, "250-AUTH LOGIN PLAIN CRAM-MD5"); 39796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mockTransport.expect(null, "250-SIZE 15728640"); 39896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mockTransport.expect(null, "250-ENHANCEDSTATUSCODES"); 39996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mockTransport.expect(null, "250-8BITMIME"); 40096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } else { 40196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project for (String capability : capabilities.split(",")) { 40296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mockTransport.expect(null, "250-" + capability); 40396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 40496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 40596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mockTransport.expect(null, "250+OK"); 40696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mockTransport.expect("AUTH PLAIN .*", "235 2.7.0 ... authentication succeeded"); 40796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 40896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project} 409