View Javadoc

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   * &lt;mailet match="RecipientIs=robot@james.apache.org" class="TagMessage"&gt;
38   * &lt;subjectPrefix&gt;[robot]&lt;/subjectPrefix&gt; &lt;/mailet&gt; <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 }