196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project/* 296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Copyright (C) 2009 The Android Open Source Project 396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * 496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * you may not use this file except in compliance with the License. 696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * You may obtain a copy of the License at 796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * 896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * 1096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 1196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 1296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * See the License for the specific language governing permissions and 1496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * limitations under the License. 1596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 1696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 172193962ca2b3157e79f731736afa2a0c972e778aMarc Blankpackage com.android.emailcommon.internet; 1896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 1931d9acbf0623872f9d4a2b3210b5970854b654c7Marc Blankimport com.android.emailcommon.TempDirectory; 202193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.mail.Address; 212193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.mail.Flag; 222193962ca2b3157e79f731736afa2a0c972e778aMarc Blankimport com.android.emailcommon.mail.Message.RecipientType; 2331d9acbf0623872f9d4a2b3210b5970854b654c7Marc Blankimport com.android.emailcommon.mail.MessagingException; 2496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 25128fb393e8ed613c2ce283c0bd51684af2ba444dMakoto Onukiimport android.test.AndroidTestCase; 26a492673609111fe8c41ae152d62547b267346502Mihai Predaimport android.test.suitebuilder.annotation.MediumTest; 2731d9acbf0623872f9d4a2b3210b5970854b654c7Marc Blankimport android.test.suitebuilder.annotation.SmallTest; 2896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 292517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Hornimport java.io.ByteArrayInputStream; 30a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaokaimport java.io.ByteArrayOutputStream; 312517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Hornimport java.io.IOException; 3296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport java.text.ParseException; 3396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport java.text.SimpleDateFormat; 3496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport java.util.Date; 3596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Projectimport java.util.Locale; 3696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 3796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project/** 3896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * This is a series of unit tests for the MimeMessage class. These tests must be locally 3996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * complete - no server(s) required. 4096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 4196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project@SmallTest 42128fb393e8ed613c2ce283c0bd51684af2ba444dMakoto Onukipublic class MimeMessageTest extends AndroidTestCase { 43961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 447dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler /** up arrow, down arrow, left arrow, right arrow */ 457dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler private final String SHORT_UNICODE = "\u2191\u2193\u2190\u2192"; 467dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler private final String SHORT_UNICODE_ENCODED = "=?UTF-8?B?4oaR4oaT4oaQ4oaS?="; 47961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 487dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler /** a string without any unicode */ 497dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler private final String SHORT_PLAIN = "abcd"; 50961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 517dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler /** longer unicode strings */ 52961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki private final String LONG_UNICODE_16 = SHORT_UNICODE + SHORT_UNICODE + 537dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler SHORT_UNICODE + SHORT_UNICODE; 54961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki private final String LONG_UNICODE_64 = LONG_UNICODE_16 + LONG_UNICODE_16 + 557dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler LONG_UNICODE_16 + LONG_UNICODE_16; 567dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler 577dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler /** longer plain strings (with fold points) */ 587dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler private final String LONG_PLAIN_16 = "abcdefgh ijklmno"; 59961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki private final String LONG_PLAIN_64 = 607dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler LONG_PLAIN_16 + LONG_PLAIN_16 + LONG_PLAIN_16 + LONG_PLAIN_16; 61961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki private final String LONG_PLAIN_256 = 627dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler LONG_PLAIN_64 + LONG_PLAIN_64 + LONG_PLAIN_64 + LONG_PLAIN_64; 6396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project 64128fb393e8ed613c2ce283c0bd51684af2ba444dMakoto Onuki @Override 65128fb393e8ed613c2ce283c0bd51684af2ba444dMakoto Onuki protected void setUp() throws Exception { 66128fb393e8ed613c2ce283c0bd51684af2ba444dMakoto Onuki super.setUp(); 6731d9acbf0623872f9d4a2b3210b5970854b654c7Marc Blank TempDirectory.setTempDirectory(getContext()); 68128fb393e8ed613c2ce283c0bd51684af2ba444dMakoto Onuki } 69128fb393e8ed613c2ce283c0bd51684af2ba444dMakoto Onuki 7096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project /** 7196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * Confirms that setSentDate() correctly set the "Date" header of a Mime message. 72961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki * 7396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * We tries a same test twice using two locales, Locale.US and the other, since 7496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * MimeMessage depends on the date formatter, which may emit wrong date format 7596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * in the locale other than Locale.US. 7696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * @throws MessagingException 7796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project * @throws ParseException 7896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project */ 79a492673609111fe8c41ae152d62547b267346502Mihai Preda @MediumTest 8096c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project public void testSetSentDate() throws MessagingException, ParseException { 8196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project Locale savedLocale = Locale.getDefault(); 8296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project Locale.setDefault(Locale.US); 83961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki doTestSetSentDate(); 8496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project Locale.setDefault(Locale.JAPAN); 85961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki doTestSetSentDate(); 8696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project Locale.setDefault(savedLocale); 8796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 88961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 8996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project private void doTestSetSentDate() throws MessagingException, ParseException { 90961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki // "Thu, 01 Jan 2009 09:00:00 +0000" => 1230800400000L 9196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project long expectedTime = 1230800400000L; 9296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project Date date = new Date(expectedTime); 9396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project MimeMessage message = new MimeMessage(); 9496c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project message.setSentDate(date); 9596c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project String[] headers = message.getHeader("Date"); 9696c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project assertEquals(1, headers.length); 9796c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // Explicitly specify the locale so that the object does not depend on the default 9896c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project // locale. 9996c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US); 100961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 10196c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project Date result = format.parse(headers[0]); 10296c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project assertEquals(expectedTime, result.getTime()); 10396c5af40d639d629267794f4f0338a267ff94ce5The Android Open Source Project } 104961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 1053b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project /** 1063b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project * Simple tests of the new "Message-ID" header 1073b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project */ 1083b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project public void testMessageId() throws MessagingException { 109961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 1103b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project // Test 1. Every message gets a default and unique message-id 1113b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project MimeMessage message1 = new MimeMessage(); 1123b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project MimeMessage message2 = new MimeMessage(); 1133b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project String id1 = message1.getMessageId(); 1143b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project String id2 = message2.getMessageId(); 1153b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project assertNotNull(id1); 1163b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project assertNotNull(id2); 1173b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project assertFalse("Message-ID should be unique", id1.equals(id2)); 118961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 1193b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project // Test 2. Set and get using API 1203b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project final String testId1 = "test-message-id-one"; 1213b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project message1.setMessageId(testId1); 1223b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project assertEquals("set and get Message-ID", testId1, message1.getMessageId()); 123961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 1243b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project // Test 3. Should only be one Message-ID per message 1253b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project final String testId2 = "test-message-id-two"; 1263b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project message2.setMessageId(testId1); 1273b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project message2.setMessageId(testId2); 1283b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project assertEquals("set and get Message-ID", testId2, message2.getMessageId()); 1293b85e2c2b5662c58525baa41479e42c59e292f66The Android Open Source Project } 1303469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project 1317dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler /** 1323469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project * Confirm getContentID() correctly works. 1333469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project */ 1343469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project public void testGetContentId() throws MessagingException { 1353469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project MimeMessage message = new MimeMessage(); 1363469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project 1373469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project // no content-id 1383469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project assertNull(message.getContentId()); 1393469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project 1403469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project // normal case 1413469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project final String cid1 = "cid.1@android.com"; 1423469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project message.setHeader(MimeHeader.HEADER_CONTENT_ID, cid1); 1433469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project assertEquals(cid1, message.getContentId()); 1443469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project 1453469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project // surrounded by optional bracket 1463469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project message.setHeader(MimeHeader.HEADER_CONTENT_ID, "<" + cid1 + ">"); 1473469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project assertEquals(cid1, message.getContentId()); 1483469902379242c723b871d1dcb09b02d0998d538The Android Open Source Project } 149961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 1507dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler /** 1517dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler * Confirm that setSubject() works with plain strings 1527dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler */ 1537dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler public void testSetSubjectPlain() throws MessagingException { 1547dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler MimeMessage message = new MimeMessage(); 1557dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler 1567dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler message.setSubject(SHORT_PLAIN); 157961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 1587dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler // test 1: readback 1597dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler assertEquals("plain subjects", SHORT_PLAIN, message.getSubject()); 160961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 1617dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler // test 2: raw readback is not escaped 1627dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler String rawHeader = message.getFirstHeader("Subject"); 1637dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler assertEquals("plain subject not encoded", -1, rawHeader.indexOf("=?")); 164961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 1657dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler // test 3: long subject (shouldn't fold) 1667dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler message.setSubject(LONG_PLAIN_64); 1677dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler rawHeader = message.getFirstHeader("Subject"); 1687dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler String[] split = rawHeader.split("\r\n"); 1697dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler assertEquals("64 shouldn't fold", 1, split.length); 170961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 1717dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler // test 4: very long subject (should fold) 1727dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler message.setSubject(LONG_PLAIN_256); 1737dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler rawHeader = message.getFirstHeader("Subject"); 1747dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler split = rawHeader.split("\r\n"); 1757dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler assertTrue("long subject should fold", split.length > 1); 1767dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler for (String s : split) { 1777dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler assertTrue("split lines max length 78", s.length() <= 76); // 76+\r\n = 78 1787dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler String trimmed = s.trim(); 1797dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler assertFalse("split lines are not encoded", trimmed.startsWith("=?")); 1807dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler } 1817dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler } 182961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 1837dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler /** 1847dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler * Confirm that setSubject() works with unicode strings 1857dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler */ 1867dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler public void testSetSubject() throws MessagingException { 1877dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler MimeMessage message = new MimeMessage(); 1887dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler 1897dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler message.setSubject(SHORT_UNICODE); 190961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 1917dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler // test 1: readback in unicode 1927dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler assertEquals("unicode readback", SHORT_UNICODE, message.getSubject()); 193961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 1947dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler // test 2: raw readback is escaped 1957dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler String rawHeader = message.getFirstHeader("Subject"); 1967dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler assertEquals("raw readback", SHORT_UNICODE_ENCODED, rawHeader); 1977dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler } 198961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 1997dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler /** 2007dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler * Confirm folding operations on unicode subjects 2017dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler */ 2027dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler public void testSetLongSubject() throws MessagingException { 2037dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler MimeMessage message = new MimeMessage(); 204961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 2057dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler // test 1: long unicode - readback in unicode 2067dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler message.setSubject(LONG_UNICODE_16); 2077dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler assertEquals("unicode readback 16", LONG_UNICODE_16, message.getSubject()); 208961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 2097dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler // test 2: longer unicode (will fold) 2107dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler message.setSubject(LONG_UNICODE_64); 2117dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler assertEquals("unicode readback 64", LONG_UNICODE_64, message.getSubject()); 212961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 2137dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler // test 3: check folding & encoding 2147dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler String rawHeader = message.getFirstHeader("Subject"); 2157dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler String[] split = rawHeader.split("\r\n"); 2167dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler assertTrue("long subject should fold", split.length > 1); 2177dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler for (String s : split) { 2187dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler assertTrue("split lines max length 78", s.length() <= 76); // 76+\r\n = 78 2197dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler String trimmed = s.trim(); 220961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki assertTrue("split lines are encoded", 2217dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler trimmed.startsWith("=?") && trimmed.endsWith("?=")); 2227dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler } 2237dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler } 224961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 2257e6df9c6aa616978efa9fc8288014735f9bf7eddAndy Stadler /** 226d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler * Test for encoding address field. 227d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler */ 228d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler public void testEncodingAddressField() throws MessagingException { 229d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler Address noName1 = new Address("noname1@dom1.com"); 230d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler Address noName2 = new Address("<noname2@dom2.com>", ""); 231d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler Address simpleName = new Address("address3@dom3.org", "simple long and long long name"); 232d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler Address dquoteName = new Address("address4@dom4.org", "name,4,long long name"); 233d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler Address quotedName = new Address("bigG@dom5.net", "big \"G\""); 234d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler Address utf16Name = new Address("<address6@co.jp>", "\"\u65E5\u672C\u8A9E\""); 235d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler Address utf32Name = new Address("<address8@ne.jp>", "\uD834\uDF01\uD834\uDF46"); 236961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 237d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler MimeMessage message = new MimeMessage(); 238961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 239d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler message.setFrom(noName1); 240d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler message.setRecipient(RecipientType.TO, noName2); 241d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler message.setRecipients(RecipientType.CC, new Address[] { simpleName, dquoteName }); 242d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler message.setReplyTo(new Address[] { quotedName, utf16Name, utf32Name }); 243961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 244d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler String[] from = message.getHeader("From"); 245d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler String[] to = message.getHeader("To"); 246d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler String[] cc = message.getHeader("Cc"); 247d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler String[] replyTo = message.getHeader("Reply-to"); 248961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 249961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki assertEquals("from address count", 1, from.length); 250d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler assertEquals("no name 1", "noname1@dom1.com", from[0]); 251961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 252961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki assertEquals("to address count", 1, to.length); 253d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler assertEquals("no name 2", "noname2@dom2.com", to[0]); 254961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 255d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler // folded. 256961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki assertEquals("cc address count", 1, cc.length); 257d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler assertEquals("simple name & double quoted name", 258d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler "simple long and long long name <address3@dom3.org>, \"name,4,long long\r\n" 259d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler + " name\" <address4@dom4.org>", 260d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler cc[0]); 261961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 262d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler // folded and encoded. 263961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki assertEquals("reply-to address count", 1, replyTo.length); 264d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler assertEquals("quoted name & encoded name", 265d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler "\"big \\\"G\\\"\" <bigG@dom5.net>, =?UTF-8?B?5pel5pys6Kqe?=\r\n" 266d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler + " <address6@co.jp>, =?UTF-8?B?8J2MgfCdjYY=?= <address8@ne.jp>", 267d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler replyTo[0]); 268d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler } 269d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler 270d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler /** 271d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler * Test for parsing address field. 272d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler */ 273d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler public void testParsingAddressField() throws MessagingException { 274d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler MimeMessage message = new MimeMessage(); 275961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 276d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler message.setHeader("From", "noname1@dom1.com"); 277d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler message.setHeader("To", "<noname2@dom2.com>"); 278d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler // folded. 279d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler message.setHeader("Cc", 280d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler "simple name <address3@dom3.org>,\r\n" 281d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler + " \"name,4\" <address4@dom4.org>"); 282d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler // folded and encoded. 283961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki message.setHeader("Reply-to", 284d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler "\"big \\\"G\\\"\" <bigG@dom5.net>,\r\n" 285d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler + " =?UTF-8?B?5pel5pys6Kqe?=\r\n" 286d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler + " <address6@co.jp>,\n" 287d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler + " \"=?UTF-8?B?8J2MgfCdjYY=?=\" <address8@ne.jp>"); 288961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 289d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler Address[] from = message.getFrom(); 290d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler Address[] to = message.getRecipients(RecipientType.TO); 291d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler Address[] cc = message.getRecipients(RecipientType.CC); 292d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler Address[] replyTo = message.getReplyTo(); 293961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 294961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki assertEquals("from address count", 1, from.length); 295d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler assertEquals("no name 1 address", "noname1@dom1.com", from[0].getAddress()); 296d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler assertNull("no name 1 name", from[0].getPersonal()); 297961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 298961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki assertEquals("to address count", 1, to.length); 299d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler assertEquals("no name 2 address", "noname2@dom2.com", to[0].getAddress()); 300d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler assertNull("no name 2 name", to[0].getPersonal()); 301d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler 302961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki assertEquals("cc address count", 2, cc.length); 303d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler assertEquals("simple name address", "address3@dom3.org", cc[0].getAddress()); 304d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler assertEquals("simple name name", "simple name", cc[0].getPersonal()); 305d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler assertEquals("double quoted name address", "address4@dom4.org", cc[1].getAddress()); 306d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler assertEquals("double quoted name name", "name,4", cc[1].getPersonal()); 307d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler 308961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki assertEquals("reply-to address count", 3, replyTo.length); 309d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler assertEquals("quoted name address", "bigG@dom5.net", replyTo[0].getAddress()); 310d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler assertEquals("quoted name name", "big \"G\"", replyTo[0].getPersonal()); 311d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler assertEquals("utf-16 name address", "address6@co.jp", replyTo[1].getAddress()); 312d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler assertEquals("utf-16 name name", "\u65E5\u672C\u8A9E", replyTo[1].getPersonal()); 313d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler assertEquals("utf-32 name address", "address8@ne.jp", replyTo[2].getAddress()); 314d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler assertEquals("utf-32 name name", "\uD834\uDF01\uD834\uDF46", replyTo[2].getPersonal()); 315d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler } 316961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 317d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler /* 3187e6df9c6aa616978efa9fc8288014735f9bf7eddAndy Stadler * Test setting & getting store-specific flags 3197e6df9c6aa616978efa9fc8288014735f9bf7eddAndy Stadler */ 3207e6df9c6aa616978efa9fc8288014735f9bf7eddAndy Stadler public void testStoreFlags() throws MessagingException { 3217e6df9c6aa616978efa9fc8288014735f9bf7eddAndy Stadler MimeMessage message = new MimeMessage(); 3227e6df9c6aa616978efa9fc8288014735f9bf7eddAndy Stadler 3237e6df9c6aa616978efa9fc8288014735f9bf7eddAndy Stadler // Message should create with no flags 3247e6df9c6aa616978efa9fc8288014735f9bf7eddAndy Stadler Flag[] flags = message.getFlags(); 3257e6df9c6aa616978efa9fc8288014735f9bf7eddAndy Stadler assertEquals(0, flags.length); 3267e6df9c6aa616978efa9fc8288014735f9bf7eddAndy Stadler 3277e6df9c6aa616978efa9fc8288014735f9bf7eddAndy Stadler // Set a store flag 3287e6df9c6aa616978efa9fc8288014735f9bf7eddAndy Stadler message.setFlag(Flag.X_STORE_1, true); 3297e6df9c6aa616978efa9fc8288014735f9bf7eddAndy Stadler assertTrue(message.isSet(Flag.X_STORE_1)); 3307e6df9c6aa616978efa9fc8288014735f9bf7eddAndy Stadler assertFalse(message.isSet(Flag.X_STORE_2)); 3317e6df9c6aa616978efa9fc8288014735f9bf7eddAndy Stadler 3327e6df9c6aa616978efa9fc8288014735f9bf7eddAndy Stadler // Set another 3337e6df9c6aa616978efa9fc8288014735f9bf7eddAndy Stadler message.setFlag(Flag.X_STORE_2, true); 3347e6df9c6aa616978efa9fc8288014735f9bf7eddAndy Stadler assertTrue(message.isSet(Flag.X_STORE_1)); 3357e6df9c6aa616978efa9fc8288014735f9bf7eddAndy Stadler assertTrue(message.isSet(Flag.X_STORE_2)); 3367e6df9c6aa616978efa9fc8288014735f9bf7eddAndy Stadler 3377e6df9c6aa616978efa9fc8288014735f9bf7eddAndy Stadler // Set some and clear some 3387e6df9c6aa616978efa9fc8288014735f9bf7eddAndy Stadler message.setFlag(Flag.X_STORE_1, false); 3397e6df9c6aa616978efa9fc8288014735f9bf7eddAndy Stadler assertFalse(message.isSet(Flag.X_STORE_1)); 3407e6df9c6aa616978efa9fc8288014735f9bf7eddAndy Stadler assertTrue(message.isSet(Flag.X_STORE_2)); 3417e6df9c6aa616978efa9fc8288014735f9bf7eddAndy Stadler 3427e6df9c6aa616978efa9fc8288014735f9bf7eddAndy Stadler } 3437dbeb7d91c7b3970426af6debe48301ba053fd79Andy Stadler 344a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka /* 345a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka * Test for setExtendedHeader() and getExtendedHeader() 346a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka */ 347a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka public void testExtendedHeader() throws MessagingException { 348a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka MimeMessage message = new MimeMessage(); 349961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 350a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka assertNull("non existent header", message.getExtendedHeader("X-Non-Existent")); 351961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 352a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka message.setExtendedHeader("X-Header1", "value1"); 353a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka message.setExtendedHeader("X-Header2", "value2\n value3\r\n value4\r\n"); 354a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka assertEquals("simple value", "value1", 355a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka message.getExtendedHeader("X-Header1")); 356a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka assertEquals("multi line value", "value2 value3 value4", 357a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka message.getExtendedHeader("X-Header2")); 358a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka assertNull("non existent header 2", message.getExtendedHeader("X-Non-Existent")); 359961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 360a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka message.setExtendedHeader("X-Header1", "value4"); 361a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka assertEquals("over written value", "value4", message.getExtendedHeader("X-Header1")); 362961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 363a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka message.setExtendedHeader("X-Header1", null); 364a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka assertNull("remove header", message.getExtendedHeader("X-Header1")); 365a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka } 366961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 367a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka /* 368a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka * Test for setExtendedHeaders() and getExtendedheaders() 369a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka */ 370a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka public void testExtendedHeaders() throws MessagingException { 371a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka MimeMessage message = new MimeMessage(); 372a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka 373a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka assertNull("new message", message.getExtendedHeaders()); 374a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka message.setExtendedHeaders(null); 375a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka assertNull("null headers", message.getExtendedHeaders()); 376a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka message.setExtendedHeaders(""); 377a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka assertNull("empty headers", message.getExtendedHeaders()); 378961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 379a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka message.setExtendedHeaders("X-Header1: value1\r\n"); 380a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka assertEquals("header 1 value", "value1", message.getExtendedHeader("X-Header1")); 381a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka assertEquals("header 1", "X-Header1: value1\r\n", message.getExtendedHeaders()); 382961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 383a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka message.setExtendedHeaders(null); 384a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka message.setExtendedHeader("X-Header2", "value2"); 385a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka message.setExtendedHeader("X-Header3", "value3\n value4\r\n value5\r\n"); 386a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka assertEquals("headers 2,3", 387a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka "X-Header2: value2\r\n" + 388a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka "X-Header3: value3 value4 value5\r\n", 389a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka message.getExtendedHeaders()); 390a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka 391a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka message.setExtendedHeaders( 392a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka "X-Header3: value3 value4 value5\r\n" + 393a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka "X-Header2: value2\r\n"); 394a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka assertEquals("header 2", "value2", message.getExtendedHeader("X-Header2")); 395a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka assertEquals("header 3", "value3 value4 value5", message.getExtendedHeader("X-Header3")); 396a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka assertEquals("headers 3,2", 397a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka "X-Header3: value3 value4 value5\r\n" + 398a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka "X-Header2: value2\r\n", 399a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka message.getExtendedHeaders()); 400a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka } 401961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 402a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka /* 403a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka * Test for writeTo(), only for header part. 40444552da606048720de11f89321dc767ef291c391Andrew Stadler * NOTE: This test is fragile because it assumes headers will be written in a specific order 405a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka */ 406a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka public void testWriteToHeader() throws Exception { 407a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka MimeMessage message = new MimeMessage(); 408961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 409a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka message.setHeader("Header1", "value1"); 410a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka message.setHeader(MimeHeader.HEADER_ANDROID_ATTACHMENT_STORE_DATA, "value2"); 411a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka message.setExtendedHeader("X-Header3", "value3"); 412a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka message.setHeader("Header4", "value4"); 413a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka message.setExtendedHeader("X-Header5", "value5"); 414961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 415a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka ByteArrayOutputStream out = new ByteArrayOutputStream(); 416a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka message.writeTo(out); 417a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka out.close(); 41844552da606048720de11f89321dc767ef291c391Andrew Stadler String expectedString = 419a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka "Header1: value1\r\n" + 420a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka "Header4: value4\r\n" + 42144552da606048720de11f89321dc767ef291c391Andrew Stadler "Message-ID: " + message.getMessageId() + "\r\n" + 422a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka "\r\n"; 423a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka byte[] expected = expectedString.getBytes(); 424a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka byte[] actual = out.toByteArray(); 425a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka assertEquals("output length", expected.length, actual.length); 426a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka for (int i = 0; i < actual.length; ++i) { 427a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka assertEquals("output byte["+i+"]", expected[i], actual[i]); 428a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka } 429a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka } 430961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 4312517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn /** 4322517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn * Test for parsing headers with extra whitespace and commennts. 4332517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn * 4342517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn * The lines up to Content-Type were copied directly out of RFC 2822 4352517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn * "Section A.5. White space, comments, and other oddities" 4362517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn */ 4372517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn public void testWhiteSpace() throws MessagingException, IOException { 4382517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn String entireMessage = 4392517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn "From: Pete(A wonderful \\) chap) <pete(his account)@silly.test(his host)>\r\n"+ 4402517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn "To:A Group(Some people)\r\n"+ 4412517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn " :Chris Jones <c@(Chris's host.)public.example>,\r\n"+ 4422517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn " joe@example.org,\r\n"+ 4432517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn " John <jdoe@one.test> (my dear friend); (the end of the group)\r\n"+ 4442517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn "Cc:(Empty list)(start)Undisclosed recipients :(nobody(that I know)) ;\r\n"+ 4452517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn "Date: Thu,\r\n"+ 4462517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn " 13\r\n"+ 4472517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn " Feb\r\n"+ 4482517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn " 1969\r\n"+ 4492517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn " 23:32\r\n"+ 4502517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn " -0330 (Newfoundland Time)\r\n"+ 4512517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn "Message-ID: <testabcd.1234@silly.test>\r\n"+ 4522517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn "Content-Type: \r\n"+ 4532517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn " TEXT/hTML \r\n"+ 4542517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn " ; x-blah=\"y-blah\" ; \r\n"+ 4552517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn " CHARSET=\"us-ascii\" ; (comment)\r\n"+ 4562517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn "\r\n"+ 4572517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn "<html><body>Testing.</body></html>\r\n"; 4582517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn MimeMessage mm = null; 4592517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn mm = new MimeMessage(new ByteArrayInputStream( 4602517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn entireMessage.getBytes("us-ascii"))); 4612517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn assertTrue(mm.getMimeType(), MimeUtility.mimeTypeMatches("text/html",mm.getMimeType())); 4622517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn assertEquals(new Date(-27723480000L),mm.getSentDate()); 4632517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn assertEquals("<testabcd.1234@silly.test>",mm.getMessageId()); 4642517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn Address[] toAddresses = mm.getRecipients(MimeMessage.RecipientType.TO); 4652517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn assertEquals("joe@example.org", toAddresses[1].getAddress()); 4662517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn assertEquals("jdoe@one.test", toAddresses[2].getAddress()); 4672517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn 4682517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn 4692517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn // Note: The parentheses in the middle of email addresses are not removed. 4702517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn //assertEquals("c@public.example", toAddresses[0].getAddress()); 4712517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn //assertEquals("pete@silly.test",mm.getFrom()[0].getAddress()); 4722517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn } 4732517a3dfd15a4bdb01677fd1ed6a63645eaad3f7Patrick Horn 474961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki /** 475961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki * Confirm parser doesn't crash when seeing "Undisclosed recipients:;". 476961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki */ 477961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki public void testUndisclosedRecipients() throws MessagingException, IOException { 478961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki String entireMessage = 479961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki "To:Undisclosed recipients:;\r\n"+ 480961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki "Cc:Undisclosed recipients:;\r\n"+ 481961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki "Bcc:Undisclosed recipients:;\r\n"+ 482961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki "\r\n"; 483961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki MimeMessage mm = null; 484961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki mm = new MimeMessage(new ByteArrayInputStream( 485961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki entireMessage.getBytes("us-ascii"))); 486961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 487961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki assertEquals(0, mm.getRecipients(MimeMessage.RecipientType.TO).length); 488961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki assertEquals(0, mm.getRecipients(MimeMessage.RecipientType.CC).length); 489961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki assertEquals(0, mm.getRecipients(MimeMessage.RecipientType.BCC).length); 490961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki } 491961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 492961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki /** 493961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki * Confirm parser doesn't crash when seeing invalid headers/addresses. 494961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki */ 495961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki public void testInvalidHeaders() throws MessagingException, IOException { 496961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki String entireMessage = 497961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki "To:\r\n"+ 498961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki "Cc:!invalid!address!, a@b.com\r\n"+ 499961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki "Bcc:Undisclosed recipients;\r\n"+ // no colon at the end 500961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki "invalid header\r\n"+ 501961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki "Message-ID:<testabcd.1234@silly.test>\r\n"+ 502961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki "\r\n"+ 503961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki "Testing\r\n"; 504961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki MimeMessage mm = null; 505961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki mm = new MimeMessage(new ByteArrayInputStream( 506961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki entireMessage.getBytes("us-ascii"))); 507961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 508961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki assertEquals(0, mm.getRecipients(MimeMessage.RecipientType.TO).length); 509961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki assertEquals(1, mm.getRecipients(MimeMessage.RecipientType.CC).length); 510961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki assertEquals("a@b.com", mm.getRecipients(MimeMessage.RecipientType.CC)[0].getAddress()); 511961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki assertEquals(0, mm.getRecipients(MimeMessage.RecipientType.BCC).length); 512dfd53b0e821a6c48f128f62566066876a063fed6Andrew Stadler assertEquals("<testabcd.1234@silly.test>", mm.getMessageId()); 513dfd53b0e821a6c48f128f62566066876a063fed6Andrew Stadler } 514dfd53b0e821a6c48f128f62566066876a063fed6Andrew Stadler 515dfd53b0e821a6c48f128f62566066876a063fed6Andrew Stadler /** 516dfd53b0e821a6c48f128f62566066876a063fed6Andrew Stadler * Confirm parser w/o a message-id inhibits a local message-id from being generated 517dfd53b0e821a6c48f128f62566066876a063fed6Andrew Stadler */ 518dfd53b0e821a6c48f128f62566066876a063fed6Andrew Stadler public void testParseNoMessageId() throws MessagingException, IOException { 519dfd53b0e821a6c48f128f62566066876a063fed6Andrew Stadler String entireMessage = 520dfd53b0e821a6c48f128f62566066876a063fed6Andrew Stadler "To: user@domain.com\r\n" + 521dfd53b0e821a6c48f128f62566066876a063fed6Andrew Stadler "\r\n" + 522dfd53b0e821a6c48f128f62566066876a063fed6Andrew Stadler "Testing\r\n"; 523dfd53b0e821a6c48f128f62566066876a063fed6Andrew Stadler MimeMessage mm = null; 524dfd53b0e821a6c48f128f62566066876a063fed6Andrew Stadler mm = new MimeMessage(new ByteArrayInputStream(entireMessage.getBytes("us-ascii"))); 525dfd53b0e821a6c48f128f62566066876a063fed6Andrew Stadler 526dfd53b0e821a6c48f128f62566066876a063fed6Andrew Stadler assertNull(mm.getMessageId()); 527961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki } 528961ee151fcb7451cd17c79effdb356a5a35d547eMakoto Onuki 529128fb393e8ed613c2ce283c0bd51684af2ba444dMakoto Onuki /** 530128fb393e8ed613c2ce283c0bd51684af2ba444dMakoto Onuki * Make sure the parser accepts the "eBay style" date format. 531128fb393e8ed613c2ce283c0bd51684af2ba444dMakoto Onuki * 532128fb393e8ed613c2ce283c0bd51684af2ba444dMakoto Onuki * Messages from ebay have been seen that they use the wrong date format. 53331d9acbf0623872f9d4a2b3210b5970854b654c7Marc Blank * @see com.android.emailcommon.utility.Utility#cleanUpMimeDate 534128fb393e8ed613c2ce283c0bd51684af2ba444dMakoto Onuki */ 535128fb393e8ed613c2ce283c0bd51684af2ba444dMakoto Onuki public void testEbayDate() throws MessagingException, IOException { 536128fb393e8ed613c2ce283c0bd51684af2ba444dMakoto Onuki String entireMessage = 537128fb393e8ed613c2ce283c0bd51684af2ba444dMakoto Onuki "To:a@b.com\r\n" + 538128fb393e8ed613c2ce283c0bd51684af2ba444dMakoto Onuki "Date:Thu, 10 Dec 09 15:08:08 GMT-0700" + 539128fb393e8ed613c2ce283c0bd51684af2ba444dMakoto Onuki "\r\n" + 540128fb393e8ed613c2ce283c0bd51684af2ba444dMakoto Onuki "\r\n"; 541128fb393e8ed613c2ce283c0bd51684af2ba444dMakoto Onuki MimeMessage mm = null; 542128fb393e8ed613c2ce283c0bd51684af2ba444dMakoto Onuki mm = new MimeMessage(new ByteArrayInputStream(entireMessage.getBytes("us-ascii"))); 543128fb393e8ed613c2ce283c0bd51684af2ba444dMakoto Onuki Date actual = mm.getSentDate(); 544128fb393e8ed613c2ce283c0bd51684af2ba444dMakoto Onuki Date expected = new Date(Date.UTC(109, 11, 10, 15, 8, 8) + 7 * 60 * 60 * 1000); 545128fb393e8ed613c2ce283c0bd51684af2ba444dMakoto Onuki assertEquals(expected, actual); 546128fb393e8ed613c2ce283c0bd51684af2ba444dMakoto Onuki } 547128fb393e8ed613c2ce283c0bd51684af2ba444dMakoto Onuki 548a8884b9b72b164dfd347dab24f754bd8f7fcbd7cTadashi Takaoka // TODO more test for writeTo() 549d8cbeaf7aee0b307b96c2aa1c2a93c4c417838e2Andy Stadler} 550