1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.jsieve.mailet;
21
22 import java.io.InputStream;
23 import java.util.Collection;
24 import java.util.Enumeration;
25 import java.util.Iterator;
26 import java.util.Vector;
27
28 import javax.mail.Header;
29 import javax.mail.MessagingException;
30 import javax.mail.internet.InternetHeaders;
31 import javax.mail.internet.MimeMessage;
32
33 import org.apache.commons.logging.Log;
34 import org.apache.jsieve.ConfigurationManager;
35 import org.apache.jsieve.SieveConfigurationException;
36 import org.apache.jsieve.SieveFactory;
37 import org.apache.mailet.Mail;
38 import org.apache.mailet.MailAddress;
39 import org.apache.mailet.MailetConfig;
40 import org.apache.mailet.MailetException;
41 import org.apache.mailet.base.GenericMailet;
42 import org.apache.mailet.base.RFC2822Headers;
43
44
45
46
47
48
49
50
51
52
53
54
55
56 public class SieveMailboxMailet extends GenericMailet {
57
58
59
60
61 private String deliveryHeader;
62
63
64
65
66 private boolean resetReturnPath;
67
68 private Poster poster;
69
70 private ResourceLocator locator;
71
72
73 private boolean verbose = false;
74
75 private boolean consume = true;
76
77 private boolean quiet = true;
78
79 private SieveFactory factory;
80
81 private ActionDispatcher actionDispatcher;
82
83 private Log log;
84
85
86
87
88 public SieveMailboxMailet() {}
89
90
91
92
93
94 public SieveMailboxMailet(Poster poster, ResourceLocator locator) {
95 this();
96 this.poster = poster;
97 this.locator = locator;
98 }
99
100
101 public ResourceLocator getLocator() {
102 return locator;
103 }
104
105
106
107
108
109 public void setLocator(ResourceLocator locator) {
110 this.locator = locator;
111 }
112
113 public Poster getPoster() {
114 return poster;
115 }
116
117
118
119
120
121 public void setPoster(Poster poster) {
122 this.poster = poster;
123 }
124
125
126
127
128
129 public boolean isConsume() {
130 return consume;
131 }
132
133
134
135
136
137
138 public void setConsume(boolean consume) {
139 this.consume = consume;
140 }
141
142
143
144
145
146
147 public boolean isVerbose() {
148 return verbose;
149 }
150
151
152
153
154
155
156
157
158
159 public void setVerbose(boolean verbose) {
160 this.verbose = verbose;
161 }
162
163
164
165
166
167 public boolean isQuiet() {
168 return quiet;
169 }
170
171
172
173
174
175
176 public void setQuiet(boolean quiet) {
177 this.quiet = quiet;
178 }
179
180
181
182
183
184
185 public boolean isInfoLoggingOn() {
186 return verbose || !quiet;
187 }
188
189
190 public void init(MailetConfig config) throws MessagingException {
191
192 super.init(config);
193
194 try {
195 final ConfigurationManager configurationManager = new ConfigurationManager();
196 final int logLevel;
197 if (verbose) {
198 logLevel = CommonsLoggingAdapter.TRACE;
199 } else if (quiet) {
200 logLevel = CommonsLoggingAdapter.FATAL;
201 } else {
202 logLevel = CommonsLoggingAdapter.WARN;
203 }
204 log = new CommonsLoggingAdapter(this, logLevel);
205 configurationManager.setLog(log);
206 factory = configurationManager.build();
207 } catch (SieveConfigurationException e) {
208 throw new MessagingException("Failed to load standard Sieve configuration.", e);
209 }
210 }
211
212
213
214
215
216
217
218
219
220
221 public void service(Mail mail) throws MessagingException {
222 Collection recipients = mail.getRecipients();
223 Collection errors = new Vector();
224
225 MimeMessage message = null;
226 if (deliveryHeader != null || resetReturnPath) {
227 message = mail.getMessage();
228 }
229
230 if (resetReturnPath) {
231
232
233
234
235 message.setHeader(RFC2822Headers.RETURN_PATH,
236 (mail.getSender() == null ? "<>" : "<" + mail.getSender()
237 + ">"));
238 }
239
240 Enumeration headers;
241 InternetHeaders deliveredTo = new InternetHeaders();
242 if (deliveryHeader != null) {
243
244 headers = message
245 .getMatchingHeaders(new String[] { deliveryHeader });
246 while (headers.hasMoreElements()) {
247 Header header = (Header) headers.nextElement();
248 deliveredTo.addHeader(header.getName(), header.getValue());
249 }
250 }
251
252 for (Iterator i = recipients.iterator(); i.hasNext();) {
253 MailAddress recipient = (MailAddress) i.next();
254 try {
255 if (deliveryHeader != null) {
256
257 message.addHeader(deliveryHeader, recipient.toString());
258 }
259
260 storeMail(mail.getSender(), recipient, mail);
261
262 if (deliveryHeader != null) {
263 if (i.hasNext()) {
264
265 message.removeHeader(deliveryHeader);
266 headers = deliveredTo.getAllHeaders();
267
268 while (headers.hasMoreElements()) {
269 Header header = (Header) headers.nextElement();
270 message.addHeader(header.getName(), header
271 .getValue());
272 }
273 }
274 }
275 } catch (Exception ex) {
276 log("Error while storing mail.", ex);
277 errors.add(recipient);
278 }
279 }
280
281 if (!errors.isEmpty()) {
282
283
284
285
286
287
288
289 getMailetContext().sendMail(mail.getSender(), errors,
290 mail.getMessage(), Mail.ERROR);
291 }
292 if (consume) {
293
294 mail.setState(Mail.GHOST);
295 }
296 }
297
298
299
300
301
302
303 public String getMailetInfo() {
304 return "Sieve Mailbox Mailet";
305 }
306
307
308
309
310
311
312
313
314 public void storeMail(MailAddress sender, MailAddress recipient,
315 Mail mail) throws MessagingException {
316 String username;
317 if (recipient == null) {
318 throw new IllegalArgumentException(
319 "Recipient for mail to be spooled cannot be null.");
320 }
321 if (mail.getMessage() == null) {
322 throw new IllegalArgumentException(
323 "Mail message to be spooled cannot be null.");
324 }
325
326 username = recipient.getUser();
327
328 sieveMessage(username, mail);
329
330 }
331
332 void sieveMessage(String username, Mail aMail) throws MessagingException {
333
334 String relativeUri = "//" + username + "@" + "localhost/sieve";
335 try
336 {
337 final InputStream ins = locator.get(relativeUri);
338
339 SieveMailAdapter aMailAdapter = new SieveMailAdapter(aMail,
340 getMailetContext(), actionDispatcher, poster);
341 aMailAdapter.setLog(log);
342
343 if (verbose) {
344 log("Evaluating " + aMailAdapter.toString() + "against \""
345 + relativeUri + "\"");
346 }
347 factory.evaluate(aMailAdapter, factory.parse(ins));
348 }
349 catch (Exception ex)
350 {
351
352
353
354
355
356
357 if (isInfoLoggingOn()) {
358 log("Cannot evaluate Sieve script. Storing mail in user INBOX.", ex);
359 }
360 storeMessageInbox(username, aMail);
361 }
362 }
363
364 void storeMessageInbox(String username, Mail mail) throws MessagingException {
365 String url = "mailbox://" + username + "@localhost/";
366 poster.post(url, mail.getMessage());
367 }
368
369
370
371
372 public void init() throws MessagingException {
373 super.init();
374 if (poster == null || locator == null) {
375 throw new MailetException("Not initialised. Please ensure that the mailet container supports either" +
376 " setter or constructor injection");
377 }
378
379 this.deliveryHeader = getInitParameter("addDeliveryHeader");
380 this.resetReturnPath = getInitParameter("resetReturnPath", true);
381 this.consume = getInitParameter("consume", true);
382 this.verbose = getInitParameter("verbose", false);
383 this.quiet = getInitParameter("quiet", false);
384
385 actionDispatcher = new ActionDispatcher();
386 }
387 }