1 19 20 package org.apache.james.core; 21 22 import org.apache.avalon.framework.container.ContainerUtil; 23 import org.apache.mailet.RFC2822Headers; 24 25 import javax.mail.BodyPart ; 26 import javax.mail.Session ; 27 import javax.mail.internet.InternetHeaders ; 28 import javax.mail.internet.MimeBodyPart ; 29 import javax.mail.internet.MimeMessage ; 30 import javax.mail.internet.MimeMultipart ; 31 32 import java.io.ByteArrayInputStream ; 33 import java.io.ByteArrayOutputStream ; 34 import java.util.Arrays ; 35 import java.util.Enumeration ; 36 import java.util.Properties ; 37 38 import junit.framework.TestCase; 39 40 43 public class MimeMessageTest extends TestCase { 44 45 protected MimeMessage getSimpleMessage() throws Exception { 46 MimeMessage mmCreated = new MimeMessage (Session.getDefaultInstance(new Properties ())); 47 mmCreated.setSubject("test"); 48 mmCreated.setText("test body"); 49 mmCreated.saveChanges(); 50 return mmCreated; 51 } 52 53 protected String getSimpleMessageCleanedSource() throws Exception { 54 return "Subject: test\r\n" 55 +"MIME-Version: 1.0\r\n" 56 +"Content-Type: text/plain; charset=us-ascii\r\n" 57 +"Content-Transfer-Encoding: 7bit\r\n" 58 +"\r\n" 59 +"test body"; 60 } 61 62 63 protected MimeMessage getMessageWithBadReturnPath() throws Exception { 64 MimeMessage mmCreated = new MimeMessage (Session.getDefaultInstance(new Properties ())); 65 mmCreated.setSubject("test"); 66 mmCreated.setHeader(RFC2822Headers.RETURN_PATH, "<mybadreturn@example.com>"); 67 mmCreated.setText("test body"); 68 mmCreated.saveChanges(); 69 return mmCreated; 70 } 71 72 protected String getMessageWithBadReturnPathSource() throws Exception { 73 return "Subject: test\r\n" 74 +"Return-Path: <mybadreturn@example.com>\r\n" 75 +"MIME-Version: 1.0\r\n" 76 +"Content-Type: text/plain; charset=us-ascii\r\n" 77 +"Content-Transfer-Encoding: 7bit\r\n" 78 +"\r\n" 79 +"test body"; 80 } 81 82 protected String getSimpleMessageCleanedSourceHeaderExpected() throws Exception { 83 return "X-Test: foo\r\n"+getSimpleMessageCleanedSource(); 84 } 85 86 89 public void testSimpleMessage() throws Exception { 90 MimeMessage m = getSimpleMessage(); 91 assertEquals(getSimpleMessageCleanedSource(), getCleanedMessageSource(m)); 92 ContainerUtil.dispose(m); 93 } 94 95 96 protected MimeMessage getMultipartMessage() throws Exception { 97 MimeMessage mmCreated = new MimeMessage (Session.getDefaultInstance(new Properties ())); 98 mmCreated.setSubject("test"); 99 MimeMultipart mm = new MimeMultipart ("alternative"); 100 mm.addBodyPart(new MimeBodyPart (new InternetHeaders (new ByteArrayInputStream ("X-header: test1\r\nContent-Type: text/plain; charset=Cp1252\r\n".getBytes())),"first part \u00F2\u00E0\u00F9".getBytes())); 101 mm.addBodyPart(new MimeBodyPart (new InternetHeaders (new ByteArrayInputStream ("X-header: test2\r\nContent-Type: text/plain; charset=Cp1252\r\nContent-Transfer-Encoding: quoted-printable\r\n".getBytes())),"second part =E8=E8".getBytes())); 102 mmCreated.setContent(mm); 103 mmCreated.saveChanges(); 104 return mmCreated; 105 } 106 107 protected String getMultipartMessageSource() { 108 return "Subject: test\r\n" 109 +"MIME-Version: 1.0\r\n" 110 +"Content-Type: multipart/alternative; \r\n" 111 +"\tboundary=\"----=_Part_0_XXXXXXXXXXX.XXXXXXXXXXX\"\r\n" 112 +"\r\n" 113 +"------=_Part_0_XXXXXXXXXXX.XXXXXXXXXXX\r\n" 114 +"X-header: test1\r\n" 115 +"Content-Type: text/plain; charset=Cp1252\r\n" 116 +"Content-Transfer-Encoding: quoted-printable\r\n" 117 +"\r\n" 118 +"first part =E8\r\n" 119 +"------=_Part_0_XXXXXXXXXXX.XXXXXXXXXXX\r\n" 120 +"X-header: test2\r\n" 121 +"Content-Type: text/plain; charset=Cp1252\r\n" 122 +"Content-Transfer-Encoding: quoted-printable\r\n" 123 +"\r\n" 124 +"second part =E8=E8\r\n" 125 +"------=_Part_0_XXXXXXXXXXX.XXXXXXXXXXX--\r\n"; 126 } 127 128 protected String getMultipartMessageExpected1() { 129 return "Subject: test\r\n" 130 +"MIME-Version: 1.0\r\n" 131 +"Content-Type: multipart/alternative; \r\n" 132 +"\tboundary=\"----=_Part_0_XXXXXXXXXXX.XXXXXXXXXXX\"\r\n" 133 +"\r\n" 134 +"------=_Part_0_XXXXXXXXXXX.XXXXXXXXXXX\r\n" 135 +"X-header: test1\r\n" 136 +"Content-Type: text/plain; charset=Cp1252\r\n" 137 +"Content-Transfer-Encoding: quoted-printable\r\n" 138 +"\r\n" 139 +"test=80\r\n" 140 +"------=_Part_0_XXXXXXXXXXX.XXXXXXXXXXX\r\n" 141 +"X-header: test2\r\n" 142 +"Content-Type: text/plain; charset=Cp1252\r\n" 143 +"Content-Transfer-Encoding: quoted-printable\r\n" 144 +"\r\n" 145 +"second part =E8=E8\r\n" 146 +"------=_Part_0_XXXXXXXXXXX.XXXXXXXXXXX--\r\n"; 147 } 148 149 protected String getMultipartMessageExpected2() { 150 return "Subject: test\r\n" 151 +"MIME-Version: 1.0\r\n" 152 +"Content-Type: multipart/alternative; \r\n" 153 +"\tboundary=\"----=_Part_0_XXXXXXXXXXX.XXXXXXXXXXX\"\r\n" 154 +"\r\n" 155 +"------=_Part_0_XXXXXXXXXXX.XXXXXXXXXXX\r\n" 156 +"X-header: test1\r\n" 157 +"Content-Type: text/plain; charset=Cp1252\r\n" 158 +"Content-Transfer-Encoding: quoted-printable\r\n" 159 +"\r\n" 160 +"test=80\r\n" 161 +"------=_Part_0_XXXXXXXXXXX.XXXXXXXXXXX\r\n" 162 +"X-header: test2\r\n" 163 +"Content-Type: text/plain; charset=Cp1252\r\n" 164 +"Content-Transfer-Encoding: quoted-printable\r\n" 165 +"\r\n" 166 +"second part =E8=E8\r\n" 167 +"------=_Part_0_XXXXXXXXXXX.XXXXXXXXXXX\r\n" 168 +"Subject: test3\r\n" 169 +"Content-Transfer-Encoding: 7bit\r\n" 170 +"Content-Type: text/plain; charset=us-ascii\r\n" 171 +"\r\n" 172 +"second part\r\n" 173 +"------=_Part_0_XXXXXXXXXXX.XXXXXXXXXXX--\r\n"; 174 } 175 176 protected String getMultipartMessageExpected3() { 177 return "Subject: test\r\n" 178 +"MIME-Version: 1.0\r\n" 179 +"Content-Type: binary/octet-stream\r\n" 180 +"Content-Transfer-Encoding: quoted-printable\r\n" 181 +"\r\n" 182 +"mynewco=F2=E0=F9ntent=80=E0!"; 183 } 184 185 188 public void testMultipartMessageChanges() throws Exception { 189 190 MimeMessage mm = getMultipartMessage(); 191 192 197 198 MimeMultipart content1 = (MimeMultipart ) mm.getContent(); 199 BodyPart b1 = content1.getBodyPart(0); 200 b1.setContent("test\u20AC","text/plain; charset=Cp1252"); 201 mm.setContent(content1,mm.getContentType()); 202 mm.saveChanges(); 204 205 assertEquals(getMultipartMessageExpected1(),getCleanedMessageSource(mm)); 206 207 MimeMultipart content2 = (MimeMultipart ) mm.getContent(); 208 content2.addBodyPart(new MimeBodyPart (new InternetHeaders (new ByteArrayInputStream ("Subject: test3\r\n".getBytes())),"second part".getBytes())); 209 mm.setContent(content2,mm.getContentType()); 210 mm.saveChanges(); 211 212 assertEquals(getMultipartMessageExpected2(),getCleanedMessageSource(mm)); 213 214 mm.setContent("mynewco\u00F2\u00E0\u00F9ntent\u20AC\u00E0!","text/plain; charset=cp1252"); 215 mm.setHeader(RFC2822Headers.CONTENT_TYPE,"binary/octet-stream"); 216 mm.saveChanges(); 218 219 assertEquals(getMultipartMessageExpected3(),getCleanedMessageSource(mm)); 220 221 ContainerUtil.dispose(mm); 222 223 } 224 225 protected MimeMessage getMissingEncodingAddHeaderMessage() throws Exception { 226 MimeMessage m = new MimeMessage (Session.getDefaultInstance(new Properties ())); 227 m.setText("Test\u00E0\r\n"); 228 m.setSubject("test"); 229 m.saveChanges(); 230 return m; 231 } 232 233 234 protected String getMissingEncodingAddHeaderSource() { 235 return "Subject: test\r\n"+ 236 "\r\n"+ 237 "Test\u00E0\r\n"; 238 } 239 240 protected String getMissingEncodingAddHeaderExpected() { 241 return "Subject: test\r\n" 242 +"MIME-Version: 1.0\r\n" 243 +"Content-Type: text/plain; charset=Cp1252\r\n" 244 +"Content-Transfer-Encoding: quoted-printable\r\n" 245 +"\r\n" 246 +"Test=E0\r\n"; 247 } 248 249 250 253 264 265 266 protected String getCleanedMessageSource(MimeMessage mm) throws Exception { 267 ByteArrayOutputStream out2; 268 out2 = new ByteArrayOutputStream (); 269 mm.writeTo(out2,new String [] {"Message-ID"}); 270 271 String res = out2.toString(); 272 273 int p = res.indexOf("\r\n\r\n"); 274 if (p > 0) { 275 String head = res.substring(0,p); 276 String [] str = head.split("\r\n"); 277 Arrays.sort(str); 278 StringBuffer outputHead = new StringBuffer (); 279 for (int i = str.length-1; i >= 0; i--) { 280 outputHead.append(str[i]); 281 outputHead.append("\r\n"); 282 } 283 outputHead.append(res.substring(p+2)); 284 res = outputHead.toString(); 285 } 286 287 res = res.replaceAll("----=_Part_\\d_\\d+\\.\\d+","----=_Part_\\0_XXXXXXXXXXX.XXXXXXXXXXX"); 288 return res; 289 } 290 291 protected void debugMessage(MimeMessage mm) throws Exception { 292 System.out.println("-------------------"); 293 System.out.println(getCleanedMessageSource(mm)); 294 System.out.println("-------------------"); 295 } 296 297 298 protected MimeMessage getMissingEncodingMessage() throws Exception { 299 MimeMessage mmCreated = new MimeMessage (Session.getDefaultInstance(new Properties ())); 300 mmCreated.setSubject("test"); 301 MimeMultipart mm = new MimeMultipart ("alternative"); 302 mm.addBodyPart(new MimeBodyPart (new InternetHeaders (new ByteArrayInputStream ("X-header: test2\r\nContent-Type: text/plain; charset=Cp1252\r\nContent-Transfer-Encoding: quoted-printable\r\n".getBytes())),"second part =E8=E8".getBytes())); 303 mmCreated.setContent(mm); 304 mmCreated.saveChanges(); 305 return mmCreated; 306 } 307 308 309 protected String getMissingEncodingMessageSource() { 310 return "Subject: test\r\n" 311 +"MIME-Version: 1.0\r\n" 312 +"Content-Type: multipart/alternative; \r\n" 313 +"\tboundary=\"----=_Part_0_XXXXXXXXXXX.XXXXXXXXXXX\"\r\n" 314 +"\r\n" 315 +"------=_Part_0_XXXXXXXXXXX.XXXXXXXXXXX\r\n" 316 +"X-header: test2\r\n" 317 +"Content-Type: text/plain; charset=Cp1252\r\n" 318 +"Content-Transfer-Encoding: quoted-printable\r\n" 319 +"\r\n" 320 +"second part =E8=E8\r\n" 321 +"------=_Part_0_XXXXXXXXXXX.XXXXXXXXXXX--\r\n"; 322 } 323 324 325 public void testGetLineCount() throws Exception { 326 MimeMessage mm = getMissingEncodingMessage(); 327 try { 328 int count = mm.getLineCount(); 329 assertTrue(count == -1 || count == 7); 330 } catch (Exception e) { 331 fail("Unexpected exception in getLineCount"); 332 } 333 ContainerUtil.dispose(mm); 334 } 335 336 340 public void testMessageCloningViaCoW() throws Exception { 341 MimeMessage mmorig = getSimpleMessage(); 342 343 MimeMessage mm = new MimeMessageCopyOnWriteProxy(mmorig); 344 345 MimeMessage mm2 = new MimeMessageCopyOnWriteProxy(mm); 346 347 mm2.setHeader("Subject", "Modified"); 348 349 ContainerUtil.dispose(mm2); 350 System.gc(); 351 Thread.sleep(200); 352 354 mm.setHeader("Subject", "Modified"); 355 356 ContainerUtil.dispose(mm); 357 ContainerUtil.dispose(mmorig); 358 } 359 360 364 public void testMessageCloningViaCoW2() throws Exception { 365 MimeMessage mmorig = getSimpleMessage(); 366 367 MimeMessage mm = new MimeMessageCopyOnWriteProxy(mmorig); 368 369 MimeMessage mm2 = new MimeMessageCopyOnWriteProxy(mm); 370 371 ContainerUtil.dispose(mm); 372 mm = null; 373 System.gc(); 374 Thread.sleep(200); 375 376 try { 377 mm2.writeTo(System.out); 378 } catch (Exception e) { 379 e.printStackTrace(); 380 fail("Exception while writing the message to output"); 381 } 382 383 ContainerUtil.dispose(mm2); 384 ContainerUtil.dispose(mmorig); 385 } 386 387 388 392 public void testMessageCloningViaCoWSubjectLost() throws Exception { 393 MimeMessage mmorig = getSimpleMessage(); 394 395 MimeMessage mm = new MimeMessageCopyOnWriteProxy(mmorig); 396 397 mm.setHeader("X-Test", "foo"); 398 mm.saveChanges(); 399 400 assertEquals(getSimpleMessageCleanedSourceHeaderExpected(),getCleanedMessageSource(mm)); 401 402 ContainerUtil.dispose(mm); 403 ContainerUtil.dispose(mmorig); 404 } 405 406 public void testReturnPath() throws Exception { 407 MimeMessage message = getSimpleMessage(); 408 assertNull(message.getHeader(RFC2822Headers.RETURN_PATH)); 409 ContainerUtil.dispose(message); 410 } 411 412 public void testHeaderOrder() throws Exception { 413 MimeMessage message = getSimpleMessage(); 414 message.setHeader(RFC2822Headers.RETURN_PATH, "<test@test.de>"); 415 Enumeration h = message.getAllHeaderLines(); 416 417 assertEquals(h.nextElement(),"Return-Path: <test@test.de>"); 418 ContainerUtil.dispose(message); 419 } 420 421 } 422 | Popular Tags |