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 }