1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.james.transport.mailets;
21
22 import org.apache.mailet.base.GenericMailet;
23 import org.apache.mailet.Mail;
24 import org.apache.mailet.MailetException;
25
26 import javax.mail.Message;
27 import javax.mail.MessagingException;
28 import javax.mail.Multipart;
29 import javax.mail.Part;
30 import javax.mail.internet.MimeMessage;
31 import javax.mail.internet.MimeUtility;
32
33 import java.io.BufferedInputStream;
34 import java.io.BufferedOutputStream;
35 import java.io.ByteArrayOutputStream;
36 import java.io.File;
37 import java.io.FileOutputStream;
38 import java.io.InputStream;
39 import java.io.OutputStream;
40 import java.util.ArrayList;
41 import java.util.Collection;
42 import java.util.LinkedHashMap;
43 import java.util.List;
44 import java.util.Map;
45 import java.util.regex.Pattern;
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69 public class StripAttachment extends GenericMailet {
70
71 public static final String PATTERN_PARAMETER_NAME = "pattern";
72
73 public static final String NOTPATTERN_PARAMETER_NAME = "notpattern";
74
75 public static final String ATTRIBUTE_PARAMETER_NAME = "attribute";
76
77 public static final String DIRECTORY_PARAMETER_NAME = "directory";
78
79
80 public static final String REMOVE_ATTACHMENT_PARAMETER_NAME = "remove";
81
82
83 public static final String DECODE_FILENAME_PARAMETER_NAME = "decodeFilename";
84
85 public static final String REPLACE_FILENAME_PATTERN_PARAMETER_NAME = "replaceFilenamePattern";
86
87 public static final String REMOVE_NONE = "no";
88
89 public static final String REMOVE_ALL = "all";
90
91 public static final String REMOVE_MATCHED = "matched";
92
93 public static final String REMOVED_ATTACHMENTS_ATTRIBUTE_KEY = "org.apache.james.transport.mailets.StripAttachment.removed";
94
95 public static final String SAVED_ATTACHMENTS_ATTRIBUTE_KEY = "org.apache.james.transport.mailets.StripAttachment.saved";
96
97 private String patternString = null;
98
99 private String notpatternString = null;
100
101 private String removeAttachments = null;
102
103 private String directoryName = null;
104
105 private String attributeName = null;
106
107 private Pattern regExPattern = null;
108
109 private Pattern notregExPattern = null;
110
111 private boolean decodeFilename = false;
112
113 private Pattern[] replaceFilenamePatterns = null;
114
115 private String[] replaceFilenameSubstitutions = null;
116
117 private Integer[] replaceFilenameFlags = null;
118
119 private static boolean getBooleanParameter(String v, boolean def) {
120 return def ? !(v != null && (v.equalsIgnoreCase("false") || v
121 .equalsIgnoreCase("no"))) : v != null
122 && (v.equalsIgnoreCase("true") || v.equalsIgnoreCase("yes"));
123 }
124
125
126
127
128
129
130
131 public void init() throws MailetException {
132 patternString = getInitParameter(PATTERN_PARAMETER_NAME);
133 notpatternString = getInitParameter(NOTPATTERN_PARAMETER_NAME);
134 if (patternString == null && notpatternString == null) {
135 throw new MailetException("No value for " + PATTERN_PARAMETER_NAME
136 + " parameter was provided.");
137 }
138
139 directoryName = getInitParameter(DIRECTORY_PARAMETER_NAME);
140 attributeName = getInitParameter(ATTRIBUTE_PARAMETER_NAME);
141
142 removeAttachments = getInitParameter(REMOVE_ATTACHMENT_PARAMETER_NAME,
143 REMOVE_NONE).toLowerCase();
144 if (!REMOVE_MATCHED.equals(removeAttachments)
145 && !REMOVE_ALL.equals(removeAttachments)) {
146 removeAttachments = REMOVE_NONE;
147 }
148
149 try {
150
151
152 if (patternString != null)
153 regExPattern = Pattern.compile(patternString);
154 } catch (Exception e) {
155 throw new MailetException("Could not compile regex ["
156 + patternString + "].");
157 }
158 try {
159
160
161 if (notpatternString != null)
162 notregExPattern = Pattern.compile(notpatternString);
163 } catch (Exception e) {
164 throw new MailetException("Could not compile regex ["
165 + notpatternString + "].");
166 }
167
168 if (directoryName != null) {
169 try {
170 File saveDirectory = null;
171 saveDirectory = new File(directoryName);
172 if (!saveDirectory.exists()) {
173 saveDirectory.mkdirs();
174 }
175 } catch (Exception e) {
176 throw new MailetException("Could not create directory ["
177 + directoryName + "].", e);
178 }
179 }
180
181 decodeFilename = getBooleanParameter(
182 getInitParameter(DECODE_FILENAME_PARAMETER_NAME),
183 decodeFilename);
184 if (getInitParameter(REPLACE_FILENAME_PATTERN_PARAMETER_NAME) != null) {
185 List[] pl = ReplaceContent
186 .getPatternsFromString(getInitParameter(REPLACE_FILENAME_PATTERN_PARAMETER_NAME));
187 replaceFilenamePatterns = (Pattern[]) pl[0].toArray(new Pattern[0]);
188 replaceFilenameSubstitutions = (String[]) pl[1]
189 .toArray(new String[0]);
190 replaceFilenameFlags = (Integer[]) pl[2].toArray(new Integer[0]);
191 }
192
193 String toLog = "StripAttachment is initialised with regex pattern ["
194 + patternString + " / " + notpatternString + "]";
195 if (directoryName != null) {
196 toLog += " and will save to directory [" + directoryName + "]";
197 }
198 if (attributeName != null) {
199 toLog += " and will store attachments to attribute ["
200 + attributeName + "]";
201 }
202 log(toLog);
203 }
204
205
206
207
208
209
210
211
212
213
214 public void service(Mail mail) throws MailetException {
215 MimeMessage message = null;
216 try {
217 message = mail.getMessage();
218 } catch (MessagingException e) {
219 throw new MailetException(
220 "Could not retrieve message from Mail object", e);
221 }
222
223
224 try {
225 if (message.isMimeType("multipart/*")) {
226 analyseMultipartPartMessage(message, mail);
227 }
228 } catch (MessagingException e) {
229 throw new MailetException(
230 "Could not retrieve contenttype of message.", e);
231 } catch (Exception e) {
232 throw new MailetException("Could not analyse message.", e);
233 }
234 }
235
236
237
238
239
240
241 public String getMailetInfo() {
242 return "StripAttachment";
243 }
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258 private boolean analyseMultipartPartMessage(Part part, Mail mail)
259 throws Exception {
260 if (part.isMimeType("multipart/*")) {
261 try {
262 Multipart multipart = (Multipart) part.getContent();
263 boolean atLeastOneRemoved = false;
264 int numParts = multipart.getCount();
265 for (int i = 0; i < numParts; i++) {
266 Part p = multipart.getBodyPart(i);
267 if (p.isMimeType("multipart/*")) {
268 atLeastOneRemoved |= analyseMultipartPartMessage(p,
269 mail);
270 } else {
271 boolean removed = checkMessageRemoved(p, mail);
272 if (removed) {
273 multipart.removeBodyPart(i);
274 atLeastOneRemoved = true;
275 i--;
276 numParts--;
277 }
278 }
279 }
280 if (atLeastOneRemoved) {
281 part.setContent(multipart);
282 if (part instanceof Message) {
283 ((Message) part).saveChanges();
284 }
285 }
286 return atLeastOneRemoved;
287 } catch (Exception e) {
288 log("Could not analyse part.", e);
289 }
290 }
291 return false;
292 }
293
294 private boolean checkMessageRemoved(Part part, Mail mail)
295 throws MessagingException, Exception {
296 String fileName = null;
297 fileName = part.getFileName();
298
299
300 boolean ret = false;
301
302 if (fileName != null) {
303 if (decodeFilename)
304 fileName = MimeUtility.decodeText(fileName);
305
306 if (replaceFilenamePatterns != null)
307 fileName = ReplaceContent.applyPatterns(
308 replaceFilenamePatterns, replaceFilenameSubstitutions,
309 replaceFilenameFlags, fileName, 0, this);
310
311 if (fileNameMatches(fileName)) {
312 if (directoryName != null) {
313 String filename = saveAttachmentToFile(part, fileName);
314 if (filename != null) {
315 Collection c = (Collection) mail
316 .getAttribute(SAVED_ATTACHMENTS_ATTRIBUTE_KEY);
317 if (c == null) {
318 c = new ArrayList();
319 mail.setAttribute(SAVED_ATTACHMENTS_ATTRIBUTE_KEY,
320 (ArrayList) c);
321 }
322 c.add(filename);
323 }
324 }
325 if (attributeName != null) {
326 Map m = (Map) mail.getAttribute(attributeName);
327 if (m == null) {
328 m = new LinkedHashMap();
329 mail.setAttribute(attributeName, (LinkedHashMap) m);
330 }
331 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
332 OutputStream os = new BufferedOutputStream(
333 byteArrayOutputStream);
334 part.writeTo(os);
335 m.put(fileName, byteArrayOutputStream.toByteArray());
336 }
337 if (removeAttachments.equals(REMOVE_MATCHED)) {
338 ret = true;
339 }
340 }
341 if (!ret) {
342 ret = removeAttachments.equals(REMOVE_ALL);
343 }
344 if (ret) {
345 Collection c = (Collection) mail
346 .getAttribute(REMOVED_ATTACHMENTS_ATTRIBUTE_KEY);
347 if (c == null) {
348 c = new ArrayList();
349 mail.setAttribute(REMOVED_ATTACHMENTS_ATTRIBUTE_KEY,
350 (ArrayList) c);
351 }
352 c.add(fileName);
353 }
354 }
355 return ret;
356 }
357
358
359
360
361
362
363
364
365 private boolean fileNameMatches(String name) {
366 boolean result = true;
367 if (regExPattern != null)
368 result = regExPattern.matcher(name).matches();
369 if (result && notregExPattern != null)
370 result = !notregExPattern.matcher(name).matches();
371
372 String log = "attachment " + name + " ";
373 if (!result)
374 log += "does not match";
375 else
376 log += "matches";
377 log(log);
378 return result;
379 }
380
381
382
383
384
385
386
387
388
389
390 private String saveAttachmentToFile(Part part, String fileName)
391 throws Exception {
392 BufferedOutputStream os = null;
393 InputStream is = null;
394 File f = null;
395 try {
396 if (fileName == null)
397 fileName = part.getFileName();
398 int pos = -1;
399 if (fileName != null) {
400 pos = fileName.lastIndexOf(".");
401 }
402 String prefix = pos > 0 ? (fileName.substring(0, pos)) : fileName;
403 String suffix = pos > 0 ? (fileName.substring(pos)) : ".bin";
404 while (prefix.length() < 3)
405 prefix += "_";
406 if (suffix.length() == 0)
407 suffix = ".bin";
408 f = File.createTempFile(prefix, suffix, new File(directoryName));
409 log("saving content of " + f.getName() + "...");
410 os = new BufferedOutputStream(new FileOutputStream(f));
411 is = part.getInputStream();
412 if (!(is instanceof BufferedInputStream)) {
413 is = new BufferedInputStream(is);
414 }
415 int c;
416 while ((c = is.read()) != -1) {
417 os.write(c);
418 }
419
420 return f.getName();
421 } catch (Exception e) {
422 log("Error while saving contents of ["
423 + (f != null ? f.getName() : (part != null ? part
424 .getFileName() : "NULL")) + "].", e);
425 throw e;
426 } finally {
427 is.close();
428 os.close();
429 }
430 }
431
432 }