View Javadoc

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.smtpserver;
20  
21  import org.apache.avalon.cornerstone.services.sockets.SocketManager;
22  import org.apache.avalon.cornerstone.services.store.Store;
23  import org.apache.avalon.cornerstone.services.threads.ThreadManager;
24  import org.apache.avalon.framework.container.ContainerUtil;
25  import org.apache.commons.net.smtp.SMTPClient;
26  import org.apache.commons.net.smtp.SMTPReply;
27  import org.apache.james.Constants;
28  import org.apache.james.core.MailImpl;
29  import org.apache.james.services.DNSServer;
30  import org.apache.james.services.JamesConnectionManager;
31  import org.apache.james.services.MailServer;
32  import org.apache.james.services.UsersRepository;
33  import org.apache.james.test.mock.avalon.MockLogger;
34  import org.apache.james.test.mock.avalon.MockServiceManager;
35  import org.apache.james.test.mock.avalon.MockSocketManager;
36  import org.apache.james.test.mock.avalon.MockStore;
37  import org.apache.james.test.mock.avalon.MockThreadManager;
38  import org.apache.james.test.mock.james.InMemorySpoolRepository;
39  import org.apache.james.test.mock.james.MockMailServer;
40  import org.apache.james.test.mock.mailet.MockMailContext;
41  import org.apache.james.test.mock.mailet.MockMailetConfig;
42  import org.apache.james.test.util.Util;
43  import org.apache.james.transport.mailets.RemoteDelivery;
44  import org.apache.james.userrepository.MockUsersRepository;
45  import org.apache.james.util.Base64;
46  import org.apache.james.util.connection.SimpleConnectionManager;
47  import org.apache.mailet.MailAddress;
48  
49  import javax.mail.MessagingException;
50  import javax.mail.Session;
51  import javax.mail.internet.MimeMessage;
52  
53  import java.io.ByteArrayInputStream;
54  import java.io.ByteArrayOutputStream;
55  import java.io.IOException;
56  import java.io.Writer;
57  import java.net.InetAddress;
58  import java.net.Socket;
59  import java.net.UnknownHostException;
60  import java.util.ArrayList;
61  import java.util.Arrays;
62  import java.util.Collection;
63  import java.util.Iterator;
64  import java.util.List;
65  import java.util.Properties;
66  
67  import junit.framework.TestCase;
68  
69  /***
70   * Tests the org.apache.james.smtpserver.SMTPServer unit 
71   */
72  public class SMTPServerTest extends TestCase {
73      private int m_smtpListenerPort = Util.getNonPrivilegedPort();
74      private MockMailServer m_mailServer;
75      private SMTPTestConfiguration m_testConfiguration;
76      private SMTPServer m_smtpServer;
77      private MockUsersRepository m_usersRepository = new MockUsersRepository();
78  
79      public SMTPServerTest() {
80          super("SMTPServerTest");
81      }
82  
83      public void verifyLastMail(String sender, String recipient, MimeMessage msg) throws IOException, MessagingException {
84          Object[] mailData = m_mailServer.getLastMail();
85          assertNotNull("mail received by mail server", mailData);
86  
87          if (sender == null && recipient == null && msg == null) fail("no verification can be done with all arguments null");
88  
89          if (sender != null) assertEquals("sender verfication", sender, ((MailAddress)mailData[0]).toString());
90          if (recipient != null) assertTrue("recipient verfication", ((Collection) mailData[1]).contains(new MailAddress(recipient)));
91          if (msg != null) {
92              ByteArrayOutputStream bo1 = new ByteArrayOutputStream();
93              msg.writeTo(bo1);
94              ByteArrayOutputStream bo2 = new ByteArrayOutputStream();
95              ((MimeMessage) mailData[2]).writeTo(bo2);
96              assertEquals(bo1.toString(),bo2.toString());
97              assertEquals("message verification", msg, ((MimeMessage) mailData[2]));
98          }
99      }
100     
101     protected void setUp() throws Exception {
102         m_smtpServer = new SMTPServer();
103         ContainerUtil.enableLogging(m_smtpServer,new MockLogger());
104         m_serviceManager = setUpServiceManager();
105         ContainerUtil.service(m_smtpServer, m_serviceManager);
106         m_testConfiguration = new SMTPTestConfiguration(m_smtpListenerPort);
107     }
108 
109     private void finishSetUp(SMTPTestConfiguration testConfiguration) throws Exception {
110         testConfiguration.init();
111         ContainerUtil.configure(m_smtpServer, testConfiguration);
112         ContainerUtil.initialize(m_smtpServer);
113         m_mailServer.setMaxMessageSizeBytes(m_testConfiguration.getMaxMessageSize()*1024);
114     }
115 
116     private MockServiceManager setUpServiceManager() throws Exception {
117         m_serviceManager = new MockServiceManager();
118         SimpleConnectionManager connectionManager = new SimpleConnectionManager();
119         ContainerUtil.enableLogging(connectionManager, new MockLogger());
120         m_serviceManager.put(JamesConnectionManager.ROLE, connectionManager);
121         m_serviceManager.put("org.apache.mailet.MailetContext", new MockMailContext());
122         m_mailServer = new MockMailServer();
123         m_serviceManager.put(MailServer.ROLE, m_mailServer);
124         m_serviceManager.put(UsersRepository.ROLE, m_usersRepository);
125         m_serviceManager.put(SocketManager.ROLE, new MockSocketManager(m_smtpListenerPort));
126         m_serviceManager.put(ThreadManager.ROLE, new MockThreadManager());
127         // Mock DNS Server
128         DNSServer dns = new DNSServer() {
129 
130             public Collection findMXRecords(String hostname) {
131                 List res = new ArrayList();
132                 if (hostname == null) {
133                     return res;
134                 };
135                 if ("james.apache.org".equals(hostname)) {
136                     res.add("nagoya.apache.org");
137                 }
138                 return res;
139             }
140 
141             public Iterator getSMTPHostAddresses(String domainName) {
142                 throw new UnsupportedOperationException("Unimplemented mock service");
143             }
144             
145 
146             public InetAddress[] getAllByName(String host) throws UnknownHostException
147             {
148                 return new InetAddress[] {getByName(host)};
149 //                throw new UnsupportedOperationException("getByName not implemented in mock for host: "+host);
150             }
151 
152 
153             public InetAddress getByName(String host) throws UnknownHostException
154             {
155                 return InetAddress.getByName(host);
156 //                throw new UnsupportedOperationException("getByName not implemented in mock for host: "+host);
157             }
158             
159             public Collection findTXTRecords(String hostname) {
160                 List res = new ArrayList();
161                 if (hostname == null) {
162                     return res;
163                 };
164                 if ("2.0.0.127.bl.spamcop.net".equals(hostname)) {
165                     res.add("Blocked - see http://www.spamcop.net/bl.shtml?127.0.0.2");
166                 }
167                 return res;
168             }
169             
170         };
171         m_serviceManager.put(DNSServer.ROLE, dns);
172         m_serviceManager.put(Store.ROLE, new MockStore());
173         return m_serviceManager;
174     }
175 
176     public void testSimpleMailSendWithEHLO() throws Exception {
177         finishSetUp(m_testConfiguration);
178         
179         SMTPClient smtpProtocol = new SMTPClient();
180         smtpProtocol.connect("127.0.0.1", m_smtpListenerPort);
181 
182         // no message there, yet
183         assertNull("no mail received by mail server", m_mailServer.getLastMail());
184 
185         smtpProtocol.sendCommand("EHLO "+InetAddress.getLocalHost());
186         String[] capabilityRes = smtpProtocol.getReplyStrings();
187         
188         List capabilitieslist = new ArrayList();
189         for (int i = 1; i < capabilityRes.length; i++) {
190             capabilitieslist.add(capabilityRes[i].substring(4));
191         }
192         
193         assertEquals("capabilities", 2, capabilitieslist.size());
194         assertTrue("capabilities present PIPELINING", capabilitieslist.contains("PIPELINING"));
195         assertTrue("capabilities present ENHANCEDSTATUSCODES", capabilitieslist.contains("ENHANCEDSTATUSCODES"));
196         //assertTrue("capabilities present 8BITMIME", capabilitieslist.contains("8BITMIME"));
197 
198         smtpProtocol.setSender("mail@localhost");
199         smtpProtocol.addRecipient("mail@localhost");
200 
201         smtpProtocol.sendShortMessageData("Subject: test\r\n\r\nBody\r\n\r\n.\r\n");
202         smtpProtocol.quit();
203         smtpProtocol.disconnect();
204 
205         // mail was propagated by SMTPServer
206         assertNotNull("mail received by mail server", m_mailServer.getLastMail());
207     }
208 
209     public void testEmptyMessage() throws Exception {
210         finishSetUp(m_testConfiguration);
211 
212         SMTPClient smtp = new SMTPClient();
213         smtp.connect("127.0.0.1", m_smtpListenerPort);
214 
215         // no message there, yet
216         assertNull("no mail received by mail server", m_mailServer.getLastMail());
217 
218         smtp.helo(InetAddress.getLocalHost().toString());
219         
220         smtp.setSender("mail@localhost");
221         
222         smtp.addRecipient("mail@localhost");
223 
224         smtp.sendShortMessageData("");
225 
226         smtp.quit();
227         
228         smtp.disconnect();
229 
230         // mail was propagated by SMTPServer
231         assertNotNull("mail received by mail server", m_mailServer.getLastMail());
232 
233         // added to check a NPE in the test (JAMES-474) due to MockMailServer
234         // not cloning the message (added a MimeMessageCopyOnWriteProxy there)
235         System.gc();
236 
237         int size = ((MimeMessage) m_mailServer.getLastMail()[2]).getSize();
238 
239         assertEquals(size, 2);
240     }
241 
242     public void testSimpleMailSendWithHELO() throws Exception {
243         finishSetUp(m_testConfiguration);
244 
245         SMTPClient smtpProtocol = new SMTPClient();
246         smtpProtocol.connect("127.0.0.1", m_smtpListenerPort);
247 
248         // no message there, yet
249         assertNull("no mail received by mail server", m_mailServer.getLastMail());
250 
251         smtpProtocol.helo(InetAddress.getLocalHost().toString());
252         
253         smtpProtocol.setSender("mail@localhost");
254         
255         smtpProtocol.addRecipient("mail@localhost");
256 
257         smtpProtocol.sendShortMessageData("Subject: test mail\r\n\r\nTest body\r\n.\r\n");
258 
259         smtpProtocol.quit();
260         smtpProtocol.disconnect();
261 
262         // mail was propagated by SMTPServer
263         assertNotNull("mail received by mail server", m_mailServer.getLastMail());
264     }
265 
266     public void testTwoSimultaneousMails() throws Exception {
267         finishSetUp(m_testConfiguration);
268 
269         SMTPClient smtpProtocol1 = new SMTPClient();
270         smtpProtocol1.connect("127.0.0.1", m_smtpListenerPort);
271         SMTPClient smtpProtocol2 = new SMTPClient();
272         smtpProtocol2.connect("127.0.0.1", m_smtpListenerPort);
273 
274         assertTrue("first connection taken",smtpProtocol1.isConnected());
275         assertTrue("second connection taken",smtpProtocol2.isConnected());
276 
277         // no message there, yet
278         assertNull("no mail received by mail server", m_mailServer.getLastMail());
279 
280         smtpProtocol1.helo(InetAddress.getLocalHost().toString());
281         smtpProtocol2.helo(InetAddress.getLocalHost().toString());
282 
283         String sender1 = "mail_sender1@localhost";
284         String recipient1 = "mail_recipient1@localhost";
285         smtpProtocol1.setSender(sender1);
286         smtpProtocol1.addRecipient(recipient1);
287 
288         String sender2 = "mail_sender2@localhost";
289         String recipient2 = "mail_recipient2@localhost";
290         smtpProtocol2.setSender(sender2);
291         smtpProtocol2.addRecipient(recipient2);
292 
293         smtpProtocol1.sendShortMessageData("Subject: test\r\n\r\nTest body\r\n.\r\n");
294         verifyLastMail(sender1, recipient1, null);
295             
296         smtpProtocol2.sendShortMessageData("Subject: test\r\n\r\nTest body\r\n.\r\n");
297         verifyLastMail(sender2, recipient2, null);
298 
299         smtpProtocol1.quit();
300         smtpProtocol2.quit();
301         
302         smtpProtocol1.disconnect();
303         smtpProtocol2.disconnect();
304     }
305 
306     public void testTwoMailsInSequence() throws Exception {
307         finishSetUp(m_testConfiguration);
308 
309         SMTPClient smtpProtocol1 = new SMTPClient();
310         smtpProtocol1.connect("127.0.0.1", m_smtpListenerPort);
311 
312         assertTrue("first connection taken", smtpProtocol1.isConnected());
313 
314         // no message there, yet
315         assertNull("no mail received by mail server", m_mailServer.getLastMail());
316 
317         smtpProtocol1.helo(InetAddress.getLocalHost().toString());
318 
319         String sender1 = "mail_sender1@localhost";
320         String recipient1 = "mail_recipient1@localhost";
321         smtpProtocol1.setSender(sender1);
322         smtpProtocol1.addRecipient(recipient1);
323 
324         smtpProtocol1.sendShortMessageData("Subject: test\r\n\r\nTest body\r\n");
325         verifyLastMail(sender1, recipient1, null);
326             
327         String sender2 = "mail_sender2@localhost";
328         String recipient2 = "mail_recipient2@localhost";
329         smtpProtocol1.setSender(sender2);
330         smtpProtocol1.addRecipient(recipient2);
331 
332         smtpProtocol1.sendShortMessageData("Subject: test2\r\n\r\nTest body2\r\n");
333         verifyLastMail(sender2, recipient2, null);
334 
335         smtpProtocol1.quit();
336         smtpProtocol1.disconnect();
337     }
338     
339     public void testHeloResolv() throws Exception {
340         m_testConfiguration.setHeloResolv();
341         m_testConfiguration.setAuthorizedAddresses("192.168.0.1");
342         finishSetUp(m_testConfiguration);
343 
344 
345         SMTPClient smtpProtocol1 = new SMTPClient();
346         smtpProtocol1.connect("127.0.0.1", m_smtpListenerPort);
347 
348         assertTrue("first connection taken", smtpProtocol1.isConnected());
349 
350         // no message there, yet
351         assertNull("no mail received by mail server", m_mailServer.getLastMail());
352 
353         String helo1 = "abgsfe3rsf.de";
354         String helo2 = "james.apache.org";
355         
356         smtpProtocol1.sendCommand("helo",helo1);
357         // this should give a 501 code cause the helo could not resolved
358         assertEquals("expected error: helo could not resolved", 501, smtpProtocol1.getReplyCode());
359             
360         smtpProtocol1.sendCommand("helo", helo2);
361         // helo is resolvable. so this should give a 250 code
362         assertEquals("Helo accepted", 250, smtpProtocol1.getReplyCode());
363 
364         smtpProtocol1.quit();
365     }
366     
367     public void testHeloResolvDefault() throws Exception {
368         finishSetUp(m_testConfiguration);
369 
370         SMTPClient smtpProtocol1 = new SMTPClient();
371         smtpProtocol1.connect("127.0.0.1", m_smtpListenerPort);
372         
373         smtpProtocol1.helo("abgsfe3rsf.de");
374         // helo should not be checked. so this should give a 250 code
375         assertEquals("Helo accepted", 250, smtpProtocol1.getReplyCode());
376 
377         smtpProtocol1.quit();
378     }
379     
380     public void testSenderDomainResolv() throws Exception {
381         m_testConfiguration.setSenderDomainResolv();
382         m_testConfiguration.setAuthorizedAddresses("192.168.0.1/32");
383         finishSetUp(m_testConfiguration);
384 
385         SMTPClient smtpProtocol1 = new SMTPClient();
386         smtpProtocol1.connect("127.0.0.1", m_smtpListenerPort);
387 
388         
389         assertTrue("first connection taken", smtpProtocol1.isConnected());
390 
391         // no message there, yet
392         assertNull("no mail received by mail server", m_mailServer.getLastMail());
393 
394         smtpProtocol1.helo(InetAddress.getLocalHost().toString());
395 
396         String sender1 = "mail_sender1@xfwrqqfgfe.de";
397         String sender2 = "mail_sender2@james.apache.org";
398         
399         smtpProtocol1.setSender(sender1);
400         assertEquals("expected 501 error", 501, smtpProtocol1.getReplyCode());
401     
402         smtpProtocol1.setSender(sender2);
403 
404         smtpProtocol1.quit();
405         
406     }
407  
408     public void testSenderDomainResolvDefault() throws Exception {
409         finishSetUp(m_testConfiguration);
410 
411         SMTPClient smtpProtocol1 = new SMTPClient();
412         smtpProtocol1.connect("127.0.0.1", m_smtpListenerPort);
413         
414         smtpProtocol1.helo(InetAddress.getLocalHost().toString());
415         
416         String sender1 = "mail_sender1@xfwrqqfgfe.de";
417         
418         smtpProtocol1.setSender(sender1);
419 
420         smtpProtocol1.quit();
421     }
422     
423     public void testSenderDomainResolvRelayClientDefault() throws Exception {
424         m_testConfiguration.setSenderDomainResolv();
425         finishSetUp(m_testConfiguration);
426 
427         SMTPClient smtpProtocol1 = new SMTPClient();
428         smtpProtocol1.connect("127.0.0.1", m_smtpListenerPort);
429 
430         
431         assertTrue("first connection taken", smtpProtocol1.isConnected());
432 
433         // no message there, yet
434         assertNull("no mail received by mail server", m_mailServer.getLastMail());
435 
436         smtpProtocol1.helo(InetAddress.getLocalHost().toString());
437 
438         String sender1 = "mail_sender1@xfwrqqfgfe.de";
439         
440         // Both mail shold
441         smtpProtocol1.setSender(sender1);
442 
443         smtpProtocol1.quit();
444         
445     }
446     
447     public void testSenderDomainResolvRelayClient() throws Exception {
448         m_testConfiguration.setSenderDomainResolv();
449         m_testConfiguration.setCheckAuthClients(true);
450         finishSetUp(m_testConfiguration);
451 
452         SMTPClient smtpProtocol1 = new SMTPClient();
453         smtpProtocol1.connect("127.0.0.1", m_smtpListenerPort);
454 
455         
456         assertTrue("first connection taken", smtpProtocol1.isConnected());
457 
458         // no message there, yet
459         assertNull("no mail received by mail server", m_mailServer.getLastMail());
460 
461         smtpProtocol1.helo(InetAddress.getLocalHost().toString());
462 
463         String sender1 = "mail_sender1@xfwrqqfgfe.de";
464         String sender2 = "mail_sender2@james.apache.org";
465         
466         smtpProtocol1.setSender(sender1);
467         assertEquals("expected 501 error", 501, smtpProtocol1.getReplyCode());
468     
469         smtpProtocol1.setSender(sender2);
470 
471         smtpProtocol1.quit();
472         
473     }
474     
475     public void testMaxRcpt() throws Exception {
476         m_testConfiguration.setMaxRcpt(1);
477         finishSetUp(m_testConfiguration);
478 
479 
480         SMTPClient smtpProtocol1 = new SMTPClient();
481         smtpProtocol1.connect("127.0.0.1", m_smtpListenerPort);
482 
483         assertTrue("first connection taken", smtpProtocol1.isConnected());
484 
485         // no message there, yet
486         assertNull("no mail received by mail server", m_mailServer.getLastMail());
487 
488         smtpProtocol1.helo(InetAddress.getLocalHost().toString());
489 
490         String sender1 = "mail_sender1@james.apache.org";
491         String rcpt1 = "test@localhost";
492         String rcpt2 = "test2@localhost";
493     
494         smtpProtocol1.setSender(sender1);
495         smtpProtocol1.addRecipient(rcpt1);
496 
497         smtpProtocol1.addRecipient(rcpt2);
498         assertEquals("expected 452 error", 452, smtpProtocol1.getReplyCode());
499         
500         smtpProtocol1.sendShortMessageData("Subject: test\r\n\r\nTest body\r\n");
501         
502         // After the data is send the rcpt count is set back to 0.. So a new mail with rcpt should be accepted
503         
504         smtpProtocol1.setSender(sender1);
505  
506         smtpProtocol1.addRecipient(rcpt1);
507         
508         smtpProtocol1.sendShortMessageData("Subject: test\r\n\r\nTest body\r\n");
509         
510         smtpProtocol1.quit();
511         
512     }
513 
514     public void testMaxRcptDefault() throws Exception {
515         finishSetUp(m_testConfiguration);
516 
517         SMTPClient smtpProtocol1 = new SMTPClient();
518         smtpProtocol1.connect("127.0.0.1", m_smtpListenerPort);
519         
520         smtpProtocol1.helo(InetAddress.getLocalHost().toString());
521         
522         String sender1 = "mail_sender1@james.apache.org";
523         String rcpt1 = "test@localhost";
524         
525         smtpProtocol1.setSender(sender1);
526         
527         smtpProtocol1.addRecipient(rcpt1);
528         
529         smtpProtocol1.sendShortMessageData("Subject: test\r\n\r\nTest body\r\n");
530         
531         smtpProtocol1.quit();
532     }
533   
534     public void testEhloResolv() throws Exception {
535         m_testConfiguration.setEhloResolv();
536         m_testConfiguration.setAuthorizedAddresses("192.168.0.1");
537         finishSetUp(m_testConfiguration);
538 
539 
540         SMTPClient smtpProtocol1 = new SMTPClient();
541         smtpProtocol1.connect("127.0.0.1", m_smtpListenerPort);
542 
543         assertTrue("first connection taken", smtpProtocol1.isConnected());
544 
545         // no message there, yet
546         assertNull("no mail received by mail server", m_mailServer.getLastMail());
547 
548         String ehlo1 = "abgsfe3rsf.de";
549         String ehlo2 = "james.apache.org";
550         
551         smtpProtocol1.sendCommand("ehlo", ehlo1);
552         // this should give a 501 code cause the ehlo could not resolved
553         assertEquals("expected error: ehlo could not resolved", 501, smtpProtocol1.getReplyCode());
554             
555         smtpProtocol1.sendCommand("ehlo", ehlo2);
556         // ehlo is resolvable. so this should give a 250 code
557         assertEquals("ehlo accepted", 250, smtpProtocol1.getReplyCode());
558 
559         smtpProtocol1.quit();
560     }
561     
562     public void testEhloResolvDefault() throws Exception {
563         finishSetUp(m_testConfiguration);
564 
565         SMTPClient smtpProtocol1 = new SMTPClient();
566         smtpProtocol1.connect("127.0.0.1", m_smtpListenerPort);
567         
568         smtpProtocol1.sendCommand("ehlo","abgsfe3rsf.de");
569         // ehlo should not be checked. so this should give a 250 code
570         assertEquals("ehlo accepted", 250, smtpProtocol1.getReplyCode());
571 
572         smtpProtocol1.quit();
573     }
574     
575     public void testEhloResolvIgnoreClientDisabled() throws Exception {
576         m_testConfiguration.setEhloResolv();
577         m_testConfiguration.setCheckAuthNetworks(true);
578         finishSetUp(m_testConfiguration);
579 
580 
581         SMTPClient smtpProtocol1 = new SMTPClient();
582         smtpProtocol1.connect("127.0.0.1", m_smtpListenerPort);
583 
584         assertTrue("first connection taken", smtpProtocol1.isConnected());
585 
586         // no message there, yet
587         assertNull("no mail received by mail server", m_mailServer.getLastMail());
588 
589         String ehlo1 = "abgsfe3rsf.de";
590         String ehlo2 = "james.apache.org";
591         
592         smtpProtocol1.sendCommand("ehlo", ehlo1);
593         // this should give a 501 code cause the ehlo could not resolved
594         assertEquals("expected error: ehlo could not resolved", 501, smtpProtocol1.getReplyCode());
595             
596         smtpProtocol1.sendCommand("ehlo", ehlo2);
597         // ehlo is resolvable. so this should give a 250 code
598         assertEquals("ehlo accepted", 250, smtpProtocol1.getReplyCode());
599 
600         smtpProtocol1.quit();
601     }
602     
603     public void testHeloEnforcement() throws Exception {
604         finishSetUp(m_testConfiguration);
605 
606         SMTPClient smtpProtocol1 = new SMTPClient();
607         smtpProtocol1.connect("127.0.0.1", m_smtpListenerPort);
608 
609         assertTrue("first connection taken", smtpProtocol1.isConnected());
610 
611         // no message there, yet
612         assertNull("no mail received by mail server", m_mailServer.getLastMail());
613 
614         String sender1 = "mail_sender1@localhost";
615         smtpProtocol1.setSender(sender1);
616         assertEquals("expected 503 error", 503, smtpProtocol1.getReplyCode());
617         
618         smtpProtocol1.helo(InetAddress.getLocalHost().toString());
619         
620         smtpProtocol1.setSender(sender1);
621         
622         smtpProtocol1.quit();
623     }
624     
625     public void testHeloEnforcementDisabled() throws Exception {
626         m_testConfiguration.setHeloEhloEnforcement(false);
627         finishSetUp(m_testConfiguration);
628 
629         SMTPClient smtpProtocol1 = new SMTPClient();
630         smtpProtocol1.connect("127.0.0.1", m_smtpListenerPort);
631 
632         assertTrue("first connection taken", smtpProtocol1.isConnected());
633 
634         // no message there, yet
635         assertNull("no mail received by mail server", m_mailServer.getLastMail());
636 
637         String sender1 = "mail_sender1@localhost";
638         
639         smtpProtocol1.setSender(sender1);
640         
641         smtpProtocol1.quit();
642     }
643 
644     public void testAuth() throws Exception {
645         m_testConfiguration.setAuthorizedAddresses("128.0.0.1/8");
646         m_testConfiguration.setAuthorizingAnnounce();
647         finishSetUp(m_testConfiguration);
648 
649         SMTPClient smtpProtocol = new SMTPClient();
650         smtpProtocol.connect("127.0.0.1", m_smtpListenerPort);
651 
652         smtpProtocol.sendCommand("ehlo", InetAddress.getLocalHost().toString());
653         String[] capabilityRes = smtpProtocol.getReplyStrings();
654         
655         List capabilitieslist = new ArrayList();
656         for (int i = 1; i < capabilityRes.length; i++) {
657             capabilitieslist.add(capabilityRes[i].substring(4));
658         }
659             
660         assertTrue("anouncing auth required", capabilitieslist.contains("AUTH LOGIN PLAIN"));
661         // is this required or just for compatibility? assertTrue("anouncing auth required", capabilitieslist.contains("AUTH=LOGIN PLAIN"));
662 
663         String userName = "test_user_smtp";
664         String noexistUserName = "noexist_test_user_smtp";
665         String sender ="test_user_smtp@localhost";
666         smtpProtocol.sendCommand("AUTH FOO", null);
667         assertEquals("expected error: unrecognized authentication type", 504, smtpProtocol.getReplyCode());
668 
669         smtpProtocol.setSender(sender);
670 
671         smtpProtocol.addRecipient("mail@sample.com");
672         assertEquals("expected 530 error", 530, smtpProtocol.getReplyCode());
673 
674         assertFalse("user not existing", m_usersRepository.contains(noexistUserName));
675 
676         smtpProtocol.sendCommand("AUTH PLAIN");
677         smtpProtocol.sendCommand(Base64.encodeAsString("\0"+noexistUserName+"\0pwd\0"));
678 //        smtpProtocol.sendCommand(noexistUserName+"pwd".toCharArray());
679         assertEquals("expected error", 535, smtpProtocol.getReplyCode());
680 
681         m_usersRepository.addUser(userName, "pwd");
682 
683         smtpProtocol.sendCommand("AUTH PLAIN");
684         smtpProtocol.sendCommand(Base64.encodeAsString("\0"+userName+"\0wrongpwd\0"));
685         assertEquals("expected error", 535, smtpProtocol.getReplyCode());
686 
687         smtpProtocol.sendCommand("AUTH PLAIN");
688         smtpProtocol.sendCommand(Base64.encodeAsString("\0"+userName+"\0pwd\0"));
689         assertEquals("authenticated", 235, smtpProtocol.getReplyCode());
690 
691         smtpProtocol.sendCommand("AUTH PLAIN");
692         assertEquals("expected error: User has previously authenticated.", 503, smtpProtocol.getReplyCode());
693 
694         smtpProtocol.addRecipient("mail@sample.com");
695         smtpProtocol.sendShortMessageData("Subject: test\r\n\r\nTest body\r\n");
696 
697         smtpProtocol.quit();
698 
699         // mail was propagated by SMTPServer
700         assertNotNull("mail received by mail server", m_mailServer.getLastMail());
701     }
702 
703     public void testAuthWithEmptySender() throws Exception {
704         m_testConfiguration.setAuthorizedAddresses("128.0.0.1/8");
705         m_testConfiguration.setAuthorizingAnnounce();
706         finishSetUp(m_testConfiguration);
707 
708         SMTPClient smtpProtocol = new SMTPClient();
709         smtpProtocol.connect("127.0.0.1", m_smtpListenerPort);
710 
711         smtpProtocol.sendCommand("ehlo "+InetAddress.getLocalHost());
712 
713         String userName = "test_user_smtp";
714         m_usersRepository.addUser(userName, "pwd");
715 
716         smtpProtocol.setSender("");
717 
718         smtpProtocol.sendCommand("AUTH PLAIN");
719         smtpProtocol.sendCommand(Base64.encodeAsString("\0"+userName+"\0pwd\0"));
720         assertEquals("authenticated", 235, smtpProtocol.getReplyCode());
721 
722         smtpProtocol.addRecipient("mail@sample.com");
723         assertEquals("expected error", 503, smtpProtocol.getReplyCode());
724         
725         smtpProtocol.quit();
726     }
727 
728     public void testNoRecepientSpecified() throws Exception {
729         finishSetUp(m_testConfiguration);
730 
731         SMTPClient smtpProtocol = new SMTPClient();
732         smtpProtocol.connect("127.0.0.1", m_smtpListenerPort);
733 
734         smtpProtocol.sendCommand("ehlo "+InetAddress.getLocalHost());
735 
736         smtpProtocol.setSender("mail@sample.com");
737 
738         // left out for test smtpProtocol.rcpt(new Address("mail@localhost"));
739 
740         smtpProtocol.sendShortMessageData("Subject: test\r\n\r\nTest body\r\n");
741         assertTrue("sending succeeded without recepient", SMTPReply.isNegativePermanent(smtpProtocol.getReplyCode()));
742 
743         smtpProtocol.quit();
744 
745         // mail was propagated by SMTPServer
746         assertNull("no mail received by mail server", m_mailServer.getLastMail());
747     }
748 
749     public void testMultipleMailsAndRset() throws Exception {
750         finishSetUp(m_testConfiguration);
751 
752         SMTPClient smtpProtocol = new SMTPClient();
753         smtpProtocol.connect("127.0.0.1", m_smtpListenerPort);
754 
755         smtpProtocol.sendCommand("ehlo "+InetAddress.getLocalHost());
756 
757         smtpProtocol.setSender("mail@sample.com");
758         
759         smtpProtocol.reset();
760         
761         smtpProtocol.setSender("mail@sample.com");
762 
763         smtpProtocol.quit();
764 
765         // mail was propagated by SMTPServer
766         assertNull("no mail received by mail server", m_mailServer.getLastMail());
767     }
768 
769     public void testRelayingDenied() throws Exception {
770         m_testConfiguration.setAuthorizedAddresses("128.0.0.1/8");
771         finishSetUp(m_testConfiguration);
772 
773         SMTPClient smtpProtocol = new SMTPClient();
774         smtpProtocol.connect("127.0.0.1", m_smtpListenerPort);
775 
776         smtpProtocol.sendCommand("ehlo "+InetAddress.getLocalHost());
777 
778         smtpProtocol.setSender("mail@sample.com");
779 
780         smtpProtocol.addRecipient("maila@sample.com");
781         assertEquals("expected 550 error", 550, smtpProtocol.getReplyCode());
782     }
783 
784     public void testHandleAnnouncedMessageSizeLimitExceeded() throws Exception {
785         m_testConfiguration.setMaxMessageSize(1); // set message limit to 1kb
786         finishSetUp(m_testConfiguration);
787 
788         SMTPClient smtpProtocol = new SMTPClient();
789         smtpProtocol.connect("127.0.0.1", m_smtpListenerPort);
790 
791         smtpProtocol.sendCommand("ehlo "+InetAddress.getLocalHost());
792 
793         smtpProtocol.sendCommand("MAIL FROM:<mail@localhost> SIZE=1025", null);
794         assertEquals("expected error: max msg size exceeded", 552, smtpProtocol.getReplyCode());
795 
796         smtpProtocol.addRecipient("mail@localhost");
797         assertEquals("expected error", 503, smtpProtocol.getReplyCode());
798     }
799 
800     public void testHandleMessageSizeLimitExceeded() throws Exception {
801         m_testConfiguration.setMaxMessageSize(1); // set message limit to 1kb 
802         finishSetUp(m_testConfiguration);
803 
804         SMTPClient smtpProtocol = new SMTPClient();
805         smtpProtocol.connect("127.0.0.1", m_smtpListenerPort);
806 
807         smtpProtocol.sendCommand("ehlo "+InetAddress.getLocalHost());
808 
809         smtpProtocol.setSender("mail@localhost");
810         smtpProtocol.addRecipient("mail@localhost");
811 
812         Writer wr = smtpProtocol.sendMessageData();
813         // create Body with more than 1kb . 502
814         wr.write("1234567810123456782012345678301234567840123456785012345678601234567870123456788012345678901234567100");
815         wr.write("1234567810123456782012345678301234567840123456785012345678601234567870123456788012345678901234567100");
816         wr.write("1234567810123456782012345678301234567840123456785012345678601234567870123456788012345678901234567100");
817         wr.write("1234567810123456782012345678301234567840123456785012345678601234567870123456788012345678901234567100");
818         wr.write("1234567810123456782012345678301234567840123456785012345678601234567870123456788012345678901234567100\r\n");
819         // second line
820         wr.write("1234567810123456782012345678301234567840123456785012345678601234567870123456788012345678901234567100");
821         wr.write("1234567810123456782012345678301234567840123456785012345678601234567870123456788012345678901234567100");
822         wr.write("1234567810123456782012345678301234567840123456785012345678601234567870123456788012345678901234567100");
823         wr.write("1234567810123456782012345678301234567840123456785012345678601234567870123456788012345678901234567100");
824         wr.write("1234567810123456782012345678301234567840123456785012345678601234567870123456788012345678901234567100");
825         wr.write("123456781012345678201\r\n"); // 521 + CRLF = 523 + 502 => 1025
826         wr.close();
827         
828         assertFalse(smtpProtocol.completePendingCommand());
829 
830         assertEquals("expected 552 error", 552, smtpProtocol.getReplyCode());
831 
832     }
833 
834     public void testHandleMessageSizeLimitRespected() throws Exception {
835         m_testConfiguration.setMaxMessageSize(1); // set message limit to 1kb 
836         finishSetUp(m_testConfiguration);
837 
838         SMTPClient smtpProtocol = new SMTPClient();
839         smtpProtocol.connect("127.0.0.1", m_smtpListenerPort);
840 
841         smtpProtocol.sendCommand("ehlo "+InetAddress.getLocalHost());
842 
843         smtpProtocol.setSender("mail@localhost");
844         smtpProtocol.addRecipient("mail@localhost");
845 
846         Writer wr = smtpProtocol.sendMessageData();
847         // create Body with less than 1kb
848         wr.write("1234567810123456782012345678301234567840123456785012345678601234567870123456788012345678901234567100");
849         wr.write("1234567810123456782012345678301234567840123456785012345678601234567870123456788012345678901234567100");
850         wr.write("1234567810123456782012345678301234567840123456785012345678601234567870123456788012345678901234567100");
851         wr.write("1234567810123456782012345678301234567840123456785012345678601234567870123456788012345678901234567100");
852         wr.write("1234567810123456782012345678301234567840123456785012345678601234567870123456788012345678901234567100");
853         wr.write("1234567810123456782012345678301234567840123456785012345678601234567870123456788012345678901234567100");
854         wr.write("1234567810123456782012345678301234567840123456785012345678601234567870123456788012345678901234567100");
855         wr.write("1234567810123456782012345678301234567840123456785012345678601234567870123456788012345678901234567100");
856         wr.write("1234567810123456782012345678301234567840123456785012345678601234567870123456788012345678901234567100");
857         wr.write("1234567810123456782012345678301234567840123456785012345678601234567870123456788012345678901234567100");
858         wr.write("1234567810123456782012\r\n"); // 1022 + CRLF = 1024
859         wr.close();
860         
861         assertTrue(smtpProtocol.completePendingCommand());
862 
863         assertEquals("expected 250 ok", 250, smtpProtocol.getReplyCode());
864 
865     }
866 
867     /*
868       What we want to see is that for a given connection limit and a
869       given backlog, that connection limit requests are handled, and
870       that up to the backlog number of connections are queued.  More
871       connections than that would eventually error out (unless space
872       connections than that should error out until space opens up in
873       the queue.
874 
875       For example:
876 
877         # telnet localhost <m_smtpListenPort>
878         Trying 127.0.0.1...
879         telnet: Unable to connect to remote host: Connection refused
880 
881       is the immediate response if the backlog is full.
882     */
883 
884     public void testConnectionLimitExceeded() throws Exception {
885         final int acceptLimit = 1;
886         final int backlog = 1;
887 
888         m_testConfiguration.setConnectionLimit(acceptLimit);   // allow no more than <acceptLimit> connection(s) in the service
889         m_testConfiguration.setConnectionBacklog(backlog);     // allow <backlog> additional connection(s) in the queue
890         finishSetUp(m_testConfiguration);
891 
892         final SMTPClient[] client = new SMTPClient[acceptLimit];
893         for (int i = 0; i < client.length; i++) {
894              client[i] = new SMTPClient(); // should connect to worker
895              try {
896                 client[i].connect("127.0.0.1", m_smtpListenerPort);
897             } catch (Exception _) {
898             }
899             assertTrue("client #" + (i+1) + " established", client[i].isConnected());
900         }
901 
902         // Cannot use SMTPClient.  It appears that even though the
903         // client's socket is established, since the client won't be
904         // able to connect to the protocol handler, the connect call
905         // hangs.
906         // Different TCP/IP stacks may provide a "grace" margin above
907         // and beyond the specified backlog.  So we won't try to be
908         // precise.  Instead we will compute some upper limit, loop
909         // until we get a connection error (or hit the limit), and
910         // then test for the expected behavior.
911         //
912         // See: http://www.phrack.org/archives/48/P48-13
913         final Socket connection[] = new Socket[Math.max(((backlog * 3) / 2) + 1, backlog + 3)];
914 
915         final java.net.SocketAddress server = new java.net.InetSocketAddress("localhost", m_smtpListenerPort);
916 
917         for (int i = 0; i < connection.length; i++) {
918             connection[i] = new Socket();
919             try {
920                 connection[i].connect(server, 1000);
921             } catch (Exception _) {
922                 assertTrue("Accepted connections " + i + " did not meet or exceed backlog of " + backlog + ".", i >= backlog);
923                 connection[i] = null; // didn't open, so don't try to close later
924                 break; // OK to fail, since we've at least reached the backlog          
925             }
926             assertTrue("connection #" + (i+1) + " established", connection[i].isConnected());
927         }
928         
929         try {
930             final Socket shouldFail = new Socket();
931             shouldFail.connect(server, 1000);
932             fail("connection # " + (client.length + connection.length + 1) + " did not fail.");            
933         } catch (Exception _) {      
934         }
935         
936         client[0].quit();
937         client[0].disconnect();  
938         
939         Thread.sleep(100);
940 
941         // now should be able to connect (backlog)
942         try {
943             final Socket shouldWork = new Socket();
944             shouldWork.connect(server, 1000);
945             assertTrue("Additional connection established after close.", shouldWork.isConnected());
946             shouldWork.close();
947         } catch (Exception e) {
948             fail("Could not establish additional connection after close." + e.getMessage());
949         }
950         
951         // close the pending connections first, so that the server doesn't see them
952         for (int i = 0; i < connection.length; i++) if (connection[i] != null) connection[i].close();
953         
954         // close the remaining clients
955         for (int i = 1; i < client.length; i++) {
956             client[i].quit();
957             client[i].disconnect();
958         }
959     }
960 
961     
962     // RemoteDelivery tests.
963     
964     InMemorySpoolRepository outgoingSpool;
965     private MockServiceManager m_serviceManager;
966     
967     private Properties getStandardParameters() {
968         Properties parameters = new Properties();
969         parameters.put("delayTime", "500 msec, 500 msec, 500 msec"); // msec, sec, minute, hour
970         parameters.put("maxRetries", "3");
971         parameters.put("deliveryThreads", "1");
972         parameters.put("debug", "true");
973         parameters.put("sendpartial", "false");
974         parameters.put("bounceProcessor", "bounce");
975         parameters.put("outgoing", "mocked://outgoing/");
976         return parameters;
977     }
978     
979 
980     /***
981      * This has been created to test javamail 1.4 introduced bug.
982      * http://issues.apache.org/jira/browse/JAMES-490
983      */
984     public void testDeliveryToSelfWithGatewayAndBind() throws Exception {
985         finishSetUp(m_testConfiguration);
986         outgoingSpool = new InMemorySpoolRepository();
987         ((MockStore) m_serviceManager.lookup(Store.ROLE)).add("outgoing", outgoingSpool);
988         
989         RemoteDelivery rd = new RemoteDelivery();
990         
991         MockMailContext mmc = new MockMailContext();
992         mmc.setAttribute(Constants.AVALON_COMPONENT_MANAGER,m_serviceManager);
993         mmc.setAttribute(Constants.HELLO_NAME,"localhost");
994         MockMailetConfig mci = new MockMailetConfig("Test",mmc,getStandardParameters());
995         mci.setProperty("bind", "127.0.0.1");
996         mci.setProperty("gateway","127.0.0.1");
997         mci.setProperty("gatewayPort",""+m_smtpListenerPort);
998         rd.init(mci);
999         String sources = "Content-Type: text/plain;\r\nSubject: test\r\n\r\nBody";
1000         String sender = "test@localhost";
1001         String recipient = "test@localhost";
1002         MimeMessage mm = new MimeMessage(Session.getDefaultInstance(new Properties()),new ByteArrayInputStream(sources.getBytes()));
1003         MailImpl mail = new MailImpl("name",new MailAddress(sender),Arrays.asList(new MailAddress[] {new MailAddress(recipient)}),mm);
1004         
1005         rd.service(mail);
1006         
1007         while (outgoingSpool.size() > 0) {
1008             Thread.sleep(1000);
1009         }
1010 
1011         verifyLastMail(sender, recipient, null);
1012         
1013         assertEquals(((String) mm.getContent()).trim(),((String) ((MimeMessage) m_mailServer.getLastMail()[2]).getContent()).trim());
1014         
1015         mail.dispose();
1016     }
1017 
1018     
1019     /***
1020      * This is useful code to run tests on javamail bugs 
1021      * http://issues.apache.org/jira/browse/JAMES-52
1022      * 
1023      * This 
1024      * @throws Exception
1025      */
1026     public void test8bitmimeFromStream() throws Exception {
1027         finishSetUp(m_testConfiguration);
1028         outgoingSpool = new InMemorySpoolRepository();
1029         ((MockStore) m_serviceManager.lookup(Store.ROLE)).add("outgoing", outgoingSpool);
1030         
1031         RemoteDelivery rd = new RemoteDelivery();
1032         
1033         MockMailContext mmc = new MockMailContext();
1034         mmc.setAttribute(Constants.AVALON_COMPONENT_MANAGER,m_serviceManager);
1035         mmc.setAttribute(Constants.HELLO_NAME,"localhost");
1036         MockMailetConfig mci = new MockMailetConfig("Test",mmc,getStandardParameters());
1037         mci.setProperty("gateway","127.0.0.1");
1038         mci.setProperty("gatewayPort",""+m_smtpListenerPort);
1039         rd.init(mci);
1040         
1041         String sources = "Content-Type: text/plain;\r\nContent-Transfer-Encoding: quoted-printable\r\nSubject: test\r\n\r\nBody=80\r\n";
1042         //String sources = "Content-Type: text/plain; charset=iso-8859-15\r\nContent-Transfer-Encoding: quoted-printable\r\nSubject: test\r\n\r\nBody=80\r\n";
1043         //String sources = "Content-Type: text/plain; charset=iso-8859-15\r\nContent-Transfer-Encoding: 8bit\r\nSubject: test\r\n\r\nBody\u20AC\r\n";
1044         String sender = "test@localhost";
1045         String recipient = "test@localhost";
1046         MimeMessage mm = new MimeMessage(Session.getDefaultInstance(new Properties()),new ByteArrayInputStream(sources.getBytes()));
1047         MailImpl mail = new MailImpl("name",new MailAddress(sender),Arrays.asList(new MailAddress[] {new MailAddress(recipient)}),mm);
1048         
1049         rd.service(mail);
1050         
1051         while (outgoingSpool.size() > 0) {
1052             Thread.sleep(1000);
1053         }
1054 
1055         // verifyLastMail(sender, recipient, mm);
1056         verifyLastMail(sender, recipient, null);
1057         
1058         // THIS WOULD FAIL BECAUSE OF THE JAVAMAIL BUG
1059         // assertEquals(mm.getContent(),((MimeMessage) m_mailServer.getLastMail()[2]).getContent());
1060         
1061         mail.dispose();
1062     }
1063     
1064     
1065 }