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.io.IOException;
26 import java.net.UnknownHostException;
27 import java.util.ArrayList;
28 import java.util.Collection;
29 import java.util.HashSet;
30 import java.util.Iterator;
31
32 import javax.mail.MessagingException;
33 import javax.mail.internet.MimeBodyPart;
34 import javax.mail.internet.MimeMessage;
35 import javax.mail.internet.MimeMultipart;
36 import javax.mail.internet.MimePart;
37
38 import org.apache.avalon.framework.configuration.Configuration;
39 import org.apache.avalon.framework.configuration.ConfigurationException;
40
41 import org.apache.avalon.framework.service.ServiceException;
42 import org.apache.avalon.framework.service.ServiceManager;
43 import org.apache.avalon.framework.service.Serviceable;
44 import org.apache.james.api.dnsservice.DNSService;
45 import org.apache.james.dsn.DSNStatus;
46 import org.apache.james.smtpserver.MessageHandler;
47 import org.apache.james.smtpserver.SMTPSession;
48 import org.apache.james.smtpserver.urirbl.URIScanner;
49
50
51
52
53 public class URIRBLHandler extends AbstractJunkHandler implements MessageHandler,
54 Serviceable {
55
56 private DNSService dnsServer;
57
58 private Collection uriRbl;
59
60 private boolean getDetail = false;
61
62 private boolean checkAuthNetworks = false;
63
64 private final static String LISTED_DOMAIN ="LISTED_DOMAIN";
65
66 private final static String URBLSERVER = "URBL_SERVER";
67
68
69
70
71 public void service(ServiceManager serviceMan) throws ServiceException {
72 setDnsServer((DNSService) serviceMan.lookup(DNSService.ROLE));
73 }
74
75
76
77
78 public void configure(Configuration arg0) throws ConfigurationException {
79 boolean invalidConfig = false;
80
81 Configuration serverConfiguration = arg0.getChild("uriRblServers", false);
82 if ( serverConfiguration != null ) {
83 ArrayList serverCollection = new ArrayList();
84 Configuration[] children = serverConfiguration.getChildren("server");
85 if ( children != null ) {
86 for ( int i = 0 ; i < children.length ; i++ ) {
87 String rblServerName = children[i].getValue();
88 serverCollection.add(rblServerName);
89 if (getLogger().isInfoEnabled()) {
90 getLogger().info("Adding uriRBL server: " + rblServerName);
91 }
92 }
93 if (serverCollection != null && serverCollection.size() > 0) {
94 setUriRblServer(serverCollection);
95 } else {
96 invalidConfig = true;
97 }
98 }
99 } else {
100 invalidConfig = true;
101 }
102
103 if (invalidConfig == true) {
104 throw new ConfigurationException("Please provide at least one server");
105 }
106
107 Configuration configuration = arg0.getChild("getDetail",false);
108 if(configuration != null) {
109 getDetail = configuration.getValueAsBoolean();
110 }
111
112 Configuration configRelay = arg0.getChild("checkAuthNetworks", false);
113 if (configRelay != null) {
114 setCheckAuthNetworks(configRelay.getValueAsBoolean(false));
115 }
116
117 super.configure(arg0);
118
119 }
120
121
122
123
124
125
126 public void setUriRblServer(Collection uriRbl) {
127 this.uriRbl = uriRbl;
128 }
129
130
131
132
133
134
135
136 public void setCheckAuthNetworks(boolean checkAuthNetworks) {
137 this.checkAuthNetworks = checkAuthNetworks;
138 }
139
140
141
142
143
144
145
146 public void setDnsServer(DNSService dnsServer) {
147 this.dnsServer = dnsServer;
148 }
149
150
151
152
153
154
155 public void setGetDetail(boolean getDetail) {
156 this.getDetail = getDetail;
157 }
158
159
160
161
162 public void onMessage(SMTPSession session) {
163 doProcessing(session);
164 }
165
166
167
168
169
170
171
172
173 private HashSet scanMailForDomains(MimePart part) throws MessagingException, IOException {
174 HashSet domains = new HashSet();
175 getLogger().debug("mime type is: \"" + part.getContentType() + "\"");
176
177 if (part.isMimeType("text/plain") || part.isMimeType("text/html")) {
178 getLogger().debug("scanning: \"" + part.getContent().toString() + "\"");
179 HashSet newDom = URIScanner.scanContentForDomains(domains, part.getContent().toString());
180
181
182 if (newDom != null && newDom.size() > 0) {
183 domains.addAll(newDom);
184 }
185 } else if (part.isMimeType("multipart/*")) {
186 MimeMultipart multipart = (MimeMultipart) part.getContent();
187 int count = multipart.getCount();
188 getLogger().debug("multipart count is: " + count);
189
190 for (int index = 0; index < count; index++) {
191 getLogger().debug("recursing index: " + index);
192 MimeBodyPart mimeBodyPart = (MimeBodyPart) multipart.getBodyPart(index);
193 HashSet newDomains = scanMailForDomains(mimeBodyPart);
194
195
196 if(newDomains != null && newDomains.size() > 0) {
197 domains.addAll(newDomains);
198 }
199 }
200 }
201 return domains;
202 }
203
204
205
206
207 protected boolean check(SMTPSession session) {
208 MimeMessage message;
209
210
211 if (session.isRelayingAllowed() && !checkAuthNetworks) {
212 return false;
213 }
214
215 try {
216 message = session.getMail().getMessage();
217
218 HashSet domains = scanMailForDomains(message);
219
220 Iterator fDomains = domains.iterator();
221
222 while (fDomains.hasNext()) {
223 Iterator uRbl = uriRbl.iterator();
224 String target = fDomains.next().toString();
225
226 while (uRbl.hasNext()) {
227 try {
228 String uRblServer = uRbl.next().toString();
229 String address = target + "." + uRblServer;
230
231 if (getLogger().isDebugEnabled()) {
232 getLogger().debug("Lookup " + address);
233 }
234
235 dnsServer.getByName(address);
236
237
238 session.getState().put(URBLSERVER, uRblServer);
239 session.getState().put(LISTED_DOMAIN,target);
240
241 session.abortMessage();
242 return true;
243
244 } catch (UnknownHostException uhe) {
245
246 }
247 }
248 }
249 } catch (MessagingException e) {
250 getLogger().error(e.getMessage());
251 } catch (IOException e) {
252 getLogger().error(e.getMessage());
253 }
254 return false;
255 }
256
257
258
259
260 public JunkHandlerData getJunkHandlerData(SMTPSession session) {
261 JunkHandlerData data = new JunkHandlerData();
262
263 String uRblServer = (String) session.getState().get(URBLSERVER);
264 String target = (String) session.getState().get(LISTED_DOMAIN);
265 String detail = null;
266
267
268 if (getDetail) {
269 Collection txt = dnsServer.findTXTRecords(target+ "." + uRblServer);
270
271
272 if (!txt.isEmpty()) {
273
274 detail = txt.iterator().next().toString();
275
276 }
277 }
278
279 if (detail != null) {
280
281 data.setRejectResponseString("554 " + DSNStatus.getStatus(DSNStatus.PERMANENT, DSNStatus.SECURITY_OTHER)
282 + "Rejected: message contains domain " + target + " listed by " + uRblServer +" . Details: "
283 + detail);
284 } else {
285 data.setRejectResponseString("554 " + DSNStatus.getStatus(DSNStatus.PERMANENT, DSNStatus.SECURITY_OTHER)
286 + " Rejected: message contains domain " + target + " listed by " + uRblServer);
287 }
288
289 data.setJunkScoreLogString("Message sent by " + session.getRemoteIPAddress() + " restricted by " + uRblServer + " because " + target + " is listed. Add junkScore: " + getScore());
290 data.setRejectLogString("Rejected: message contains domain " + target + " listed by " + uRblServer);
291 data.setScoreName("UriRBLCheck");
292 return data;
293 }
294
295 }