1 /****************************************************************
2 * Licensed to the Apache Software Foundation (ASF) under one *
3 * or more contributor license agreements. See the NOTICE file *
4 * distributed with this work for additional information *
5 * regarding copyright ownership. The ASF licenses this file *
6 * to you under the Apache License, Version 2.0 (the *
7 * "License"); you may not use this file except in compliance *
8 * with the License. You may obtain a copy of the License at *
9 * *
10 * http://www.apache.org/licenses/LICENSE-2.0 *
11 * *
12 * Unless required by applicable law or agreed to in writing, *
13 * software distributed under the License is distributed on an *
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
15 * KIND, either express or implied. See the License for the *
16 * specific language governing permissions and limitations *
17 * under the License. *
18 ****************************************************************/
19
20
21
22 package org.apache.james.transport.mailets;
23
24 import javax.mail.MessagingException;
25 import javax.mail.internet.MimeMessage;
26
27 import org.apache.mailet.base.GenericMailet;
28 import org.apache.mailet.Mail;
29 import org.apache.mailet.base.RFC2822Headers;
30
31 /**
32 * Add an prefix (tag) to the subject of a message <br>
33 * <br>
34 *
35 * Sample Configuration: <br>
36 * <pre><code>
37 * <mailet match="RecipientIs=robot@james.apache.org" class="TagMessage">
38 * <subjectPrefix>[robot]</subjectPrefix> </mailet> <br>
39 * </code></pre>
40 */
41 public class AddSubjectPrefix extends GenericMailet {
42
43 // prefix to add
44 private String subjectPrefix = null;
45
46 /**
47 * Initialize the mailet.
48 */
49 public void init() throws MessagingException {
50 subjectPrefix = getInitParameter("subjectPrefix");
51
52 if (subjectPrefix == null || subjectPrefix.equals("")) {
53 throw new MessagingException(
54 "Please configure a valid subjectPrefix");
55 }
56 }
57
58 /**
59 * Takes the message and adds a prefix to the subject
60 *
61 * @param mail
62 * the mail being processed
63 *
64 * @throws MessagingException
65 * if an error arises during message processing
66 */
67 public void service(Mail mail) throws MessagingException {
68 String newSubject = null;
69 MimeMessage m = mail.getMessage();
70
71 String subject = m.getSubject();
72
73 if (subject != null) {
74 // m.setSubject(subjectPrefix + " " + subject);
75 newSubject = subjectPrefix + " " + m.getSubject().toString();
76
77 } else {
78 newSubject = subjectPrefix;
79 }
80
81 /*
82 * Get sure to use the right encoding when add the subjectPrefix..
83 * otherwise we get problems with some special chars
84 */
85 String rawSubject = m.getHeader(RFC2822Headers.SUBJECT, null);
86 String mimeCharset = determineMailHeaderEncodingCharset(rawSubject);
87 if (mimeCharset == null) { // most likely ASCII
88 // it uses the system charset or the value of the
89 // mail.mime.charset property if set
90 m.setSubject(newSubject);
91 return;
92 } else { // original charset determined
93 String javaCharset = javax.mail.internet.MimeUtility
94 .javaCharset(mimeCharset);
95 try {
96 m.setSubject(newSubject, javaCharset);
97 } catch (MessagingException e) {
98 // known, but unsupported encoding
99 // this should be logged, the admin may setup a more i18n
100 // capable JRE, but the log API cannot be accessed from here
101 // if (charset != null) log(charset +
102 // " charset unsupported by the JRE, email subject may be
103 // damaged");
104 m.setSubject(newSubject); // recover
105 }
106 }
107 m.saveChanges();
108 }
109
110 public String getMailetInfo() {
111 return "AddSubjectPrefix Mailet";
112 }
113
114 /**
115 * It attempts to determine the charset used to encode an "unstructured" RFC
116 * 822 header (like Subject). The encoding is specified in RFC 2047. If it
117 * cannot determine or the the text is not encoded then it returns null.
118 *
119 * Here is an example raw text: Subject:
120 * =?iso-8859-2?Q?leg=FAjabb_pr=F3ba_l=F5elemmel?=
121 *
122 * TODO: Should we include this in a util class ?
123 *
124 * @param rawText
125 * the raw (not decoded) value of the header. Null means that the
126 * header was not present (in this case it always return null).
127 * @return the MIME charset name or null if no encoding applied
128 */
129 static private String determineMailHeaderEncodingCharset(String rawText) {
130 if (rawText == null)
131 return null;
132 int iEncodingPrefix = rawText.indexOf("=?");
133 if (iEncodingPrefix == -1)
134 return null;
135 int iCharsetBegin = iEncodingPrefix + 2;
136 int iSecondQuestionMark = rawText.indexOf('?', iCharsetBegin);
137 if (iSecondQuestionMark == -1)
138 return null;
139 // safety checks
140 if (iSecondQuestionMark == iCharsetBegin)
141 return null; // empty charset? impossible
142 int iThirdQuestionMark = rawText.indexOf('?', iSecondQuestionMark + 1);
143 if (iThirdQuestionMark == -1)
144 return null; // there must be one after encoding
145 if (-1 == rawText.indexOf("?=", iThirdQuestionMark + 1))
146 return null; // closing tag
147 String mimeCharset = rawText.substring(iCharsetBegin,
148 iSecondQuestionMark);
149 return mimeCharset;
150 }
151
152 }