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