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.core.filter.fastfail;
22
23 import java.util.Iterator;
24
25 import javax.mail.MessagingException;
26 import javax.mail.internet.MimeMessage;
27
28 import org.apache.avalon.framework.configuration.Configurable;
29 import org.apache.avalon.framework.configuration.Configuration;
30 import org.apache.avalon.framework.configuration.ConfigurationException;
31 import org.apache.avalon.framework.logger.AbstractLogEnabled;
32 import org.apache.james.dsn.DSNStatus;
33 import org.apache.james.smtpserver.MessageHandler;
34 import org.apache.james.smtpserver.SMTPSession;
35 import org.apache.james.util.scanner.SpamAssassinInvoker;
36 import org.apache.mailet.Mail;
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 public class SpamAssassinHandler extends AbstractLogEnabled implements
55 MessageHandler, Configurable {
56
57
58
59
60 private int spamdPort = 783;
61
62
63
64
65 private String spamdHost = "localhost";
66
67
68
69
70 private double spamdRejectionHits = 0.0;
71
72 private boolean checkAuthNetworks = false;
73
74
75
76
77 public void configure(Configuration arg0) throws ConfigurationException {
78 Configuration spamdHostConf = arg0.getChild("spamdHost", false);
79 if (spamdHostConf != null) {
80 setSpamdHost(spamdHostConf.getValue("localhost"));
81 }
82
83 Configuration spamdPortConf = arg0.getChild("spamdPort", false);
84 if (spamdPortConf != null) {
85 setSpamdPort(spamdPortConf.getValueAsInteger(783));
86 }
87
88 Configuration spamdRejectionHitsConf = arg0.getChild(
89 "spamdRejectionHits", false);
90 if (spamdRejectionHitsConf != null) {
91 setSpamdRejectionHits(spamdRejectionHitsConf.getValueAsDouble(0.0));
92 }
93
94 Configuration configRelay = arg0.getChild("checkAuthNetworks", false);
95 if (configRelay != null) {
96 setCheckAuthNetworks(configRelay.getValueAsBoolean(false));
97 }
98
99 }
100
101
102
103
104
105
106
107 public void setCheckAuthNetworks(boolean checkAuthNetworks) {
108 this.checkAuthNetworks = checkAuthNetworks;
109 }
110
111
112
113
114
115
116
117 public void setSpamdHost(String spamdHost) {
118 this.spamdHost = spamdHost;
119 }
120
121
122
123
124
125
126
127 public void setSpamdPort(int spamdPort) {
128 this.spamdPort = spamdPort;
129 }
130
131
132
133
134
135
136
137 public void setSpamdRejectionHits(double spamdRejectionHits) {
138 this.spamdRejectionHits = spamdRejectionHits;
139
140 }
141
142
143
144
145 public void onMessage(SMTPSession session) {
146
147
148 if (session.isRelayingAllowed() && !checkAuthNetworks) {
149 return;
150 }
151
152 try {
153 Mail mail = session.getMail();
154 MimeMessage message = mail.getMessage();
155 SpamAssassinInvoker sa = new SpamAssassinInvoker(spamdHost,
156 spamdPort);
157 sa.scanMail(message);
158
159 Iterator headers = sa.getHeadersAsAttribute().keySet().iterator();
160
161
162 while (headers.hasNext()) {
163 String key = headers.next().toString();
164
165 mail.setAttribute(key, (String) sa.getHeadersAsAttribute().get(
166 key));
167 }
168
169
170 if (spamdRejectionHits > 0) {
171 try {
172 double hits = Double.parseDouble(sa.getHits());
173
174
175
176 if (spamdRejectionHits <= hits) {
177 String responseString = "554 "
178 + DSNStatus.getStatus(DSNStatus.PERMANENT,
179 DSNStatus.SECURITY_OTHER)
180 + " This message reach the spam hits treshold. Please contact the Postmaster if the email is not SPAM. Message rejected";
181 StringBuffer buffer = new StringBuffer(256).append(
182 "Rejected message from ").append(
183 session.getState().get(SMTPSession.SENDER)
184 .toString()).append(" from host ")
185 .append(session.getRemoteHost()).append(" (")
186 .append(session.getRemoteIPAddress()).append(
187 ") " + responseString).append(
188 ". Required rejection hits: "
189 + spamdRejectionHits
190 + " hits: " + hits);
191 getLogger().info(buffer.toString());
192 session.writeResponse(responseString);
193
194
195 session.abortMessage();
196 }
197 } catch (NumberFormatException e) {
198
199 }
200 }
201 } catch (MessagingException e) {
202 getLogger().error(e.getMessage());
203 }
204
205 }
206 }