1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.apache.james.transport.mailets;
23
24 import org.apache.avalon.framework.service.ServiceManager;
25 import org.apache.avalon.framework.configuration.Configuration;
26 import org.apache.james.Constants;
27 import org.apache.james.api.user.UsersRepository;
28 import org.apache.james.api.user.UsersStore;
29 import org.apache.mailet.base.RFC2822Headers;
30 import org.apache.james.util.XMLResources;
31 import org.apache.mailet.base.MailetUtil;
32 import org.apache.mailet.base.GenericMailet;
33 import org.apache.mailet.Mail;
34 import org.apache.mailet.MailAddress;
35 import org.apache.mailet.MailetException;
36
37 import javax.mail.MessagingException;
38 import javax.mail.internet.MimeMessage;
39 import javax.mail.internet.MimeMultipart;
40 import javax.mail.internet.ParseException;
41 import java.io.IOException;
42 import java.lang.reflect.Field;
43 import java.util.ArrayList;
44 import java.util.Collection;
45 import java.util.Iterator;
46 import java.util.Properties;
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76 public class CommandListservProcessor extends GenericMailet {
77
78
79
80
81
82
83
84
85 protected boolean membersOnly;
86
87
88
89
90
91
92
93
94 protected boolean attachmentsAllowed;
95
96
97
98
99
100
101
102
103
104 protected boolean replyToList;
105
106
107
108
109
110
111
112
113
114 protected String subjectPrefix;
115
116
117
118
119
120
121
122
123
124 protected boolean autoBracket;
125
126
127
128
129
130
131
132 protected UsersRepository usersRepository;
133
134
135
136
137
138
139
140 protected MailAddress listOwner;
141
142
143
144
145
146
147
148
149 protected String listName;
150
151
152
153
154 protected ICommandListservManager commandListservManager;
155
156
157
158
159 protected CommandListservFooter commandListservFooter;
160
161
162
163
164 protected XMLResources xmlResources;
165
166 protected boolean specificPostersOnly;
167 protected Collection allowedPosters;
168
169 protected boolean addFooter;
170
171
172
173
174 public void init() throws MessagingException {
175 try {
176 Configuration configuration = (Configuration) getField(getMailetConfig(), "configuration");
177
178 membersOnly = getBoolean("membersonly", false);
179 attachmentsAllowed = getBoolean("attachmentsallowed", true);
180 replyToList = getBoolean("replytolist", true);
181 subjectPrefix = getString("subjectprefix", null);
182 listName = getString("listName", null);
183 autoBracket = getBoolean("autobracket", true);
184 listOwner = new MailAddress(getString("listOwner", null));
185 specificPostersOnly = getBoolean("specifiedpostersonly", false);
186 addFooter = getBoolean("addfooter", true);
187
188 initializeResources();
189
190 initUsersRepository();
191 initAllowedPosters(configuration);
192 } catch (Exception e) {
193 throw new MessagingException(e.getMessage(), e);
194 }
195 }
196
197
198
199
200
201
202 public void service(Mail mail) throws MessagingException {
203 try {
204 Collection members = getMembers();
205 MailAddress listservAddr = (MailAddress) mail.getRecipients().iterator().next();
206
207
208 if (!checkAllowedPoster(mail, members)) {
209 return;
210 }
211
212
213 if (!checkAnnouncements(mail)) {
214 return;
215 }
216
217
218 if (!checkBeenThere(listservAddr, mail)) {
219 return;
220 }
221
222
223 if (addFooter) addFooter(mail);
224
225
226 MimeMessage message = prepareListMessage(mail, listservAddr);
227
228
229 setSubject(message);
230
231
232
233 getMailetContext().sendMail(listOwner, members, message);
234 } catch (IOException ioe) {
235 throw new MailetException("Error creating listserv message", ioe);
236 } finally {
237
238 mail.setState(Mail.GHOST);
239 }
240 }
241
242
243
244
245
246
247 protected void addFooter(Mail mail) throws MessagingException {
248 getCommandListservFooter().service(mail);
249 }
250
251 protected void setSubject(MimeMessage message) throws MessagingException {
252 String prefix = subjectPrefix;
253 if (prefix != null) {
254 if (autoBracket) {
255 StringBuffer prefixBuffer =
256 new StringBuffer(64)
257 .append("[")
258 .append(prefix)
259 .append("]");
260 prefix = prefixBuffer.toString();
261 }
262 String subj = message.getSubject();
263 if (subj == null) {
264 subj = "";
265 }
266 subj = MailetUtil.normalizeSubject(subj, prefix);
267 AbstractRedirect.changeSubject(message, subj);
268 }
269 }
270
271
272
273
274
275
276
277
278 protected MimeMessage prepareListMessage(Mail mail, MailAddress listservAddr) throws MessagingException {
279
280 MimeMessage message = new MimeMessage(mail.getMessage());
281
282
283 message.removeHeader(RFC2822Headers.RETURN_PATH);
284
285
286
287 message.setHeader("X-been-there", listservAddr.toString());
288
289
290 if (replyToList) {
291 message.setHeader(RFC2822Headers.REPLY_TO, listservAddr.toString());
292 }
293
294 return message;
295 }
296
297
298
299
300
301
302
303
304
305
306
307
308 protected boolean checkBeenThere(MailAddress listservAddr, Mail mail) throws MessagingException {
309 if (listservAddr.equals(mail.getMessage().getHeader("X-been-there"))) {
310 return false;
311 }
312 return true;
313 }
314
315
316
317
318
319
320
321
322 protected boolean checkAnnouncements(Mail mail) throws IOException, MessagingException {
323 if (!attachmentsAllowed && mail.getMessage().getContent() instanceof MimeMultipart) {
324 Properties standardProperties = getCommandListservManager().getStandardProperties();
325
326 getCommandListservManager().onError(mail,
327 xmlResources.getString("invalid.mail.subject", standardProperties),
328 xmlResources.getString("error.attachments", standardProperties));
329 return false;
330 }
331 return true;
332 }
333
334
335
336
337
338
339
340
341
342 protected boolean checkMembers(Collection members, Mail mail) throws MessagingException {
343 if (membersOnly && !members.contains(mail.getSender())) {
344 Properties standardProperties = getCommandListservManager().getStandardProperties();
345 getCommandListservManager().onError(mail,
346 xmlResources.getString("invalid.mail.subject", standardProperties),
347 xmlResources.getString("error.membersonly", standardProperties));
348
349 return false;
350 }
351 return true;
352 }
353
354 public Collection getMembers() throws ParseException {
355 Collection reply = new ArrayList();
356 for (Iterator it = usersRepository.list(); it.hasNext();) {
357 String member = it.next().toString();
358 try {
359 reply.add(new MailAddress(member));
360 } catch (Exception e) {
361
362
363 StringBuffer logBuffer =
364 new StringBuffer(1024)
365 .append("Invalid subscriber address: ")
366 .append(member)
367 .append(" caused: ")
368 .append(e.getMessage());
369 log(logBuffer.toString());
370 }
371 }
372 return reply;
373 }
374
375
376
377
378
379
380
381 protected boolean getBoolean(String attrName, boolean defValue) {
382 boolean value = defValue;
383 try {
384 value = new Boolean(getInitParameter(attrName)).booleanValue();
385 } catch (Exception e) {
386
387 }
388 return value;
389 }
390
391
392
393
394
395
396
397 protected String getString(String attrName, String defValue) {
398 String value = defValue;
399 try {
400 value = getInitParameter(attrName);
401 } catch (Exception e) {
402
403 }
404 return value;
405 }
406
407
408
409
410
411 protected void initializeResources() throws Exception {
412 xmlResources = getCommandListservManager().initXMLResources(new String[]{"List Manager"})[0];
413 }
414
415
416
417
418 protected void initUsersRepository() throws Exception {
419 ServiceManager compMgr = (ServiceManager) getMailetContext().getAttribute(Constants.AVALON_COMPONENT_MANAGER);
420 UsersStore usersStore = (UsersStore) compMgr.lookup(UsersStore.ROLE);
421 String repName = getInitParameter("repositoryName");
422
423 usersRepository = usersStore.getRepository(repName);
424 if (usersRepository == null) throw new Exception("Invalid user repository: " + repName);
425 }
426
427
428
429
430
431 protected ICommandListservManager getCommandListservManager() {
432 if (commandListservManager == null) {
433 commandListservManager = (ICommandListservManager) getMailetContext().getAttribute(ICommandListservManager.ID + listName);
434 if (commandListservManager == null) {
435 throw new IllegalStateException("Unable to find command list manager named: " + listName);
436 }
437 }
438
439 return commandListservManager;
440 }
441
442
443
444
445
446 protected CommandListservFooter getCommandListservFooter() throws MessagingException {
447 if (commandListservFooter == null) {
448 commandListservFooter = new CommandListservFooter(getCommandListservManager());
449 commandListservFooter.init(getMailetConfig());
450 }
451 return commandListservFooter;
452 }
453
454
455
456
457
458 protected static Object getField(Object instance, String name) throws IllegalAccessException {
459 Class clazz = instance.getClass();
460 Field[] fields;
461 while (clazz != null) {
462 fields = clazz.getDeclaredFields();
463 for (int index = 0; index < fields.length; index++) {
464 Field field = fields[index];
465 if (field.getName().equals(name)) {
466 field.setAccessible(true);
467 return field.get(instance);
468 }
469 }
470 clazz = clazz.getSuperclass();
471 }
472
473 return null;
474 }
475
476 protected void initAllowedPosters(Configuration configuration) throws Exception {
477 final Configuration allowedPostersElement = configuration.getChild("allowedposters");
478 allowedPosters = new ArrayList();
479 if (allowedPostersElement != null) {
480 final Configuration[] addresses = allowedPostersElement.getChildren("address");
481 for (int index = 0; index < addresses.length; index++) {
482 Configuration address = addresses[index];
483 String emailAddress = address.getValue();
484 allowedPosters.add(new MailAddress(emailAddress));
485 }
486 }
487 }
488
489
490
491
492
493
494
495
496 protected boolean checkAllowedPoster(Mail mail, Collection members) throws MessagingException {
497
498
499
500
501 if ((!specificPostersOnly && (!membersOnly || members.contains(mail.getSender()))) || allowedPosters.contains(mail.getSender())) {
502 return true;
503 } else {
504 Properties standardProperties = getCommandListservManager().getStandardProperties();
505 getCommandListservManager().onError(mail,
506 xmlResources.getString("invalid.mail.subject", standardProperties),
507 xmlResources.getString("error.membersonly", standardProperties));
508 return false;
509 }
510 }
511 }