1   /*****************************************************************
2    * Licensed to the Apache Software Foundation (ASF) under one   *
3    * or more contributor license agreements.  See the NOTICE file *
4    * distributed with this work for additional information        *
5    * regarding copyright ownership.  The ASF licenses this file   *
6    * to you under the Apache License, Version 2.0 (the            *
7    * "License"); you may not use this file except in compliance   *
8    * with the License.  You may obtain a copy of the License at   *
9    *                                                              *
10   *   http://www.apache.org/licenses/LICENSE-2.0                 *
11   *                                                              *
12   * Unless required by applicable law or agreed to in writing,   *
13   * software distributed under the License is distributed on an  *
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
15   * KIND, either express or implied.  See the License for the    *
16   * specific language governing permissions and limitations      *
17   * under the License.                                           *
18   ****************************************************************/
19  package org.apache.james.pop3server;
20  
21  import org.apache.avalon.cornerstone.services.sockets.SocketManager;
22  import org.apache.avalon.cornerstone.services.threads.ThreadManager;
23  import org.apache.avalon.framework.container.ContainerUtil;
24  import org.apache.commons.net.pop3.POP3Client;
25  import org.apache.commons.net.pop3.POP3MessageInfo;
26  import org.apache.james.core.MailImpl;
27  import org.apache.james.core.MimeMessageCopyOnWriteProxy;
28  import org.apache.james.core.MimeMessageInputStreamSource;
29  import org.apache.james.services.JamesConnectionManager;
30  import org.apache.james.services.MailServer;
31  import org.apache.james.services.UsersRepository;
32  import org.apache.james.test.mock.avalon.MockLogger;
33  import org.apache.james.test.mock.avalon.MockServiceManager;
34  import org.apache.james.test.mock.avalon.MockSocketManager;
35  import org.apache.james.test.mock.avalon.MockThreadManager;
36  import org.apache.james.test.mock.james.MockMailRepository;
37  import org.apache.james.test.mock.james.MockMailServer;
38  import org.apache.james.test.util.Util;
39  import org.apache.james.userrepository.MockUsersRepository;
40  import org.apache.james.util.connection.SimpleConnectionManager;
41  import org.apache.mailet.MailAddress;
42  
43  import javax.mail.MessagingException;
44  import javax.mail.internet.MimeMessage;
45  import javax.mail.util.SharedByteArrayInputStream;
46  
47  import java.io.Reader;
48  import java.util.ArrayList;
49  
50  import junit.framework.TestCase;
51  
52  /***
53   * Tests the org.apache.james.smtpserver.SMTPServer unit
54   */
55  public class POP3ServerTest extends TestCase {
56      private int m_pop3ListenerPort = Util.getNonPrivilegedPort();
57  
58      private MockMailServer m_mailServer;
59  
60      private POP3TestConfiguration m_testConfiguration;
61  
62      private POP3Server m_pop3Server;
63  
64      private MockUsersRepository m_usersRepository = new MockUsersRepository();
65      private POP3Client m_pop3Protocol = null;
66  
67      public POP3ServerTest() {
68          super("POP3ServerTest");
69      }
70  
71      protected void setUp() throws Exception {
72          m_pop3Server = new POP3Server();
73          ContainerUtil.enableLogging(m_pop3Server, new MockLogger());
74          ContainerUtil.service(m_pop3Server, setUpServiceManager());
75          m_testConfiguration = new POP3TestConfiguration(m_pop3ListenerPort);
76      }
77  
78      private void finishSetUp(POP3TestConfiguration testConfiguration)
79              throws Exception {
80          testConfiguration.init();
81          ContainerUtil.configure(m_pop3Server, testConfiguration);
82          ContainerUtil.initialize(m_pop3Server);
83      }
84  
85      private MockServiceManager setUpServiceManager() {
86          MockServiceManager serviceManager = new MockServiceManager();
87          SimpleConnectionManager connectionManager = new SimpleConnectionManager();
88          ContainerUtil.enableLogging(connectionManager, new MockLogger());
89          serviceManager.put(JamesConnectionManager.ROLE, connectionManager);
90          m_mailServer = new MockMailServer();
91          serviceManager
92                  .put(MailServer.ROLE, m_mailServer);
93          serviceManager.put(UsersRepository.ROLE,
94                  m_usersRepository);
95          serviceManager.put(SocketManager.ROLE, new MockSocketManager(
96                  m_pop3ListenerPort));
97          serviceManager.put(ThreadManager.ROLE, new MockThreadManager());
98          return serviceManager;
99      }
100 
101     protected void tearDown() throws Exception {
102         super.tearDown();
103         if (m_pop3Protocol != null) {
104             m_pop3Protocol.sendCommand("quit");
105             m_pop3Protocol.disconnect();
106         }
107         m_pop3Server.dispose();
108     }
109 
110     public void testAuthenticationFail() throws Exception {
111         finishSetUp(m_testConfiguration);
112         
113         m_pop3Protocol = new POP3Client();
114         m_pop3Protocol.connect("127.0.0.1", m_pop3ListenerPort);
115 
116         m_usersRepository.addUser("known", "test2");
117 
118         m_pop3Protocol.login("known", "test");
119         assertEquals(0, m_pop3Protocol.getState());
120         assertTrue(m_pop3Protocol.getReplyString().startsWith("-ERR"));
121     }
122 
123     public void testUnknownUser() throws Exception {
124         finishSetUp(m_testConfiguration);
125 
126         m_pop3Protocol = new POP3Client();
127         m_pop3Protocol.connect("127.0.0.1", m_pop3ListenerPort);
128 
129         m_pop3Protocol.login("unknown", "test");
130         assertEquals(0, m_pop3Protocol.getState());
131         assertTrue(m_pop3Protocol.getReplyString().startsWith("-ERR"));
132     }
133 
134     public void testKnownUserEmptyInbox() throws Exception {
135         finishSetUp(m_testConfiguration);
136 
137         m_pop3Protocol = new POP3Client();
138         m_pop3Protocol.connect("127.0.0.1",m_pop3ListenerPort);
139 
140         m_usersRepository.addUser("foo", "bar");
141         m_mailServer.setUserInbox("foo", new MockMailRepository());
142 
143         m_pop3Protocol.login("foo", "bar");
144         System.err.println(m_pop3Protocol.getState());
145         assertEquals(1, m_pop3Protocol.getState());
146 
147         POP3MessageInfo[] entries = m_pop3Protocol.listMessages();
148         assertEquals(1, m_pop3Protocol.getState());
149 
150         assertNotNull(entries);
151         assertEquals(entries.length, 0);
152     }
153 
154     public void testNotAsciiCharsInPassword() throws Exception {
155         finishSetUp(m_testConfiguration);
156 
157         m_pop3Protocol = new POP3Client();
158         m_pop3Protocol.connect("127.0.0.1",m_pop3ListenerPort);
159 
160         String pass = "bar" + (new String(new char[] { 200, 210 })) + "foo";
161         m_usersRepository.addUser("foo", pass);
162         m_mailServer.setUserInbox("foo", new MockMailRepository());
163 
164         m_pop3Protocol.login("foo", pass);
165         assertEquals(1, m_pop3Protocol.getState());
166     }
167 
168     public void testKnownUserInboxWithMessages() throws Exception {
169         finishSetUp(m_testConfiguration);
170 
171         m_pop3Protocol = new POP3Client();
172         m_pop3Protocol.connect("127.0.0.1",m_pop3ListenerPort);
173 
174         m_usersRepository.addUser("foo2", "bar2");
175         MockMailRepository mailRep = new MockMailRepository();
176 
177         setupTestMails(mailRep);
178 
179         m_mailServer.setUserInbox("foo2", mailRep);
180 
181         m_pop3Protocol.login("foo2", "bar2");
182         assertEquals(1, m_pop3Protocol.getState());
183 
184         POP3MessageInfo[] entries = m_pop3Protocol.listMessages();
185 
186         assertNotNull(entries);
187         assertEquals(2, entries.length);
188         assertEquals(1, m_pop3Protocol.getState());
189 
190         Reader r = m_pop3Protocol.retrieveMessageTop(entries[0].number, 0);
191         assertNotNull(r);
192         r.close();
193 
194         Reader r2 = m_pop3Protocol.retrieveMessage(entries[0].number);
195         assertNotNull(r2);
196         r2.close();
197 
198         boolean deleted = m_pop3Protocol.deleteMessage(entries[0].number);
199 
200         assertTrue(deleted);
201         assertEquals(1, m_pop3Protocol.getState());
202 
203         m_pop3Protocol.sendCommand("quit");
204         m_pop3Protocol.disconnect();
205 
206         m_pop3Protocol.connect("127.0.0.1",m_pop3ListenerPort);
207 
208         m_pop3Protocol.login("foo2", "bar2");
209         assertEquals(1, m_pop3Protocol.getState());
210 
211         entries = null;
212 
213         POP3MessageInfo stats = m_pop3Protocol.status();
214         assertEquals(92, stats.size);
215         assertEquals(1, stats.number);
216 
217         entries = m_pop3Protocol.listMessages();
218 
219         assertNotNull(entries);
220         assertEquals(1, entries.length);
221         assertEquals(1, m_pop3Protocol.getState());
222 
223         Reader r3 = m_pop3Protocol.retrieveMessageTop(entries[0].number, 0);
224         assertNotNull(r3);
225         r3.close();
226     }
227 
228     private void setupTestMails(MockMailRepository mailRep) throws MessagingException {
229         ArrayList recipients = new ArrayList();
230         recipients.add(new MailAddress("recipient@test.com"));
231         MimeMessage mw = new MimeMessageCopyOnWriteProxy(
232                 new MimeMessageInputStreamSource(
233                         "test",
234                         new SharedByteArrayInputStream(
235                                 ("Return-path: return@test.com\r\n"+
236                                  "Content-Transfer-Encoding: plain\r\n"+
237                                  "Subject: test\r\n\r\n"+
238                                  "Body Text\r\n").getBytes())));
239         MailImpl m = new MailImpl("name", new MailAddress("from@test.com"),
240                 recipients, mw);
241         mailRep.store(m);
242         MimeMessage mw2 = new MimeMessageCopyOnWriteProxy(
243                 new MimeMessageInputStreamSource(
244                         "test2",
245                         new SharedByteArrayInputStream(
246                                 ("").getBytes())));
247         MailImpl mailimpl2 = new MailImpl("name2", new MailAddress("from@test.com"),
248                         recipients, mw2);
249         mailRep.store(mailimpl2);
250         m.dispose();
251         mailimpl2.dispose();
252     }
253 
254     public void testTwoSimultaneousMails() throws Exception {
255         finishSetUp(m_testConfiguration);
256 
257         
258         m_usersRepository.addUser("foo1", "bar1");
259         MockMailRepository mailRep1 = new MockMailRepository();
260         setupTestMails(mailRep1);
261         m_mailServer.setUserInbox("foo1", mailRep1);
262 
263         m_usersRepository.addUser("foo2", "bar2");
264         MockMailRepository mailRep2 = new MockMailRepository();
265         
266         m_mailServer.setUserInbox("foo2", mailRep2);
267 
268         POP3Client pop3Protocol2 = null;
269         try {
270             
271             m_pop3Protocol = new POP3Client();
272             m_pop3Protocol.connect("127.0.0.1", m_pop3ListenerPort);
273             pop3Protocol2 = new POP3Client();
274             pop3Protocol2.connect("127.0.0.1", m_pop3ListenerPort);
275 
276             assertEquals("first connection taken", 0, m_pop3Protocol.getState());
277             assertEquals("second connection taken", 0, pop3Protocol2.getState());
278 
279             
280             m_pop3Protocol.login("foo1", "bar1");
281 
282             pop3Protocol2.login("foo2", "bar2");
283 
284             POP3MessageInfo[] entries = m_pop3Protocol.listMessages();
285             assertEquals("foo1 has mails", 2, entries.length);
286 
287             entries = pop3Protocol2.listMessages();
288             assertEquals("foo2 has no mails", 0, entries.length);
289 
290         } finally {
291             
292             if (pop3Protocol2 != null) {
293                 pop3Protocol2.sendCommand("quit");
294                 pop3Protocol2.disconnect();
295             }
296         }
297     }
298 
299 }