1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.apache.james.smtpserver.core.filter.fastfail;
24
25 import java.util.Iterator;
26 import java.util.Map;
27
28 import javax.mail.MessagingException;
29 import javax.mail.internet.MimeMessage;
30
31 import org.apache.avalon.framework.configuration.Configurable;
32 import org.apache.avalon.framework.configuration.Configuration;
33 import org.apache.avalon.framework.configuration.ConfigurationException;
34 import org.apache.avalon.framework.logger.AbstractLogEnabled;
35 import org.apache.james.dsn.DSNStatus;
36 import org.apache.james.smtpserver.ConnectHandler;
37 import org.apache.james.smtpserver.MessageHandler;
38 import org.apache.james.smtpserver.SMTPSession;
39 import org.apache.james.smtpserver.junkscore.ComposedJunkScore;
40 import org.apache.james.smtpserver.junkscore.JunkScore;
41 import org.apache.james.smtpserver.junkscore.JunkScoreImpl;
42
43
44
45
46
47
48
49
50 public class JunkScoreHandler extends AbstractLogEnabled implements ConnectHandler, MessageHandler,Configurable {
51
52 private double maxScore = 0;
53 private String action;
54 private static final String REJECT_ACTION = "reject";
55 private static final String COMPOSE_ACTION = "compose";
56 private static final String HEADER_ACTION = "header";
57
58
59
60
61 public void configure(Configuration arg0) throws ConfigurationException {
62 Configuration maxScoreConfig = arg0.getChild("maxScore");
63
64 if (maxScoreConfig != null) {
65 setMaxScore(maxScoreConfig.getValueAsDouble(0));
66 }
67
68 Configuration actionConfig = arg0.getChild("action");
69 if (actionConfig != null) {
70 setAction(actionConfig.getValue().toLowerCase());
71 } else {
72 throw new ConfigurationException("Please configure the action");
73 }
74 }
75
76
77
78
79
80
81 public void setMaxScore(double maxScore) {
82 this.maxScore = maxScore;
83 }
84
85
86
87
88
89
90
91 public void setAction(String action) throws ConfigurationException {
92 if (!action.equals(REJECT_ACTION) && !action.equals(COMPOSE_ACTION) && !action.equals(HEADER_ACTION))
93 throw new ConfigurationException("Illegal action: " + action);
94
95 this.action = action;
96 }
97
98
99
100
101 public void onMessage(SMTPSession session) {
102 checkScore(session);
103 }
104
105
106
107
108
109
110 private void checkScore(SMTPSession session) {
111 JunkScore score1 = (JunkScore) session.getConnectionState().get(JunkScore.JUNK_SCORE_SESSION);
112 JunkScore score2 = (JunkScore) session.getState().get(JunkScore.JUNK_SCORE);
113 JunkScore composed = new ComposedJunkScore(score1,score2);
114
115 if (action.equals(COMPOSE_ACTION)) {
116
117 session.getMail().setAttribute(JunkScore.JUNK_SCORE_SESSION_ATTR, String.valueOf(score1.getCompleteStoredScores()));
118 session.getMail().setAttribute(JunkScore.JUNK_SCORE_ATTR, String.valueOf(score2.getCompleteStoredScores()));
119 session.getMail().setAttribute(JunkScore.JUNK_SCORE_COMPOSED_ATTR, String.valueOf(composed.getCompleteStoredScores()));
120 } else if (action.equals(REJECT_ACTION)) {
121 if (maxScore < composed.getCompleteStoredScores()) {
122
123
124 String responseString = "554 "
125 + DSNStatus.getStatus(DSNStatus.PERMANENT,
126 DSNStatus.SECURITY_OTHER)
127 + " This message reach the spam hits treshold. Please contact the Postmaster if the email is not SPAM. Message rejected";
128 StringBuffer buffer = new StringBuffer(256).append(
129 "Rejected message from ").append(
130 session.getState().get(SMTPSession.SENDER)
131 .toString()).append(" from host ")
132 .append(session.getRemoteHost()).append(" (")
133 .append(session.getRemoteIPAddress()).append(
134 ") " + responseString).append(
135 ". Required rejection hits: "
136 + maxScore
137 + " hits: " + composed.getCompleteStoredScores());
138 getLogger().info(buffer.toString());
139
140 session.writeResponse(responseString);
141 session.setStopHandlerProcessing(true);
142 session.abortMessage();
143 }
144 } else if (action.equals(HEADER_ACTION)) {
145 try {
146 MimeMessage message = session.getMail().getMessage();
147 Map scores = composed.getStoredScores();
148 Iterator itScores = scores.keySet().iterator();
149
150 StringBuffer header = new StringBuffer();
151 while (itScores.hasNext()) {
152 String key = itScores.next().toString();
153 header.append(key);
154 header.append("=");
155 header.append(scores.get(key));
156 header.append("; ");
157 }
158
159 message.setHeader("X-JUNKSCORE", header.toString());
160 message.setHeader("X-JUNKSCORE-COMPOSED", String.valueOf(composed.getCompleteStoredScores()));
161
162 } catch (MessagingException e) {
163 getLogger().info("Unable to add Junkscore to header: " + e.getMessage());
164 }
165 }
166 }
167
168
169
170
171 public void onConnect(SMTPSession session) {
172 session.getState().put(JunkScore.JUNK_SCORE, new JunkScoreImpl());
173 session.getConnectionState().put(JunkScore.JUNK_SCORE_SESSION, new JunkScoreImpl());
174 }
175 }