1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.james.smtpserver;
22
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27
28 import org.apache.avalon.framework.container.ContainerUtil;
29 import org.apache.james.jspf.core.DNSRequest;
30 import org.apache.james.jspf.core.DNSService;
31 import org.apache.james.jspf.core.exceptions.TimeoutException;
32 import org.apache.james.smtpserver.core.filter.fastfail.SPFHandler;
33 import org.apache.james.smtpserver.junkscore.JunkScore;
34 import org.apache.james.smtpserver.junkscore.JunkScoreImpl;
35 import org.apache.james.test.mock.avalon.MockLogger;
36 import org.apache.mailet.base.test.FakeMail;
37 import org.apache.mailet.Mail;
38 import org.apache.mailet.MailAddress;
39
40 import junit.framework.TestCase;
41
42 public class SPFHandlerTest extends TestCase {
43
44 private DNSService mockedDnsService;
45
46 private SMTPSession mockedSMTPSession;;
47
48 private boolean relaying = false;
49
50 private String command = "MAIL";
51
52 protected void setUp() throws Exception {
53 super.setUp();
54 setupMockedDnsService();
55 setRelayingAllowed(false);
56 }
57
58
59
60
61
62
63
64 private void setRelayingAllowed(boolean relaying) {
65 this.relaying = relaying;
66 }
67
68
69
70
71
72 private void setupMockedDnsService() {
73 mockedDnsService = new DNSService() {
74
75 public List getLocalDomainNames() {
76 throw new UnsupportedOperationException(
77 "Unimplemented mock service");
78 }
79
80 public void setTimeOut(int arg0) {
81
82 }
83
84 public int getRecordLimit() {
85 return 0;
86 }
87
88 public void setRecordLimit(int arg0) {
89 throw new UnsupportedOperationException(
90 "Unimplemented mock service");
91 }
92
93 public List getRecords(DNSRequest req) throws TimeoutException {
94 switch (req.getRecordType()) {
95 case DNSRequest.TXT:
96 case DNSRequest.SPF:
97 List l = new ArrayList();
98 if (req.getHostname().equals("spf1.james.apache.org")) {
99
100 l.add("v=spf1 +all");
101 return l;
102 } else if (req.getHostname().equals("spf2.james.apache.org")) {
103
104 l.add("v=spf1 -all");
105 return l;
106 } else if (req.getHostname().equals("spf3.james.apache.org")) {
107
108 l.add("v=spf1 ~all");
109 return l;
110 } else if (req.getHostname().equals("spf4.james.apache.org")) {
111
112 l.add("v=spf1 badcontent!");
113 return l;
114 } else if (req.getHostname().equals("spf5.james.apache.org")) {
115
116 throw new TimeoutException("TIMEOUT");
117 } else {
118 return null;
119 }
120 default:
121 throw new UnsupportedOperationException(
122 "Unimplemented mock service");
123 }
124 }
125
126 };
127 }
128
129 private void setCommand(String command) {
130 this.command = command;
131 }
132
133
134
135
136 private void setupMockedSMTPSession(final String ip, final String helo,
137 final MailAddress sender, final MailAddress recipient) {
138 mockedSMTPSession = new AbstractSMTPSession() {
139 HashMap state = new HashMap();
140
141 HashMap connectionState = new HashMap();
142
143 Mail mail = new FakeMail();
144
145 boolean stopHandler = false;
146
147 public void writeResponse(String respString) {
148
149 }
150
151 public String getCommandName() {
152 return command;
153 }
154
155 public Mail getMail() {
156 return mail;
157 }
158
159 public String getRemoteIPAddress() {
160 return ip;
161 }
162
163 public Map getState() {
164 state.put(SMTPSession.CURRENT_HELO_NAME, helo);
165 state.put(SMTPSession.SENDER, sender);
166 state.put(SMTPSession.CURRENT_RECIPIENT, recipient);
167 return state;
168 }
169
170 public boolean isRelayingAllowed() {
171 return relaying;
172 }
173
174 public boolean isAuthRequired() {
175 return false;
176 }
177
178 public int getRcptCount() {
179 return 0;
180 }
181
182 public void setStopHandlerProcessing(boolean b) {
183 stopHandler = b;
184 }
185
186 public boolean getStopHandlerProcessing() {
187 return stopHandler;
188 }
189
190 public Map getConnectionState() {
191 return connectionState;
192 }
193
194 public void resetConnectionState() {
195 connectionState.clear();
196 }
197
198 };
199 }
200
201 private void runHandlers(SPFHandler spf, SMTPSession mockedSMTPSession) {
202
203 setCommand("MAIL");
204 spf.onCommand(mockedSMTPSession);
205
206 setCommand("RCPT");
207 spf.onCommand(mockedSMTPSession);
208
209 spf.onMessage(mockedSMTPSession);
210 }
211
212 public void testSPFpass() throws Exception {
213 setupMockedSMTPSession("192.168.100.1", "spf1.james.apache.org",
214 new MailAddress("test@spf1.james.apache.org"), new MailAddress(
215 "test@localhost"));
216 SPFHandler spf = new SPFHandler();
217
218
219 ContainerUtil.enableLogging(spf, new MockLogger());
220
221 spf.setDNSService(mockedDnsService);
222
223 spf.initialize();
224
225 runHandlers(spf, mockedSMTPSession);
226
227 assertNull("Not reject", mockedSMTPSession.getState().get(
228 SPFHandler.SPF_BLOCKLISTED));
229 assertNull("Not blocked so no details", mockedSMTPSession.getState()
230 .get(SPFHandler.SPF_DETAIL));
231 assertNull("No tempError", mockedSMTPSession.getState().get(
232 SPFHandler.SPF_TEMPBLOCKLISTED));
233 assertNotNull("Header should present", mockedSMTPSession.getState()
234 .get(SPFHandler.SPF_HEADER));
235 assertEquals("header", mockedSMTPSession.getState().get(
236 SPFHandler.SPF_HEADER), mockedSMTPSession.getMail()
237 .getAttribute(SPFHandler.SPF_HEADER_MAIL_ATTRIBUTE_NAME));
238 assertFalse(mockedSMTPSession.getStopHandlerProcessing());
239 }
240
241 public void testSPFfail() throws Exception {
242 setupMockedSMTPSession("192.168.100.1", "spf2.james.apache.org",
243 new MailAddress("test@spf2.james.apache.org"), new MailAddress(
244 "test@localhost"));
245 SPFHandler spf = new SPFHandler();
246
247 ContainerUtil.enableLogging(spf, new MockLogger());
248
249 spf.setDNSService(mockedDnsService);
250
251 spf.initialize();
252
253 runHandlers(spf, mockedSMTPSession);
254
255 assertNotNull("reject", mockedSMTPSession.getState().get(
256 SPFHandler.SPF_BLOCKLISTED));
257 assertNotNull("blocked", mockedSMTPSession.getState().get(
258 SPFHandler.SPF_DETAIL));
259 assertNull("No tempError", mockedSMTPSession.getState().get(
260 SPFHandler.SPF_TEMPBLOCKLISTED));
261 assertNotNull("Header should present", mockedSMTPSession.getState()
262 .get(SPFHandler.SPF_HEADER));
263 assertTrue(mockedSMTPSession.getStopHandlerProcessing());
264 }
265
266 public void testSPFsoftFail() throws Exception {
267 setupMockedSMTPSession("192.168.100.1", "spf3.james.apache.org",
268 new MailAddress("test@spf3.james.apache.org"), new MailAddress(
269 "test@localhost"));
270 SPFHandler spf = new SPFHandler();
271
272 ContainerUtil.enableLogging(spf, new MockLogger());
273
274 spf.setDNSService(mockedDnsService);
275
276 spf.initialize();
277
278 runHandlers(spf, mockedSMTPSession);
279
280 assertNull("not reject", mockedSMTPSession.getState().get(
281 SPFHandler.SPF_BLOCKLISTED));
282 assertNull("no details ", mockedSMTPSession.getState().get(
283 SPFHandler.SPF_DETAIL));
284 assertNull("No tempError", mockedSMTPSession.getState().get(
285 SPFHandler.SPF_TEMPBLOCKLISTED));
286 assertNotNull("Header should present", mockedSMTPSession.getState()
287 .get(SPFHandler.SPF_HEADER));
288 assertEquals("header", mockedSMTPSession.getState().get(
289 SPFHandler.SPF_HEADER), mockedSMTPSession.getMail()
290 .getAttribute(SPFHandler.SPF_HEADER_MAIL_ATTRIBUTE_NAME));
291 assertFalse(mockedSMTPSession.getStopHandlerProcessing());
292 }
293
294 public void testSPFsoftFailRejectEnabled() throws Exception {
295 setupMockedSMTPSession("192.168.100.1", "spf3.james.apache.org",
296 new MailAddress("test@spf3.james.apache.org"), new MailAddress(
297 "test@localhost"));
298 SPFHandler spf = new SPFHandler();
299
300 ContainerUtil.enableLogging(spf, new MockLogger());
301
302 spf.setDNSService(mockedDnsService);
303
304 spf.initialize();
305
306 spf.setBlockSoftFail(true);
307
308 setCommand("MAIL");
309 spf.onCommand(mockedSMTPSession);
310
311 setCommand("RCPT");
312 spf.onCommand(mockedSMTPSession);
313
314 assertNotNull("reject", mockedSMTPSession.getState().get(
315 SPFHandler.SPF_BLOCKLISTED));
316 assertNotNull("details ", mockedSMTPSession.getState().get(
317 SPFHandler.SPF_DETAIL));
318 assertNull("No tempError", mockedSMTPSession.getState().get(
319 SPFHandler.SPF_TEMPBLOCKLISTED));
320 assertNotNull("Header should present", mockedSMTPSession.getState()
321 .get(SPFHandler.SPF_HEADER));
322 assertTrue(mockedSMTPSession.getStopHandlerProcessing());
323 }
324
325 public void testSPFpermError() throws Exception {
326 setupMockedSMTPSession("192.168.100.1", "spf4.james.apache.org",
327 new MailAddress("test@spf4.james.apache.org"), new MailAddress(
328 "test@localhost"));
329 SPFHandler spf = new SPFHandler();
330
331 ContainerUtil.enableLogging(spf, new MockLogger());
332
333 spf.setDNSService(mockedDnsService);
334
335 spf.initialize();
336
337 spf.setBlockSoftFail(true);
338
339 runHandlers(spf, mockedSMTPSession);
340
341 assertNotNull("reject", mockedSMTPSession.getState().get(
342 SPFHandler.SPF_BLOCKLISTED));
343 assertNotNull("details ", mockedSMTPSession.getState().get(
344 SPFHandler.SPF_DETAIL));
345 assertNull("No tempError", mockedSMTPSession.getState().get(
346 SPFHandler.SPF_TEMPBLOCKLISTED));
347 assertNotNull("Header should present", mockedSMTPSession.getState()
348 .get(SPFHandler.SPF_HEADER));
349 assertTrue(mockedSMTPSession.getStopHandlerProcessing());
350 }
351
352 public void testSPFtempError() throws Exception {
353 setupMockedSMTPSession("192.168.100.1", "spf5.james.apache.org",
354 new MailAddress("test@spf5.james.apache.org"), new MailAddress(
355 "test@localhost"));
356 SPFHandler spf = new SPFHandler();
357
358 ContainerUtil.enableLogging(spf, new MockLogger());
359
360 spf.setDNSService(mockedDnsService);
361
362 spf.initialize();
363
364 runHandlers(spf, mockedSMTPSession);
365
366 assertNull("no reject", mockedSMTPSession.getState().get(
367 SPFHandler.SPF_BLOCKLISTED));
368 assertNull("no details ", mockedSMTPSession.getState().get(
369 SPFHandler.SPF_DETAIL));
370 assertNotNull("tempError", mockedSMTPSession.getState().get(
371 SPFHandler.SPF_TEMPBLOCKLISTED));
372 assertNotNull("Header should present", mockedSMTPSession.getState()
373 .get(SPFHandler.SPF_HEADER));
374 assertTrue(mockedSMTPSession.getStopHandlerProcessing());
375 }
376
377 public void testSPFNoRecord() throws Exception {
378 setupMockedSMTPSession("192.168.100.1", "spf6.james.apache.org",
379 new MailAddress("test@spf6.james.apache.org"), new MailAddress(
380 "test@localhost"));
381 SPFHandler spf = new SPFHandler();
382
383 ContainerUtil.enableLogging(spf, new MockLogger());
384
385 spf.setDNSService(mockedDnsService);
386
387 spf.initialize();
388
389 runHandlers(spf, mockedSMTPSession);
390
391 assertNull("no reject", mockedSMTPSession.getState().get(
392 SPFHandler.SPF_BLOCKLISTED));
393 assertNull("no details ", mockedSMTPSession.getState().get(
394 SPFHandler.SPF_DETAIL));
395 assertNull("no tempError", mockedSMTPSession.getState().get(
396 SPFHandler.SPF_TEMPBLOCKLISTED));
397 assertNotNull("Header should present", mockedSMTPSession.getState()
398 .get(SPFHandler.SPF_HEADER));
399 assertEquals("header", mockedSMTPSession.getState().get(
400 SPFHandler.SPF_HEADER), mockedSMTPSession.getMail()
401 .getAttribute(SPFHandler.SPF_HEADER_MAIL_ATTRIBUTE_NAME));
402 assertFalse(mockedSMTPSession.getStopHandlerProcessing());
403 }
404
405 public void testSPFpermErrorNotRejectPostmaster() throws Exception {
406 setupMockedSMTPSession("192.168.100.1", "spf4.james.apache.org",
407 new MailAddress("test@spf4.james.apache.org"), new MailAddress(
408 "postmaster@localhost"));
409 SPFHandler spf = new SPFHandler();
410
411 ContainerUtil.enableLogging(spf, new MockLogger());
412
413 spf.setDNSService(mockedDnsService);
414
415 spf.initialize();
416
417 spf.setBlockSoftFail(true);
418
419 runHandlers(spf, mockedSMTPSession);
420
421 assertNotNull("not removed this state", mockedSMTPSession.getState().get(
422 SPFHandler.SPF_BLOCKLISTED));
423 assertNotNull("not removed this state", mockedSMTPSession.getState().get(
424 SPFHandler.SPF_DETAIL));
425 assertNotNull("not removed this state", mockedSMTPSession.getState()
426 .get(SPFHandler.SPF_HEADER));
427 assertFalse("not rejected", mockedSMTPSession.getStopHandlerProcessing());
428 }
429
430 public void testSPFpermErrorNotRejectAbuse() throws Exception {
431 setupMockedSMTPSession("192.168.100.1", "spf4.james.apache.org",
432 new MailAddress("test@spf4.james.apache.org"), new MailAddress("abuse@localhost"));
433 SPFHandler spf = new SPFHandler();
434
435 ContainerUtil.enableLogging(spf, new MockLogger());
436
437 spf.initialize();
438
439 spf.setDNSService(mockedDnsService);
440 spf.setBlockSoftFail(true);
441
442 runHandlers(spf, mockedSMTPSession);
443
444 assertFalse("not rejected",mockedSMTPSession.getStopHandlerProcessing());
445 }
446
447 public void testSPFpermErrorRejectDisabled() throws Exception {
448 setupMockedSMTPSession("192.168.100.1", "spf4.james.apache.org",
449 new MailAddress("test@spf4.james.apache.org"), new MailAddress(
450 "test@localhost"));
451 SPFHandler spf = new SPFHandler();
452
453 ContainerUtil.enableLogging(spf, new MockLogger());
454
455 spf.setDNSService(mockedDnsService);
456
457 spf.initialize();
458
459 spf.setBlockPermError(false);
460
461 runHandlers(spf, mockedSMTPSession);
462
463 assertNull("not reject", mockedSMTPSession.getState().get(
464 SPFHandler.SPF_BLOCKLISTED));
465 assertNull("details ", mockedSMTPSession.getState().get(
466 SPFHandler.SPF_DETAIL));
467 assertNull("No tempError", mockedSMTPSession.getState().get(
468 SPFHandler.SPF_TEMPBLOCKLISTED));
469 assertNotNull("Header should present", mockedSMTPSession.getState()
470 .get(SPFHandler.SPF_HEADER));
471 assertFalse(mockedSMTPSession.getStopHandlerProcessing());
472 }
473
474 public void testSPFfailAddJunkScore() throws Exception {
475 setupMockedSMTPSession("192.168.100.1", "spf2.james.apache.org",
476 new MailAddress("test@spf2.james.apache.org"), new MailAddress(
477 "test@localhost"));
478 mockedSMTPSession.getState().put(JunkScore.JUNK_SCORE, new JunkScoreImpl());
479
480 SPFHandler spf = new SPFHandler();
481
482 ContainerUtil.enableLogging(spf, new MockLogger());
483 spf.setAction("junkScore");
484 spf.setScore(20);
485 spf.setDNSService(mockedDnsService);
486
487 spf.initialize();
488
489 runHandlers(spf, mockedSMTPSession);
490
491 assertNotNull("reject", mockedSMTPSession.getState().get(
492 SPFHandler.SPF_BLOCKLISTED));
493 assertNotNull("blocked", mockedSMTPSession.getState().get(
494 SPFHandler.SPF_DETAIL));
495 assertNull("No tempError", mockedSMTPSession.getState().get(
496 SPFHandler.SPF_TEMPBLOCKLISTED));
497 assertNotNull("Header should present", mockedSMTPSession.getState()
498 .get(SPFHandler.SPF_HEADER));
499 assertFalse("Not stopped", mockedSMTPSession.getStopHandlerProcessing());
500 assertEquals("Score added",((JunkScore) mockedSMTPSession.getState().get(JunkScore.JUNK_SCORE)).getStoredScore("SPFCheck"), 20.0, 0d);
501 }
502 }