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 package org.apache.james.transport.mailets;
21
22 import org.apache.mailet.GenericMailet;
23 import org.apache.mailet.Mail;
24 import org.apache.mailet.RFC2822Headers;
25
26 import javax.mail.MessagingException;
27 import javax.mail.internet.MimeBodyPart;
28 import javax.mail.internet.MimeMessage;
29 import javax.mail.internet.MimeMultipart;
30 import javax.mail.internet.MimePart;
31
32 import java.io.IOException;
33 import java.io.UnsupportedEncodingException;
34
35 /***
36 * An abstract implementation of a mailet that add a Footer to an email
37 */
38 public abstract class AbstractAddFooter extends GenericMailet {
39
40 /***
41 * Takes the message and attaches a footer message to it. Right now, it only
42 * supports simple messages. Needs to have additions to make it support
43 * messages with alternate content types or with attachments.
44 *
45 * @param mail the mail being processed
46 *
47 * @throws MessagingException if an error arises during message processing
48 */
49 public void service(Mail mail) throws MessagingException {
50 try {
51 MimeMessage message = mail.getMessage();
52
53 if (attachFooter(message)) {
54 message.saveChanges();
55 } else {
56 log("Unable to add footer to mail " + mail.getName());
57 }
58 } catch (UnsupportedEncodingException e) {
59 log("UnsupportedEncoding Unable to add footer to mail "
60 + mail.getName());
61 } catch (IOException ioe) {
62 throw new MessagingException("Could not read message", ioe);
63 }
64 }
65
66 /***
67 * Prepends the content of the MimePart as text to the existing footer
68 *
69 * @param part the MimePart to attach
70 *
71 * @throws MessagingException
72 * @throws IOException
73 */
74 protected void addToText(MimePart part) throws MessagingException,
75 IOException {
76
77 String contentType = part.getContentType();
78 String content = (String) part.getContent();
79
80 if (!content.endsWith("\n")) {
81 content += "\r\n";
82 }
83 content += getFooterText();
84
85 part.setContent(content, contentType);
86 part.setHeader(RFC2822Headers.CONTENT_TYPE, contentType);
87
88 }
89
90 /***
91 * Prepends the content of the MimePart as HTML to the existing footer
92 *
93 * @param part the MimePart to attach
94 *
95 * @throws MessagingException
96 * @throws IOException
97 */
98 protected void addToHTML(MimePart part) throws MessagingException,
99 IOException {
100
101 String contentType = part.getContentType();
102 String content = (String) part.getContent();
103
104
105
106
107 int index = content.lastIndexOf("</body>");
108 if (index == -1)
109 index = content.lastIndexOf("</BODY>");
110 String insert = "<br>" + getFooterHTML();
111 content = index == -1 ? content + insert : content.substring(0, index)
112 + insert + content.substring(index);
113
114 part.setContent(content, contentType);
115 part.setHeader(RFC2822Headers.CONTENT_TYPE, contentType);
116
117 }
118
119 /***
120 * Attach a footer a MimePart
121 *
122 * @param part the MimePart to which the footer is to be attached
123 *
124 * @return whether a footer was successfully attached
125 * @throws MessagingException
126 * @throws IOException
127 */
128 protected boolean attachFooter(MimePart part) throws MessagingException,
129 IOException {
130
131 if (part.isMimeType("text/plain")
132 && part.getContent() instanceof String) {
133 addToText(part);
134 return true;
135 } else if (part.isMimeType("text/html")
136 && part.getContent() instanceof String) {
137 addToHTML(part);
138 return true;
139 } else if (part.isMimeType("multipart/mixed")
140 || part.isMimeType("multipart/related")) {
141
142 MimeMultipart multipart = (MimeMultipart) part.getContent();
143 MimeBodyPart firstPart = (MimeBodyPart) multipart.getBodyPart(0);
144 boolean isFooterAttached = attachFooter(firstPart);
145 if (isFooterAttached) {
146
147
148 part.setContent(multipart);
149 }
150 return isFooterAttached;
151 } else if (part.isMimeType("multipart/alternative")) {
152 MimeMultipart multipart = (MimeMultipart) part.getContent();
153 int count = multipart.getCount();
154
155 boolean isFooterAttached = false;
156 for (int index = 0; index < count; index++) {
157
158 MimeBodyPart mimeBodyPart = (MimeBodyPart) multipart
159 .getBodyPart(index);
160 isFooterAttached |= attachFooter(mimeBodyPart);
161 }
162 if (isFooterAttached) {
163
164
165 part.setContent(multipart);
166 }
167 return isFooterAttached;
168 } else {
169
170 return false;
171 }
172 }
173
174 /***
175 * This is exposed as a method for easy subclassing to provide alternate ways
176 * to get the footer text.
177 *
178 * @return the footer text
179 */
180 protected abstract String getFooterText();
181
182 /***
183 * This is exposed as a method for easy subclassing to provide alternate ways
184 * to get the footer text. By default, this will take the footer text,
185 * converting the linefeeds to <br> tags.
186 *
187 * @return the HTML version of the footer text
188 */
189 protected abstract String getFooterHTML();
190
191 }