SmtpSenderUnitTests.java revision c849936a36424645af73dc307b19778a89d6ee84
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.Address; 2196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport com.android.email.mail.MessagingException; 2296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport com.android.email.mail.Transport; 23c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadlerimport com.android.email.provider.EmailContent.Attachment; 24c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadlerimport com.android.email.provider.EmailContent.Body; 25c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadlerimport com.android.email.provider.EmailContent.Message; 26c849936a36424645af73dc307b19778a89d6ee84Makoto Onukiimport com.android.email.provider.EmailProvider; 2796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 28c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadlerimport org.apache.commons.io.IOUtils; 29c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 30c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadlerimport android.content.Context; 31c849936a36424645af73dc307b19778a89d6ee84Makoto Onukiimport android.test.AndroidTestCase; 3296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport android.test.suitebuilder.annotation.SmallTest; 3396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 34c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadlerimport java.io.ByteArrayInputStream; 35c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadlerimport java.io.File; 36c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadlerimport java.io.FileOutputStream; 37c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadlerimport java.io.IOException; 38c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadlerimport java.io.InputStream; 39c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadlerimport java.io.OutputStream; 40f4dac9f266906a84f4710d8af5d4a24f2290b1baMakoto Onukiimport java.net.InetAddress; 41f4dac9f266906a84f4710d8af5d4a24f2290b1baMakoto Onukiimport java.net.UnknownHostException; 42f4dac9f266906a84f4710d8af5d4a24f2290b1baMakoto Onukiimport java.util.regex.Pattern; 4396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 4496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project/** 4596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * This is a series of unit tests for the SMTP Sender class. These tests must be locally 4696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * complete - no server(s) required. 47c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler * 48c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler * These tests can be run with the following command: 49c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler * runtest -c com.android.email.mail.transport.SmtpSenderUnitTests email 5096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 5196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project@SmallTest 52c849936a36424645af73dc307b19778a89d6ee84Makoto Onukipublic class SmtpSenderUnitTests extends AndroidTestCase { 53c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 54c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler EmailProvider mProvider; 55c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler Context mProviderContext; 56c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler Context mContext; 57f4dac9f266906a84f4710d8af5d4a24f2290b1baMakoto Onuki private static final String LOCAL_ADDRESS = "1.2.3.4"; 5896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 5996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /* These values are provided by setUp() */ 6096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project private SmtpSender mSender = null; 61c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 62c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler /* Simple test string and its base64 equivalent */ 63c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler private final static String TEST_STRING = "Hello, world"; 64c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler private final static String TEST_STRING_BASE64 = "SGVsbG8sIHdvcmxk"; 65c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 6696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /** 6796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Setup code. We generate a lightweight SmtpSender for testing. 6896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 6996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project @Override 7096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project protected void setUp() throws Exception { 7196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project super.setUp(); 72c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki mProviderContext = DBTestHelper.ProviderContextSetupHelper.getProviderContext( 73c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki getContext()); 74c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mContext = getContext(); 75c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki 7696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // These are needed so we can get at the inner classes 77c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mSender = (SmtpSender) SmtpSender.newInstance(mProviderContext, 78c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler "smtp://user:password@server:999"); 7996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 8096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 8196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /** 8296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Confirms simple non-SSL non-TLS login 8396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 84f4dac9f266906a84f4710d8af5d4a24f2290b1baMakoto Onuki public void testSimpleLogin() throws Exception { 85c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki 8696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project MockTransport mockTransport = openAndInjectMockTransport(); 87c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki 8896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // try to open it 8996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project setupOpen(mockTransport, null); 9096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mSender.open(); 9196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 92c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki 9396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /** 9496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * TODO: Test with SSL negotiation (faked) 9596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * TODO: Test with SSL required but not supported 9696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * TODO: Test with TLS negotiation (faked) 9796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * TODO: Test with TLS required but not supported 9896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * TODO: Test other capabilities. 9996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * TODO: Test AUTH LOGIN 10096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 101c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki 10296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /** 10396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Test: Open and send a single message (sunny day) 10496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 105f4dac9f266906a84f4710d8af5d4a24f2290b1baMakoto Onuki public void testSendMessageWithBody() throws Exception { 10696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project MockTransport mockTransport = openAndInjectMockTransport(); 107c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 10896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // Since SmtpSender.sendMessage() does a close then open, we need to preset for the open 10996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mockTransport.expectClose(); 11096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project setupOpen(mockTransport, null); 11196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 112c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler Message message = setupSimpleMessage(); 113c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler message.save(mProviderContext); 114c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 115c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler Body body = new Body(); 116c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler body.mMessageKey = message.mId; 117c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler body.mTextContent = TEST_STRING; 118c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler body.save(mProviderContext); 119c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 120c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // prepare for the message traffic we'll see 121c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // TODO The test is a bit fragile, as we are order-dependent (and headers are not) 122c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler expectSimpleMessage(mockTransport); 123c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("Content-Type: text/plain; charset=utf-8"); 124c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("Content-Transfer-Encoding: base64"); 125c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(""); 126c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(TEST_STRING_BASE64); 127c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("\r\n\\.", "250 2.0.0 kv2f1a00C02Rf8w3Vv mail accepted for delivery"); 128c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 129c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // Now trigger the transmission 130c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mSender.sendMessage(message.mId); 131c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler } 132c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 133c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler /** 134c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler * Test: Open and send a single message with an empty attachment (no file) (sunny day) 135c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler */ 136c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler public void testSendMessageWithEmptyAttachment() throws MessagingException, IOException { 137c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler MockTransport mockTransport = openAndInjectMockTransport(); 138c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 139c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // Since SmtpSender.sendMessage() does a close then open, we need to preset for the open 140c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expectClose(); 141c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler setupOpen(mockTransport, null); 142c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 143c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler Message message = setupSimpleMessage(); 144c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler message.save(mProviderContext); 145c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 146c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // Creates an attachment with a bogus file (so we get headers only) 147c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler Attachment attachment = setupSimpleAttachment(mProviderContext, message.mId, false); 148c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler attachment.save(mProviderContext); 149c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 150c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler expectSimpleMessage(mockTransport); 151c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("Content-Type: multipart/mixed; boundary=\".*"); 152c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(""); 153c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("----.*"); 154c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler expectSimpleAttachment(mockTransport, attachment); 155c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(""); 156c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("----.*--"); 157c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("\r\n\\.", "250 2.0.0 kv2f1a00C02Rf8w3Vv mail accepted for delivery"); 158c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 159c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // Now trigger the transmission 160c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mSender.sendMessage(message.mId); 161c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler } 162c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 163c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler /** 164c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler * Test: Open and send a single message with an attachment (sunny day) 165c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler */ 166c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler public void testSendMessageWithAttachment() throws MessagingException, IOException { 167c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler MockTransport mockTransport = openAndInjectMockTransport(); 168c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 169c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // Since SmtpSender.sendMessage() does a close then open, we need to preset for the open 170c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expectClose(); 171c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler setupOpen(mockTransport, null); 172c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 173c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler Message message = setupSimpleMessage(); 174c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler message.save(mProviderContext); 175c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 176c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // Creates an attachment with a real file 177c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler Attachment attachment = setupSimpleAttachment(mProviderContext, message.mId, true); 178c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler attachment.save(mProviderContext); 179c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 180c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler expectSimpleMessage(mockTransport); 181c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("Content-Type: multipart/mixed; boundary=\".*"); 182c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(""); 183c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("----.*"); 184c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler expectSimpleAttachment(mockTransport, attachment); 185c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(""); 186c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("----.*--"); 187c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("\r\n\\.", "250 2.0.0 kv2f1a00C02Rf8w3Vv mail accepted for delivery"); 188c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 189c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // Now trigger the transmission 190c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mSender.sendMessage(message.mId); 191c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler } 192c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 193c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler /** 194c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler * Test: Open and send a single message with two attachments 195c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler */ 196c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler public void testSendMessageWithTwoAttachments() throws MessagingException, IOException { 197c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler MockTransport mockTransport = openAndInjectMockTransport(); 198c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 199c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // Since SmtpSender.sendMessage() does a close then open, we need to preset for the open 200c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expectClose(); 201c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler setupOpen(mockTransport, null); 202c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 203c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler Message message = setupSimpleMessage(); 204c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler message.save(mProviderContext); 205c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 206c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // Creates an attachment with a real file 207c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler Attachment attachment = setupSimpleAttachment(mProviderContext, message.mId, true); 208c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler attachment.save(mProviderContext); 209c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 210c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // Creates an attachment with a real file 211c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler Attachment attachment2 = setupSimpleAttachment(mProviderContext, message.mId, true); 212c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler attachment2.save(mProviderContext); 213c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 214c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler expectSimpleMessage(mockTransport); 215c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("Content-Type: multipart/mixed; boundary=\".*"); 216c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(""); 217c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("----.*"); 218c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler expectSimpleAttachment(mockTransport, attachment); 219c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(""); 220c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("----.*"); 221c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler expectSimpleAttachment(mockTransport, attachment2); 222c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(""); 223c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("----.*--"); 224c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("\r\n\\.", "250 2.0.0 kv2f1a00C02Rf8w3Vv mail accepted for delivery"); 225c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 226c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // Now trigger the transmission 227c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mSender.sendMessage(message.mId); 228c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler } 229c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 230c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler /** 231c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler * Test: Open and send a single message with body & attachment (sunny day) 232c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler */ 233c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler public void testSendMessageWithBodyAndAttachment() throws MessagingException, IOException { 234c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler MockTransport mockTransport = openAndInjectMockTransport(); 235c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 236c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // Since SmtpSender.sendMessage() does a close then open, we need to preset for the open 237c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expectClose(); 238c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler setupOpen(mockTransport, null); 239c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 240c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler Message message = setupSimpleMessage(); 241c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler message.save(mProviderContext); 242c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 243c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler Body body = new Body(); 244c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler body.mMessageKey = message.mId; 245c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler body.mTextContent = TEST_STRING; 246c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler body.save(mProviderContext); 247c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 248c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler Attachment attachment = setupSimpleAttachment(mProviderContext, message.mId, true); 249c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler attachment.save(mProviderContext); 250c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 25196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // prepare for the message traffic we'll see 252c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler expectSimpleMessage(mockTransport); 253c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("Content-Type: multipart/mixed; boundary=\".*"); 254c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(""); 255c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("----.*"); 256c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("Content-Type: text/plain; charset=utf-8"); 257c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("Content-Transfer-Encoding: base64"); 258c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(""); 259c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(TEST_STRING_BASE64); 260c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("----.*"); 261c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler expectSimpleAttachment(mockTransport, attachment); 262c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(""); 263c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("----.*--"); 264c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("\r\n\\.", "250 2.0.0 kv2f1a00C02Rf8w3Vv mail accepted for delivery"); 265c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 266c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // Now trigger the transmission 267c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mSender.sendMessage(message.mId); 268c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler } 269c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 270c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler /** 271c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler * Prepare to send a simple message (see setReceiveSimpleMessage) 272c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler */ 273c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler private Message setupSimpleMessage() { 274c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler Message message = new Message(); 275c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler message.mTimeStamp = System.currentTimeMillis(); 276c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler message.mFrom = Address.parseAndPack("Jones@Registry.Org"); 277c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler message.mTo = Address.parseAndPack("Smith@Registry.Org"); 278c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler message.mMessageId = "1234567890"; 279c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler return message; 280c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler } 281c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 282c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler /** 283c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler * Prepare to receive a simple message (see setupSimpleMessage) 284c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler */ 285c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler private void expectSimpleMessage(MockTransport mockTransport) { 286c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki mockTransport.expect("MAIL FROM: <Jones@Registry.Org>", 28796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project "250 2.1.0 <Jones@Registry.Org> sender ok"); 28896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mockTransport.expect("RCPT TO: <Smith@Registry.Org>", 28996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project "250 2.1.5 <Smith@Registry.Org> recipient ok"); 29096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mockTransport.expect("DATA", "354 enter mail, end with . on a line by itself"); 291c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("Date: .*"); 292c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("Message-ID: .*"); 293c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("From: Jones@Registry.Org"); 294c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("To: Smith@Registry.Org"); 2956bcccf628413d40696980d0d86c7ab2b4f831952Andrew Stadler mockTransport.expect("MIME-Version: 1.0"); 296c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler } 29796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 298c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler /** 299c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler * Prepare to send a simple attachment 300c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler */ 301c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler private Attachment setupSimpleAttachment(Context context, long messageId, boolean withBody) 302c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler throws IOException { 303c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler Attachment attachment = new Attachment(); 304c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler attachment.mFileName = "the file.jpg"; 305c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler attachment.mMimeType = "image/jpg"; 306c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler attachment.mSize = 0; 307c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler attachment.mContentId = null; 308c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler attachment.mContentUri = "content://com.android.email/1/1"; 309c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler attachment.mMessageKey = messageId; 310c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler attachment.mLocation = null; 311c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler attachment.mEncoding = null; 312c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 313c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler if (withBody) { 314c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler // Is there an easier way to set up a temp file? 315c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler InputStream inStream = new ByteArrayInputStream(TEST_STRING.getBytes()); 316c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler File cacheDir = context.getCacheDir(); 317c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler File tmpFile = File.createTempFile("setupSimpleAttachment", "tmp", cacheDir); 318c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler OutputStream outStream = new FileOutputStream(tmpFile); 319c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 320c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler IOUtils.copy(inStream, outStream); 321c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler attachment.mContentUri = "file://" + tmpFile.getAbsolutePath(); 322c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler } 323c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 324c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler return attachment; 32596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 326c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 327c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler /** 328c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler * Prepare to receive a simple attachment (note, no multipart support here) 329c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler */ 330c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler private void expectSimpleAttachment(MockTransport mockTransport, Attachment attachment) { 331c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("Content-Type: " + attachment.mMimeType + ";"); 332c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(" name=\"" + attachment.mFileName + "\""); 333c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("Content-Transfer-Encoding: base64"); 334c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect("Content-Disposition: attachment;"); 335c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(" filename=\"" + attachment.mFileName + "\";"); 336c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(" size=" + Long.toString(attachment.mSize)); 337c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(""); 338c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler if (attachment.mContentUri != null && attachment.mContentUri.startsWith("file://")) { 339c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mockTransport.expect(TEST_STRING_BASE64); 340c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler } 341c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler } 342c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler 34396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /** 344b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler * Test: Recover from a server closing early (or returning an empty string) 345b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler */ 346f4dac9f266906a84f4710d8af5d4a24f2290b1baMakoto Onuki public void testEmptyLineResponse() throws Exception { 347b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler MockTransport mockTransport = openAndInjectMockTransport(); 348c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki 349b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler // Since SmtpSender.sendMessage() does a close then open, we need to preset for the open 350b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler mockTransport.expectClose(); 351c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki 352b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler // Load up just the bare minimum to expose the error 353b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler mockTransport.expect(null, "220 MockTransport 2000 Ready To Assist You Peewee"); 354f4dac9f266906a84f4710d8af5d4a24f2290b1baMakoto Onuki mockTransport.expect("EHLO " + Pattern.quote(LOCAL_ADDRESS), ""); 355c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki 356b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler // Now trigger the transmission 357b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler // Note, a null message is sufficient here, as we won't even get past open() 358b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler try { 359c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler mSender.sendMessage(-1); 360b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler fail("Should not be able to send with failed open()"); 361b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler } catch (MessagingException me) { 362b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler // good - expected 363b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler // TODO maybe expect a particular exception? 364b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler } 365b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler } 366c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki 367b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler /** 36896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Set up a basic MockTransport. open it, and inject it into mStore 36996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 370f4dac9f266906a84f4710d8af5d4a24f2290b1baMakoto Onuki private MockTransport openAndInjectMockTransport() throws UnknownHostException { 37196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // Create mock transport and inject it into the SmtpSender that's already set up 37296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project MockTransport mockTransport = new MockTransport(); 373e4a7cc440f081ef9c4375a2bd2f82680cc11b152Andrew Stadler mockTransport.setSecurity(Transport.CONNECTION_SECURITY_NONE, false); 37496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mSender.setTransport(mockTransport); 375f4dac9f266906a84f4710d8af5d4a24f2290b1baMakoto Onuki mockTransport.setMockLocalAddress(InetAddress.getByName(LOCAL_ADDRESS)); 37696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project return mockTransport; 37796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 378c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki 37996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /** 38096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Helper which stuffs the mock with enough strings to satisfy a call to SmtpSender.open() 381c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki * 38296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * @param mockTransport the mock transport we're using 38396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * @param capabilities if non-null, comma-separated list of capabilities 38496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 38596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project private void setupOpen(MockTransport mockTransport, String capabilities) { 38696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mockTransport.expect(null, "220 MockTransport 2000 Ready To Assist You Peewee"); 38796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mockTransport.expect("EHLO .*", "250-10.20.30.40 hello"); 38896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project if (capabilities == null) { 38996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mockTransport.expect(null, "250-HELP"); 39096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mockTransport.expect(null, "250-AUTH LOGIN PLAIN CRAM-MD5"); 39196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mockTransport.expect(null, "250-SIZE 15728640"); 39296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mockTransport.expect(null, "250-ENHANCEDSTATUSCODES"); 39396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mockTransport.expect(null, "250-8BITMIME"); 39496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } else { 39596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project for (String capability : capabilities.split(",")) { 39696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mockTransport.expect(null, "250-" + capability); 39796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 39896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 39996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mockTransport.expect(null, "250+OK"); 40096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project mockTransport.expect("AUTH PLAIN .*", "235 2.7.0 ... authentication succeeded"); 40196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 40296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project} 403