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
19cb1d65c47825dc7a45c7954cd93669296b35305eBen Komaloimport android.content.Context;
20cb1d65c47825dc7a45c7954cd93669296b35305eBen Komaloimport android.test.AndroidTestCase;
21cb1d65c47825dc7a45c7954cd93669296b35305eBen Komaloimport android.test.suitebuilder.annotation.SmallTest;
22cb1d65c47825dc7a45c7954cd93669296b35305eBen Komalo
23c849936a36424645af73dc307b19778a89d6ee84Makoto Onukiimport com.android.email.DBTestHelper;
2496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport com.android.email.mail.Transport;
25c849936a36424645af73dc307b19778a89d6ee84Makoto Onukiimport com.android.email.provider.EmailProvider;
262193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.mail.Address;
272193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.mail.MessagingException;
28f5418f1f93b02e7fab9f15eb201800b65510998eMarc Blankimport com.android.emailcommon.provider.Account;
29a7bc0319a75184ad706bb35c049af107ac3688e6Marc Blankimport com.android.emailcommon.provider.EmailContent.Attachment;
30a7bc0319a75184ad706bb35c049af107ac3688e6Marc Blankimport com.android.emailcommon.provider.EmailContent.Body;
31a7bc0319a75184ad706bb35c049af107ac3688e6Marc Blankimport com.android.emailcommon.provider.EmailContent.Message;
3212b82d9374947c9268217f45befe8a74bd9b60d7Ben Komaloimport com.android.emailcommon.provider.HostAuth;
3396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
34c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadlerimport java.io.IOException;
35f4dac9f266906a84f4710d8af5d4a24f2290b1baMakoto Onukiimport java.net.InetAddress;
36f4dac9f266906a84f4710d8af5d4a24f2290b1baMakoto Onukiimport java.net.UnknownHostException;
3796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
3896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project/**
3996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * This is a series of unit tests for the SMTP Sender class.  These tests must be locally
4096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * complete - no server(s) required.
41c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler *
42c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler * These tests can be run with the following command:
43c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler *   runtest -c com.android.email.mail.transport.SmtpSenderUnitTests email
4496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */
4596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project@SmallTest
46c849936a36424645af73dc307b19778a89d6ee84Makoto Onukipublic class SmtpSenderUnitTests extends AndroidTestCase {
47c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler
48c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler    EmailProvider mProvider;
49c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler    Context mProviderContext;
50c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler    Context mContext;
51f4dac9f266906a84f4710d8af5d4a24f2290b1baMakoto Onuki    private static final String LOCAL_ADDRESS = "1.2.3.4";
5296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
5396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /* These values are provided by setUp() */
5496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private SmtpSender mSender = null;
55c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler
56c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler    /* Simple test string and its base64 equivalent */
57c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler    private final static String TEST_STRING = "Hello, world";
58c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler    private final static String TEST_STRING_BASE64 = "SGVsbG8sIHdvcmxk";
59c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler
6096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
6196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Setup code.  We generate a lightweight SmtpSender for testing.
6296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
6396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    @Override
6496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    protected void setUp() throws Exception {
6596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        super.setUp();
66c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki        mProviderContext = DBTestHelper.ProviderContextSetupHelper.getProviderContext(
67c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki                getContext());
68c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        mContext = getContext();
69c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki
70daf869cf60de75bc91ed3aef6ac0bff1fe371733Todd Kennedy        HostAuth testAuth = new HostAuth();
71daf869cf60de75bc91ed3aef6ac0bff1fe371733Todd Kennedy        Account testAccount = new Account();
72daf869cf60de75bc91ed3aef6ac0bff1fe371733Todd Kennedy
73daf869cf60de75bc91ed3aef6ac0bff1fe371733Todd Kennedy        testAuth.setLogin("user", "password");
74daf869cf60de75bc91ed3aef6ac0bff1fe371733Todd Kennedy        testAuth.setConnection("smtp", "server", 999);
75daf869cf60de75bc91ed3aef6ac0bff1fe371733Todd Kennedy        testAccount.mHostAuthSend = testAuth;
76daf869cf60de75bc91ed3aef6ac0bff1fe371733Todd Kennedy        mSender = (SmtpSender) SmtpSender.newInstance(testAccount, mProviderContext);
7796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
7896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
7996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
8096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Confirms simple non-SSL non-TLS login
8196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
82f4dac9f266906a84f4710d8af5d4a24f2290b1baMakoto Onuki    public void testSimpleLogin() throws Exception {
83c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki
8496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        MockTransport mockTransport = openAndInjectMockTransport();
85c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki
8696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // try to open it
8796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        setupOpen(mockTransport, null);
8896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mSender.open();
8996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
90c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki
9196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
9296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * TODO: Test with SSL negotiation (faked)
9396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * TODO: Test with SSL required but not supported
9496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * TODO: Test with TLS negotiation (faked)
9596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * TODO: Test with TLS required but not supported
9696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * TODO: Test other capabilities.
9796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * TODO: Test AUTH LOGIN
9896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
99c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki
10096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
10196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Test:  Open and send a single message (sunny day)
10296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
103f4dac9f266906a84f4710d8af5d4a24f2290b1baMakoto Onuki    public void testSendMessageWithBody() throws Exception {
10496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        MockTransport mockTransport = openAndInjectMockTransport();
105c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler
10696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // Since SmtpSender.sendMessage() does a close then open, we need to preset for the open
10796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mockTransport.expectClose();
10896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        setupOpen(mockTransport, null);
10996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
110c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        Message message = setupSimpleMessage();
111c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        message.save(mProviderContext);
112c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler
113c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        Body body = new Body();
114c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        body.mMessageKey = message.mId;
115c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        body.mTextContent = TEST_STRING;
116c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        body.save(mProviderContext);
117c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler
118c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        // prepare for the message traffic we'll see
119c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        // TODO The test is a bit fragile, as we are order-dependent (and headers are not)
120c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        expectSimpleMessage(mockTransport);
121c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        mockTransport.expect("Content-Type: text/plain; charset=utf-8");
122c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        mockTransport.expect("Content-Transfer-Encoding: base64");
123c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        mockTransport.expect("");
124c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        mockTransport.expect(TEST_STRING_BASE64);
125c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        mockTransport.expect("\r\n\\.", "250 2.0.0 kv2f1a00C02Rf8w3Vv mail accepted for delivery");
126c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler
127c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        // Now trigger the transmission
128c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        mSender.sendMessage(message.mId);
129c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler    }
130c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler
131c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler    /**
132c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler     * Test:  Open and send a single message with an empty attachment (no file) (sunny day)
133c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler     */
134c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler    public void testSendMessageWithEmptyAttachment() throws MessagingException, IOException {
135c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        MockTransport mockTransport = openAndInjectMockTransport();
136c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler
137c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        // Since SmtpSender.sendMessage() does a close then open, we need to preset for the open
138c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        mockTransport.expectClose();
139c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        setupOpen(mockTransport, null);
140c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler
141c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        Message message = setupSimpleMessage();
142c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        message.save(mProviderContext);
143c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler
144c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        // Creates an attachment with a bogus file (so we get headers only)
145cb1d65c47825dc7a45c7954cd93669296b35305eBen Komalo        Attachment attachment = setupSimpleAttachment(mProviderContext, message.mId);
146c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        attachment.save(mProviderContext);
147c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler
148c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        expectSimpleMessage(mockTransport);
149c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        mockTransport.expect("Content-Type: multipart/mixed; boundary=\".*");
150c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        mockTransport.expect("");
151c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        mockTransport.expect("----.*");
152c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        expectSimpleAttachment(mockTransport, attachment);
153c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        mockTransport.expect("");
154c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        mockTransport.expect("----.*--");
155c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        mockTransport.expect("\r\n\\.", "250 2.0.0 kv2f1a00C02Rf8w3Vv mail accepted for delivery");
156c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler
157c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        // Now trigger the transmission
158c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        mSender.sendMessage(message.mId);
159c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler    }
160c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler
161c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler    /**
162c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler     * Prepare to send a simple message (see setReceiveSimpleMessage)
163c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler     */
164c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler    private Message setupSimpleMessage() {
165c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        Message message = new Message();
166c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        message.mTimeStamp = System.currentTimeMillis();
167c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        message.mFrom = Address.parseAndPack("Jones@Registry.Org");
168c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        message.mTo = Address.parseAndPack("Smith@Registry.Org");
169c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        message.mMessageId = "1234567890";
170c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        return message;
171c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler    }
172c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler
173c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler    /**
174c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler     * Prepare to receive a simple message (see setupSimpleMessage)
175c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler     */
176c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler    private void expectSimpleMessage(MockTransport mockTransport) {
177c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki        mockTransport.expect("MAIL FROM: <Jones@Registry.Org>",
17896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                "250 2.1.0 <Jones@Registry.Org> sender ok");
17996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mockTransport.expect("RCPT TO: <Smith@Registry.Org>",
18096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                "250 2.1.5 <Smith@Registry.Org> recipient ok");
18196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mockTransport.expect("DATA", "354 enter mail, end with . on a line by itself");
182c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        mockTransport.expect("Date: .*");
183c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        mockTransport.expect("Message-ID: .*");
184c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        mockTransport.expect("From: Jones@Registry.Org");
185c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        mockTransport.expect("To: Smith@Registry.Org");
1866bcccf628413d40696980d0d86c7ab2b4f831952Andrew Stadler        mockTransport.expect("MIME-Version: 1.0");
187c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler    }
18896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project
189c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler    /**
190c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler     * Prepare to send a simple attachment
191c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler     */
192cb1d65c47825dc7a45c7954cd93669296b35305eBen Komalo    private Attachment setupSimpleAttachment(Context context, long messageId) {
193c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        Attachment attachment = new Attachment();
194c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        attachment.mFileName = "the file.jpg";
195c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        attachment.mMimeType = "image/jpg";
196c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        attachment.mSize = 0;
197c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        attachment.mContentId = null;
198c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        attachment.mContentUri = "content://com.android.email/1/1";
199c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        attachment.mMessageKey = messageId;
200c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        attachment.mLocation = null;
201c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        attachment.mEncoding = null;
202c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler
203c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        return attachment;
20496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
205c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler
206c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler    /**
207c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler     * Prepare to receive a simple attachment (note, no multipart support here)
208c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler     */
209c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler    private void expectSimpleAttachment(MockTransport mockTransport, Attachment attachment) {
210c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        mockTransport.expect("Content-Type: " + attachment.mMimeType + ";");
211c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        mockTransport.expect(" name=\"" + attachment.mFileName + "\"");
212c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        mockTransport.expect("Content-Transfer-Encoding: base64");
213c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        mockTransport.expect("Content-Disposition: attachment;");
214c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        mockTransport.expect(" filename=\"" + attachment.mFileName + "\";");
215c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        mockTransport.expect(" size=" + Long.toString(attachment.mSize));
216c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        mockTransport.expect("");
217c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        if (attachment.mContentUri != null && attachment.mContentUri.startsWith("file://")) {
218c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler            mockTransport.expect(TEST_STRING_BASE64);
219c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler        }
220c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler    }
221c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler
22296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
223b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler     * Test:  Recover from a server closing early (or returning an empty string)
224b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler     */
225f4dac9f266906a84f4710d8af5d4a24f2290b1baMakoto Onuki    public void testEmptyLineResponse() throws Exception {
226b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler        MockTransport mockTransport = openAndInjectMockTransport();
227c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki
228b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler        // Since SmtpSender.sendMessage() does a close then open, we need to preset for the open
229b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler        mockTransport.expectClose();
230c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki
231b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler        // Load up just the bare minimum to expose the error
232b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler        mockTransport.expect(null, "220 MockTransport 2000 Ready To Assist You Peewee");
233cb1d65c47825dc7a45c7954cd93669296b35305eBen Komalo        mockTransport.expectLiterally("EHLO [" + LOCAL_ADDRESS + "]", null);
234c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki
235b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler        // Now trigger the transmission
236b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler        // Note, a null message is sufficient here, as we won't even get past open()
237b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler        try {
238c640cbbaf385566e1b6de361b2b23156e10f695dAndrew Stadler            mSender.sendMessage(-1);
239b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler            fail("Should not be able to send with failed open()");
240b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler        } catch (MessagingException me) {
241b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler            // good - expected
242b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler            // TODO maybe expect a particular exception?
243b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler        }
244b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler    }
245c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki
246b011a812e05902d7e417b8c47acc90a592f4b412Andrew Stadler    /**
24796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Set up a basic MockTransport. open it, and inject it into mStore
24896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
249f4dac9f266906a84f4710d8af5d4a24f2290b1baMakoto Onuki    private MockTransport openAndInjectMockTransport() throws UnknownHostException {
25096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        // Create mock transport and inject it into the SmtpSender that's already set up
25196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        MockTransport mockTransport = new MockTransport();
252e4a7cc440f081ef9c4375a2bd2f82680cc11b152Andrew Stadler        mockTransport.setSecurity(Transport.CONNECTION_SECURITY_NONE, false);
25396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mSender.setTransport(mockTransport);
254f4dac9f266906a84f4710d8af5d4a24f2290b1baMakoto Onuki        mockTransport.setMockLocalAddress(InetAddress.getByName(LOCAL_ADDRESS));
25596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        return mockTransport;
25696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
257c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki
25896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    /**
25996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * Helper which stuffs the mock with enough strings to satisfy a call to SmtpSender.open()
260c849936a36424645af73dc307b19778a89d6ee84Makoto Onuki     *
26196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @param mockTransport the mock transport we're using
26296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     * @param capabilities if non-null, comma-separated list of capabilities
26396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project     */
26496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    private void setupOpen(MockTransport mockTransport, String capabilities) {
26596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mockTransport.expect(null, "220 MockTransport 2000 Ready To Assist You Peewee");
26696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mockTransport.expect("EHLO .*", "250-10.20.30.40 hello");
26796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        if (capabilities == null) {
26896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            mockTransport.expect(null, "250-HELP");
26996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            mockTransport.expect(null, "250-AUTH LOGIN PLAIN CRAM-MD5");
27096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            mockTransport.expect(null, "250-SIZE 15728640");
27196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            mockTransport.expect(null, "250-ENHANCEDSTATUSCODES");
27296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            mockTransport.expect(null, "250-8BITMIME");
27396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        } else {
27496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            for (String capability : capabilities.split(",")) {
27596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project                mockTransport.expect(null, "250-" + capability);
27696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project            }
27796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        }
27896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mockTransport.expect(null, "250+OK");
27996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project        mockTransport.expect("AUTH PLAIN .*", "235 2.7.0 ... authentication succeeded");
28096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project    }
28196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project}
282