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 package org.apache.james.transport.mailets;
20
21 import org.apache.james.core.MailImpl;
22 import org.apache.james.test.mock.mailet.MockMailContext;
23 import org.apache.james.test.mock.mailet.MockMailetConfig;
24 import org.apache.mailet.Mail;
25 import org.apache.mailet.Mailet;
26
27 import javax.mail.MessagingException;
28 import javax.mail.Session;
29 import javax.mail.internet.MimeMessage;
30 import javax.mail.internet.MimeUtility;
31
32 import java.io.ByteArrayInputStream;
33 import java.io.ByteArrayOutputStream;
34 import java.io.IOException;
35 import java.io.UnsupportedEncodingException;
36 import java.util.Properties;
37
38 import junit.framework.TestCase;
39
40 /***
41 * Test encoding issues
42 *
43 * This test should also be run with the following JVM options to be sure it tests:
44 * "-Dfile.encoding=ASCII -Dmail.mime.charset=ANSI_X3.4-1968"
45 */
46 public class AddFooterTest extends TestCase {
47
48 public AddFooterTest(String arg0) throws UnsupportedEncodingException {
49 super(arg0);
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 }
68
69 private final static char[] hexchars = { '0', '1', '2', '3', '4', '5', '6',
70 '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
71
72 public String debugString(String a, String charset)
73 throws UnsupportedEncodingException {
74 byte[] bytes = a.getBytes(charset);
75 StringBuffer res = new StringBuffer();
76 for (int i = 0; i < bytes.length; i++) {
77 if (i > 0)
78 res.append("-");
79 res.append(hexchars[((bytes[i] + 256) % 256) / 16]);
80 res.append(hexchars[((bytes[i] + 256) % 256) % 16]);
81 }
82 res.append(" (");
83 res.append(MimeUtility.mimeCharset(charset));
84 res.append(" / ");
85 res.append(MimeUtility.javaCharset(charset));
86 res.append(")");
87 return res.toString();
88 }
89
90
91
92
93 public void testAddFooterTextPlain() throws MessagingException, IOException {
94
95
96 String asciisource = "Subject: test\r\nContent-Type: text/plain; charset=ISO-8859-15\r\nMIME-Version: 1.0\r\nContent-Transfer-Encoding: quoted-printable\r\n\r\nTest=E0 and one\r\n";
97
98 String iso885915qpheader = "------ my footer =E0/=A4 ------";
99 String footer = "------ my footer \u00E0/\u20AC ------";
100
101 String res = processAddFooter(asciisource, footer);
102
103 assertEquals(asciisource + iso885915qpheader, res);
104
105 }
106
107 public void testUnsupportedEncoding() throws MessagingException, IOException {
108
109
110 String asciisource = "Subject: test\r\nContent-Type: text/plain; charset=UNSUPPORTED_ENCODING\r\nMIME-Version: 1.0\r\nContent-Transfer-Encoding: quoted-printable\r\n\r\nTest=E0 and one\r\n";
111
112 String footer = "------ my footer \u00E0/\u20AC ------";
113
114 try {
115 String res = processAddFooter(asciisource, footer);
116 assertEquals(asciisource, res);
117 } catch (Exception e) {
118 fail("should not throw an exception: "+e.getMessage());
119 }
120
121
122 }
123
124
125
126
127
128 public void testAddFooterMimeNestedUnsupportedMultipart() throws MessagingException, IOException {
129
130
131 String asciisource = "MIME-Version: 1.0\r\n"
132 +"Content-Type: multipart/mixed; boundary=\"===============0204599088==\"\r\n"
133 +"\r\n"
134 +"This is a cryptographically signed message in MIME format.\r\n"
135 +"\r\n"
136 +"--===============0204599088==\r\n"
137 +"Content-Type: multipart/unsupported; boundary=\"------------ms050404020900070803030808\"\r\n"
138 +"\r\n"
139 +"--------------ms050404020900070803030808\r\n"
140 +"Content-Type: text/plain; charset=ISO-8859-1\r\n"
141 +"\r\n"
142 +"test\r\n"
143 +"\r\n"
144 +"--------------ms050404020900070803030808--\r\n"
145 +"\r\n"
146 +"--===============0204599088==--\r\n";
147
148
149 String footer = "------ my footer \u00E0/\u20AC ------";
150
151 String res = processAddFooter(asciisource, footer);
152
153 assertEquals(asciisource, res);
154
155 }
156
157
158
159
160
161 public void testAddFooterMultipartRelated() throws MessagingException, IOException {
162
163
164 String asciisource = "MIME-Version: 1.0\r\n"
165 +"Subject: test\r\n"
166 +"Content-Type: multipart/related;\r\n"
167 +" boundary=\"------------050206010102010306090507\"\r\n"
168 +"\r\n"
169 +"--------------050206010102010306090507\r\n"
170 +"Content-Type: text/html; charset=ISO-8859-15\r\n"
171 +"Content-Transfer-Encoding: quoted-printable\r\n"
172 +"\r\n"
173 +"<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\r\n"
174 +"<html>\r\n"
175 +"<head>\r\n"
176 +"<meta content=3D\"text/html;charset=3DISO-8859-15\" http-equiv=3D\"Content-Typ=\r\n"
177 +"e\">\r\n"
178 +"</head>\r\n"
179 +"<body bgcolor=3D\"#ffffff\" text=3D\"#000000\">\r\n"
180 +"<br>\r\n"
181 +"<div class=3D\"moz-signature\">-- <br>\r\n"
182 +"<img src=3D\"cid:part1.02060605.123@zzz.com\" border=3D\"0\"></div>\r\n";
183 String asciifoot = "</body>\r\n"
184 +"</html>\r\n"
185 +"\r\n"
186 +"--------------050206010102010306090507\r\n"
187 +"Content-Type: image/gif\r\n"
188 +"Content-Transfer-Encoding: base64\r\n"
189 +"Content-ID: <part1.02060605.123@zzz.com>\r\n"
190 +"Content-Disposition: inline;\r\n"
191 +"\r\n"
192 +"YQ==\r\n"
193 +"--------------050206010102010306090507--\r\n";
194
195
196
197 String footer = "------ my footer \u00E0/\u20AC ------";
198 String expectedFooter = "<br>------ my footer =E0/=A4 ------";
199
200 String res = processAddFooter(asciisource+asciifoot, footer);
201
202 assertEquals(asciisource+expectedFooter+asciifoot, res);
203
204 }
205
206
207
208
209
210
211 public void testAddFooterTextPlainISO8859() throws MessagingException, IOException {
212
213
214 String asciisource = "Subject: test\r\nContent-Type: text/plain; charset=iso-8859-15\r\nMIME-Version: 1.0\r\nContent-Transfer-Encoding: quoted-printable\r\n\r\nTest=E0 and one =A4\r\n";
215
216 String iso885915qpheader = "------ my footer =E0/=A4 ------";
217 String footer = "------ my footer \u00E0/\u20AC ------";
218
219 String res = processAddFooter(asciisource, footer);
220
221 assertEquals(asciisource + iso885915qpheader, res);
222
223 }
224
225
226
227
228 public void testAddFooterMultipartAlternative() throws MessagingException,
229 IOException {
230
231 String sep = "--==--";
232 String head = "Subject: test\r\nContent-Type: multipart/alternative;\r\n boundary=\""
233 + sep
234 + "\"\r\nMIME-Version: 1.0\r\n";
235 String content1 = "Content-Type: text/plain;\r\n charset=\"ISO-8859-15\"\r\nContent-Transfer-Encoding: quoted-printable\r\n\r\nTest=E0 and @=80";
236 String c2h = "Content-Type: text/html;\r\n charset=\"CP1252\"\r\nContent-Transfer-Encoding: quoted-printable\r\n\r\n";
237 String c2pre = "<html><body>test =80 ss";
238 String c2post = "</body></html>";
239
240 StringBuffer asciisource = new StringBuffer();
241 asciisource.append(head);
242 asciisource.append("\r\n--");
243 asciisource.append(sep);
244 asciisource.append("\r\n");
245 asciisource.append(content1);
246 asciisource.append("\r\n--");
247 asciisource.append(sep);
248 asciisource.append("\r\n");
249 asciisource.append(c2h);
250 asciisource.append(c2pre);
251 asciisource.append(c2post);
252 asciisource.append("\r\n--");
253 asciisource.append(sep);
254 asciisource.append("--\r\n");
255
256 String iso885915qpheader = "------ my footer =E0/=A4 ------";
257 String cp1252qpfooter = "------ my footer =E0/=80 ------";
258 String footer = "------ my footer \u00E0/\u20AC ------";
259
260 StringBuffer expected = new StringBuffer();
261 expected.append(head);
262 expected.append("\r\n--");
263 expected.append(sep);
264 expected.append("\r\n");
265 expected.append(content1);
266 expected.append("\r\n");
267 expected.append(iso885915qpheader);
268 expected.append("\r\n--");
269 expected.append(sep);
270 expected.append("\r\n");
271 expected.append(c2h);
272 expected.append(c2pre);
273 expected.append("<br>");
274 expected.append(cp1252qpfooter);
275 expected.append(c2post);
276 expected.append("\r\n--");
277 expected.append(sep);
278 expected.append("--\r\n");
279
280 String res = processAddFooter(asciisource.toString(), footer);
281
282 assertEquals(expected.toString(), res);
283
284 }
285
286 private String processAddFooter(String asciisource, String footer)
287 throws MessagingException, IOException {
288 Mailet mailet = new AddFooter();
289
290 MockMailetConfig mci = new MockMailetConfig("Test",new MockMailContext());
291 mci.setProperty("text",footer);
292
293 mailet.init(mci);
294
295 Mail mail = new MailImpl(new MimeMessage(Session
296 .getDefaultInstance(new Properties()),
297 new ByteArrayInputStream(asciisource.getBytes())));
298
299 mailet.service(mail);
300
301 ByteArrayOutputStream rawMessage = new ByteArrayOutputStream();
302 mail.getMessage().writeTo(
303 rawMessage,
304 new String[] { "Bcc", "Content-Length", "Message-ID" });
305 String res = rawMessage.toString();
306 return res;
307 }
308
309 }