1   /**
2    * Created by IntelliJ IDEA.
3    * User: Edwin
4    * Date: Dec 5, 2002
5    * Time: 5:59:17 PM
6    * To change this template use Options | File Templates.
7    */
8   package test.atlassian.mail;
9   
10  import com.atlassian.core.ofbiz.test.AbstractOFBizTestCase;
11  import com.atlassian.core.ofbiz.test.UtilsForTests;
12  import com.atlassian.core.user.UserUtils;
13  import com.atlassian.mail.MailUtils;
14  import com.opensymphony.user.DuplicateEntityException;
15  import com.opensymphony.user.ImmutableException;
16  import com.opensymphony.user.User;
17  import org.apache.commons.io.IOUtils;
18  import test.mock.mail.MockMessage;
19  
20  import java.io.ByteArrayInputStream;
21  import java.io.FileNotFoundException;
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.util.ArrayList;
25  import java.util.Collection;
26  import java.util.List;
27  import java.util.Properties;
28  import javax.activation.DataHandler;
29  import javax.mail.Address;
30  import javax.mail.BodyPart;
31  import javax.mail.Message;
32  import javax.mail.MessagingException;
33  import javax.mail.Multipart;
34  import javax.mail.Part;
35  import javax.mail.Session;
36  import javax.mail.internet.AddressException;
37  import javax.mail.internet.InternetAddress;
38  import javax.mail.internet.MimeBodyPart;
39  import javax.mail.internet.MimeMessage;
40  import javax.mail.internet.MimeMultipart;
41  import javax.mail.internet.NewsAddress;
42  
43  public class TestMailUtils extends AbstractOFBizTestCase
44  {
45      private User testuser;
46  
47      public TestMailUtils(String s)
48      {
49          super(s);
50      }
51  
52      protected void setUp() throws Exception
53      {
54          super.setUp();
55          testuser = UserUtils.createUser("test user", "password", "test@atlassian.com", "test user fullname");
56      }
57  
58      protected void tearDown() throws Exception
59      {
60          UtilsForTests.cleanUsers();
61  
62          super.tearDown();
63      }
64  
65  	//MAIL-49
66  	public void testGetAttachmentWithMissingDisposition() throws MessagingException, IOException
67  	{
68  		MimeMessage msg = new MimeMessage(Session.getDefaultInstance(new Properties()));
69  		MimeMultipart content = new MimeMultipart();
70  
71  		BodyPart text = new MimeBodyPart();
72  		text.setText("this is a text");
73  		content.addBodyPart(text);
74  
75  		MimeBodyPart attachmentPart = new MimeBodyPart();
76          attachmentPart.setDataHandler(new DataHandler("testing", "text/plain"));
77  		attachmentPart.addHeader("Content-Type", "text/plain;\n" +
78  				"\tname=\"text.txt\"");
79  		content.addBodyPart(attachmentPart);
80  		msg.setContent(content);
81  
82  		MailUtils.Attachment[] attachments = MailUtils.getAttachments(msg);
83  		assertEquals(1, attachments.length);
84  		assertEquals("text.txt", attachments[0].getFilename());		
85  	}
86  
87      public void testEmptyBodyPart() throws MessagingException
88      {
89          MimeMessage msg = new MimeMessage(Session.getDefaultInstance(new Properties()));
90  
91          MimeMultipart multi = new MimeMultipart();
92          BodyPart plainText = new MimeBodyPart();
93          BodyPart deliveryStatus = new MimeBodyPart();
94  
95          plainText.setText("test");
96          deliveryStatus.setHeader("Content-Type","text/plain" );
97  
98          multi.addBodyPart(plainText);
99          multi.addBodyPart(deliveryStatus);
100 
101         msg.setContent(multi);
102         msg.saveChanges();
103 
104         String body = MailUtils.getBody(msg);
105         assertEquals("test", body);
106     }
107 
108     public void testParseAddresses() throws AddressException
109     {
110         InternetAddress[] addresses = MailUtils.parseAddresses("edwin@atlassian.com, mike@atlassian.com, owen@atlassian.com");
111 
112         assertEquals(new InternetAddress("edwin@atlassian.com"), addresses[0]);
113         assertEquals(new InternetAddress("mike@atlassian.com"), addresses[1]);
114         assertEquals(new InternetAddress("owen@atlassian.com"), addresses[2]);
115     }
116 
117     public void testGetBody() throws MessagingException, IOException
118     {
119         testGetBodyWithContentType("text/plain");
120     }
121     
122     public void testGetBodyWithDifferentContentTypes() throws MessagingException, IOException
123     {
124         testGetBodyWithContentType("TEXT/PLAIN");
125         testGetBodyWithContentType("tExt/plAIN");
126 
127         testGetBodyWithContentType("text/html");
128         testGetBodyWithContentType("text/HTML");
129         testGetBodyWithContentType("TEXT/HTML");
130     }
131 
132     private void testGetBodyWithContentType(final String contentType) throws MessagingException
133     {
134         Message msg = new MimeMessage(null, new ByteArrayInputStream("test".getBytes()));
135         msg.setContent("test message", "");
136         msg.setHeader("Content-Type", contentType);
137         assertEquals("test message", MailUtils.getBody(msg));
138 
139         msg.setContent(new Integer(1), contentType);
140         assertNull(MailUtils.getBody(msg));
141     }
142 
143     public void testGetAuthorFromSender() throws MessagingException, ImmutableException, DuplicateEntityException
144     {
145         Message msg = new MimeMessage(null, new ByteArrayInputStream("test".getBytes()));
146         assertNull(MailUtils.getAuthorFromSender(msg));
147 
148         msg.setFrom(new InternetAddress("edwin@atlassian.com"));
149         assertNull(MailUtils.getAuthorFromSender(msg));
150 
151         msg.setFrom(new InternetAddress("test@atlassian.com"));
152         assertNotNull(MailUtils.getAuthorFromSender(msg));
153         assertEquals(testuser, MailUtils.getAuthorFromSender(msg));
154     }
155 
156     public void testGetFirstValidUser() throws ImmutableException, DuplicateEntityException, AddressException
157     {
158         Address[] blankaddresslist = { };
159         assertNull(MailUtils.getFirstValidUser(blankaddresslist));
160 
161         Address[] nouseraddresslist = { new InternetAddress("edwin@atlassian.com"), new InternetAddress("owen@atlassian.coM") };
162         assertNull(MailUtils.getFirstValidUser(nouseraddresslist));
163 
164         Address[] addresslist = { new InternetAddress("mike@atlassian.com"), new InternetAddress("test@atlassian.com") };
165         assertNotNull(MailUtils.getFirstValidUser(addresslist));
166         assertEquals(testuser, MailUtils.getFirstValidUser(addresslist));
167     }
168 
169     /**
170      * Creating edge cases for this test is difficult because the mail api
171      * tries to stop you doing funky things with nulls, blanks and padded
172      * values for addresses. This looks like the 80% coverage with 20% effort.
173      *
174      * @throws Exception
175      */
176     public void testGetSenders() throws Exception
177     {
178         Address[] blankaddresslist = { };
179 
180         Message msg = createMockMessageWithSenders(blankaddresslist);
181         assertEquals(0, MailUtils.getSenders(msg).size());
182 
183         // make a mock message that will return a null in the from address list
184         Address[] allNulls = { null, null };
185         msg = createMockMessageWithSenders(allNulls);
186         assertEquals(0, MailUtils.getSenders(msg).size());
187 
188         // check mixed bad with one good address list
189         String goodAddress = "good@address.com";
190         Address[] oneGood = { null, new InternetAddress(goodAddress) };
191         msg = createMockMessageWithSenders(oneGood);
192         List senders = MailUtils.getSenders(msg);
193         assertEquals(1, senders.size());
194         assertEquals(goodAddress, senders.get(0));
195 
196         // check mixed bag of types, nulls and a padded duplicate
197         Address[] mixedBag = {
198                 new InternetAddress(goodAddress),
199                 new NewsAddress(),
200                 null,
201                 new InternetAddress("  " + goodAddress) };
202         msg = createMockMessageWithSenders(mixedBag);
203         senders = MailUtils.getSenders(msg);
204         assertEquals(2, senders.size());
205         // should have two the same (trimmed)
206         assertEquals(goodAddress, senders.get(0));
207         assertEquals(goodAddress, senders.get(1));
208     }
209 
210     private Message createMockMessageWithSenders(final Address[] addresses) throws MessagingException
211     {
212         Message msg = new MockMessage()
213         {
214 
215             public Address[] getFrom() throws MessagingException
216             {
217                 return addresses;
218             }
219         };
220         return msg;
221     }
222 
223 
224     public void testHasRecipient() throws MessagingException
225     {
226         Message msg = new MimeMessage(null, new ByteArrayInputStream("test".getBytes()));
227         assertTrue(!MailUtils.hasRecipient("edwin@atlassian.com", msg));
228         msg.addRecipient(javax.mail.Message.RecipientType.TO, new InternetAddress("edwin@atlassian.com"));
229         assertTrue(MailUtils.hasRecipient("edwin@atlassian.com", msg));
230     }
231 
232     public void testCreateAttachmentMimeBodyPartFileNames() throws MessagingException
233     {
234         MimeBodyPart mbp = MailUtils.createAttachmentMimeBodyPart("C:/test/foo/bar/export.zip");
235         assertEquals("export.zip", mbp.getFileName());
236     }
237 
238     public void testCreateAttachmentMimeBodyPartFileNames2() throws MessagingException
239     {
240         MimeBodyPart mbp = MailUtils.createAttachmentMimeBodyPart("C:\\test\\foo\\bar\\export.zip");
241         assertEquals("export.zip", mbp.getFileName());
242     }
243 
244     public void testGetBodyText() throws MessagingException
245     {
246         assertEquals("This is a simple test mail, which isn't in HTML and has no attachments.",
247                 MailUtils.getBody(makeMessageFromResourceFile("/testmails/simplebody.txt")));
248     }
249 
250     public void testGetBodyTextIfContentEncodingUnsupported() throws MessagingException
251     {
252         assertEquals("This is a simple test mail, which isn't in HTML and has no attachments.",
253                      MailUtils.getBody(makeMessageFromResourceFile("/testmails/simplebodyunsupportedencoding.txt")));
254     }
255 
256     public void testGetBodyHtml() throws MessagingException
257     {
258         assertEquals("This is an HTML test mail\nwith a linebreak.",
259                 MailUtils.getBody(makeMessageFromResourceFile("/testmails/simplehtml.txt")));
260     }
261 
262     public void testGetBodyMultipartAlternativeGetsTextMatch() throws MessagingException
263     {
264         assertEquals("This is the text part of the mail",
265                 MailUtils.getBody(makeMessageFromResourceFile("/testmails/multipart.txt")));
266     }
267 
268     public void testGetBodyMultipartGetsFirstTextMatch() throws MessagingException
269     {
270         assertEquals("This is the first part",
271                 MailUtils.getBody(makeMessageFromResourceFile("/testmails/multipartbothtext.txt")));
272     }
273 
274     public void testGetBodyMultipartGetsHtmlIfNoText() throws MessagingException
275     {
276         assertEquals("This is\nthe HTML part of the mail",
277                 MailUtils.getBody(makeMessageFromResourceFile("/testmails/multipartnotext.txt")));
278     }
279 
280     public void testGetBodyMultipartNoMatch() throws MessagingException
281     {
282         assertEquals("", MailUtils.getBody(makeMessageFromResourceFile("/testmails/multipartnobody.txt")));
283     }
284 
285     public void testGetBodyMultipartMixed() throws MessagingException
286     {
287         assertEquals("Text alternative", MailUtils.getBody(makeMessageFromResourceFile("/testmails/multipartmixedotherorder.txt")));
288     }
289 
290     public void testGetBodyMultipartMixedWithLotsOfTextAndHtml() throws MessagingException
291     {
292         assertEquals("Text alternative\nThis is the first part after the alternative\nThis is the second part after the alternative",
293                 MailUtils.getBody(makeMessageFromResourceFile("/testmails/multipartmixedtextandhtml.txt")));
294     }
295 
296     public void testGetAttachmentsNoAttachments() throws MessagingException, IOException
297     {
298         assertEquals("no attachments", 0,
299                 MailUtils.getAttachments(makeMessageFromResourceFile("/testmails/multipart.txt")).length);
300     }
301 
302     public void testGetAttachmentsIfContentEncodingIsNotSupported() throws MessagingException, IOException
303     {
304         Message message = makeMessageFromResourceFile("/testmails/multipartunsupportedencoding.txt");
305         assertEquals("This is the text part of the mail", MailUtils.getBody(message));
306         assertEquals("no attachments", 0,
307                      MailUtils.getAttachments(message).length);
308     }
309 
310     public void testGetAttachmentsHasAttachments() throws MessagingException, IOException
311     {
312         MailUtils.Attachment[] attachments = MailUtils.getAttachments(makeMessageFromResourceFile("/testmails/multipartmixed.txt"));
313         assertEquals("has attachments", 2, attachments.length);
314         assertEquals("Attachment 1", new String(attachments[0].getContents()));
315         assertEquals("image/jpeg", attachments[0].getContentType().substring(0, 10));
316         assertEquals("bugger.jpg", attachments[0].getFilename());
317         assertEquals("html<br>attachment", new String(attachments[1].getContents()));
318         assertEquals("text/html", attachments[1].getContentType().substring(0, 9));
319         assertEquals("foo.html", attachments[1].getFilename());
320     }
321 
322     private Message makeMessageFromResourceFile(String resourceName) throws MessagingException
323     {
324         return new MimeMessage(null, this.getClass().getResourceAsStream(resourceName));
325     }
326 
327 
328     public void testGetContentTypeFromHeaderValue()
329     {
330         final String input = "text/plain";
331         final String actual = MailUtils.getContentType(input);
332         final String expected = input;
333 
334         assertEquals(expected, actual);
335     }
336 
337     public void testGetContentTypeFromHeaderValueWithParameter()
338     {
339         final String input = "text/plain; something=somevalue";
340         final String actual = MailUtils.getContentType(input);
341         final String expected = "text/plain";
342 
343         assertEquals(expected, actual);
344     }
345 
346     /**
347      * A simplistic attempt at a enum safe pattern. Use these constnats to make the checkParts invocations
348      * more englishlike and readable.
349      */
350     final static boolean PLAIN_TEXT_YES = true;
351     final static boolean PLAIN_TEXT_NO = false;
352 
353     final static boolean HTML_YES = true;
354     final static boolean HTML_NO = false;
355 
356     final static boolean INLINE_YES = true;
357     final static boolean INLINE_NO = false;
358 
359     final static boolean ATTACHMENT_YES = true;
360     final static boolean ATTACHMENT_NO = false;
361 
362     public void testIsPlainTextPart() throws Exception
363     {
364         this.checkParts("OutlookPlainText.msg", PLAIN_TEXT_YES, HTML_YES, INLINE_NO, ATTACHMENT_NO);
365     }
366 
367     public void testIsHtmlPart() throws Exception
368     {
369         this.checkParts("OutlookHtml.msg", PLAIN_TEXT_YES, HTML_YES, INLINE_NO, ATTACHMENT_NO);
370     }
371 
372     public void testIsImageAttachedPart() throws Exception
373     {
374         this.checkParts("OutlookHtmlImageAttached.msg", PLAIN_TEXT_YES, HTML_YES, INLINE_NO, ATTACHMENT_YES);
375     }
376 
377     public void testIsInlineImagePart() throws Exception
378     {
379         this.checkParts("OutlookHtmlInlineImage.msg", PLAIN_TEXT_YES, HTML_YES, INLINE_YES, ATTACHMENT_NO);
380     }
381 
382     public void testIsInlineImagePartWherePartHasDisposition() throws Exception
383     {
384         this.checkParts("ThunderbirdHtmlAndPlainTextInlineImage.msg", PLAIN_TEXT_YES, HTML_YES, INLINE_YES, ATTACHMENT_NO);
385     }
386 
387     public void testIsAttachmentPart() throws Exception
388     {
389         this.checkParts("OutlookHtmlBinaryAttachment.msg", PLAIN_TEXT_YES, HTML_YES, INLINE_NO, ATTACHMENT_YES);
390     }
391 
392     public void testIsRelatedPart() throws Exception
393     {
394         assertFalse(MailUtils.isPartRelated(makeMessageFromResourceFile("/testmails/multipartmixedtextandhtml.txt")));
395         assertTrue(MailUtils.isPartRelated(makeMessageFromResourceFile("/testmails/multipartrelated.txt")));
396     }
397 
398     /**
399      * The mail method which firstly creates a message from a message file.
400      * After that all the parts present are tested against the predicates passed in as the boolean parameters. Eg if plainTextPresent is set to false
401      * and a plain text part is found by MailUtils.isPartPlainText() then it will complain. Its got other smarts to make sure the XXXPresent parameters
402      * match what was found.
403      *
404      * @param filename
405      * @param plainTextExpected
406      * @param htmlExpected
407      * @param inlineExpected
408      * @param attachmentExpected
409      * @throws Exception
410      */
411     void checkParts(final String filename, final boolean plainTextExpected, final boolean htmlExpected, final boolean inlineExpected, final boolean attachmentExpected)
412             throws Exception
413     {
414         assertNotNull(filename);
415 
416         final Part[] parts = this.createPartsFromMessage(filename);
417         assertNotNull("parts", parts);
418         assertTrue("Expected atleast 1 part but got " + parts.length + " part(s)", parts.length > 0);
419 
420         // testing time...
421         boolean plainTextFound = false;
422         boolean htmlFound = false;
423         boolean inlineFound = false;
424         boolean attachmentFound = false;
425 
426         for (int i = 0; i < parts.length; i++)
427         {
428             final Part part = parts[i];
429 
430             if (MailUtils.isPartPlainText(part))
431             {
432                 assertTrue("PlainText part found when none was expected", plainTextExpected);
433                 plainTextFound = true;
434                 continue;
435             }
436 
437             if (MailUtils.isPartHtml(part))
438             {
439                 assertTrue("Html part found when none was expected", htmlExpected);
440                 htmlFound = true;
441             }
442 
443             if (MailUtils.isPartInline(part))
444             {
445                 assertTrue("Inline part found when none was expected", inlineExpected);
446                 inlineFound = true;
447 
448                 final boolean reportedEmpty = MailUtils.isContentEmpty(part);
449                 assertFalse("All inline parts in the prepared msg files are never empty...", reportedEmpty);
450             }
451 
452             if (MailUtils.isPartAttachment(part))
453             {
454                 assertTrue("Attachment part found when none was expected", attachmentExpected);
455                 attachmentFound = true;
456 
457                 final boolean reportedEmpty = MailUtils.isContentEmpty(part);
458                 assertFalse("All attachments parts in the prepared msg files are never empty...", reportedEmpty);
459             }
460         }
461 
462         assertEquals("Expected to find a plain text part but one was not found", plainTextExpected, plainTextFound);
463         assertEquals("Expected to find a html part but one was not found", htmlExpected, htmlFound);
464         assertEquals("Expected to find a inline part but one was not found", inlineExpected, inlineFound);
465         assertEquals("Expected to find a attachment part but one was not found", attachmentExpected, attachmentFound);
466     }
467 
468     /**
469      * Nice little method that creates an array of parts after creating a new message from a *.msg file.
470      * Any multiparts are traversed until to grab their parts.
471      *
472      * @param filename The test msg to load.
473      * @return An array of parts.
474      * @throws Exception
475      */
476     Part[] createPartsFromMessage(final String filename) throws Exception
477     {
478         assertNotNull(filename);
479 
480         InputStream fis = null;
481 
482         try
483         {
484             fis = getTestEmailFile(filename);
485 
486             // build a message...
487             final Message message = new MimeMessage(Session.getDefaultInstance(new Properties()), fis);
488             final Part[] parts = this.getAllParts(message);
489             assertNotNull("parts", parts);
490             assertTrue("Expected atleast 1 part but got " + parts.length + " part(s)", parts.length > 0);
491 
492             return parts;
493         }
494         finally
495         {
496             IOUtils.closeQuietly(fis);
497         }
498     }
499 
500     private InputStream getTestEmailFile(String filename) throws FileNotFoundException
501     {
502         // try it as a class resource
503         return getClass().getResourceAsStream("/testmails/" + filename);
504     }
505 
506     /**
507      * This method along with its helpers returns all parts that contain content other than Multiparts( they are continuously
508      * expanded until the raw parts are located). All these parts are placed into an array and returned.
509      *
510      * @param message The message
511      * @return An array of parts nb, no MultiParts will be in here...
512      * @throws Exception only because javamail does...
513      */
514     Part[] getAllParts(final Message message) throws Exception
515     {
516         final List partsList = new ArrayList();
517         this.processMessageParts(message, partsList);
518         final Part[] parts = (Part[]) partsList.toArray(new Part[0]);
519         return parts;
520     }
521 
522     void processMessageParts(final Message message, final Collection parts) throws Exception
523     {
524         final Object content = message.getContent();
525         this.handlePartOrContent(content, parts);
526     }
527 
528     void handlePartOrContent(final Object partOrContent, final Collection parts) throws Exception
529     {
530         if (partOrContent instanceof Multipart)
531         {
532             this.processMultipartParts((Multipart) partOrContent, parts);
533             return;
534         }
535 
536         if (partOrContent instanceof BodyPart)
537         {
538             final BodyPart bodyPart = (BodyPart) partOrContent;
539             final Object bodyPartContent = bodyPart.getContent();
540 
541             if (bodyPartContent instanceof Multipart)
542             {
543                 this.handlePartOrContent(bodyPartContent, parts);
544             }
545             else
546             {
547                 parts.add(bodyPart);
548             }
549             return;
550         }
551         parts.add((Part) partOrContent);
552     }
553 
554     void processMultipartParts(final Multipart multipart, final Collection parts) throws Exception
555     {
556         final int partsCount = multipart.getCount();
557         for (int i = 0; i < partsCount; i++)
558         {
559             final BodyPart bodyPart = multipart.getBodyPart(i);
560             this.handlePartOrContent(bodyPart, parts);
561         }
562     }
563 
564 
565     static final String X_PKCS7_SIGNATURE = "application/x-pkcs7-signature";
566 
567     public void testPositivePartIsSignature() throws Exception
568     {
569         final Message message = createMessageWithAttachment(X_PKCS7_SIGNATURE, "attachment", "filename", "xxxx");
570         final boolean actual = MailUtils.isPartSignaturePKCS7(message);
571         assertTrue("The message being tested is of \"" + X_PKCS7_SIGNATURE + "\" but MailUtils returned false instead of true", actual);
572     }
573 
574     public void testNegativePartIsSignature() throws Exception
575     {
576         final Message message = createMessageWithAttachment("text/plain", "", null, "xxxx");
577         final boolean actual = MailUtils.isPartSignaturePKCS7(message);
578         assertFalse("The message being tested is of \"" + X_PKCS7_SIGNATURE + "\" but MailUtils returned true for a text/plain when it should have returned false.", actual);
579     }
580 
581     public void testTextPartContentIsEmpty() throws Exception
582     {
583         final Message message = createMessageWithAttachment("text/plain", "", null, "");
584         final boolean actual = MailUtils.isContentEmpty(message);
585         assertTrue("The plaintext message contains a part that should be empty.", actual);
586     }
587 
588 
589     public void testTextPartContentIsEmptyOnNullContent() throws Exception
590     {
591         final Message message = createMessageWithAttachment("text/plain", "", null, (String) null);
592         final boolean actual = MailUtils.isContentEmpty(message);
593         assertTrue("The plaintext message contains a part that should be empty.", actual);
594     }
595 
596     public void testTextPartContentIsEmptyBecauseContainsOnlyWhitespace() throws Exception
597     {
598         final Message message = createMessageWithAttachment("text/plain", "", null, "   ");
599         final boolean actual = MailUtils.isContentEmpty(message);
600         assertTrue("The plaintext message contains a part that should be empty.", actual);
601     }
602 
603     public void testBinaryAttachmentPartContentIsEmpty() throws Exception
604     {
605         final Message message = createMessageWithAttachment("binary/octet-stream", "file.bin", Part.ATTACHMENT, new byte[0]);
606         final boolean actual = MailUtils.isContentEmpty(message);
607         assertTrue("The attachment part should be empty.", actual);
608     }
609 
610     public void testBinaryAttachmentPartContentIsNotEmpty() throws Exception
611     {
612         final Message message = createMessageWithAttachment("binary/octet-stream", "file.bin", Part.ATTACHMENT, " NOT EMPTY!!!  ".getBytes());
613         final boolean actual = MailUtils.isContentEmpty(message);
614         assertFalse("The attachment part should be empty.", actual);
615     }
616 
617     public void testInlineAttachment() throws Exception
618     {
619         final Message message = createMessageWithAttachment("image/jpeg", "image.jpeg", Part.INLINE, " NOT EMPTY!!!  ".getBytes());
620         final boolean actual = MailUtils.isPartInline(message);
621         assertFalse("The attachment part is an inline part.", actual);
622     }
623 
624     /**
625      * This test tests the oddf case where a part has a content-id but is not base64 encoded(aka binary) and therefore
626      * fails to be recognised as a probable inline part.
627      *
628      * @throws Exception
629      */
630     public void testInlineAttachmentThatIsntBase64Encoded() throws Exception
631     {
632         final Message message = createMessageWithAttachment("image/jpeg", "image.jpeg", null, " NOT EMPTY!!!  ".getBytes());
633         message.setHeader("Content-ID", "1234567890");
634         final boolean actual = MailUtils.isPartInline(message);
635         assertFalse("The attachment part isnt not base64 encoded.", actual);
636     }
637 
638     /**
639      * Helper which creates a message with a part with the given disposition, filename and content etc.
640      *
641      * @param mimeType
642      * @param disposition
643      * @param filename
644      * @param content
645      * @return
646      * @throws Exception
647      */
648     Message createMessageWithAttachment(final String mimeType, final String disposition, final String filename, final String content)
649             throws Exception
650     {
651         assertNotNull("mimeType", mimeType);
652         assertTrue("mimeType must not be empty", mimeType.length() > 0);
653 
654         final Message message = new MimeMessage(Session.getDefaultInstance(new Properties()));
655         message.setContent(content, mimeType);
656         if (null != filename && filename.length() > 0)
657         {
658             message.setFileName(filename);
659         }
660         message.setHeader("Content-Type", mimeType);
661         message.setDisposition(disposition);
662         return message;
663     }
664 
665     Message createMessageWithAttachment(final String mimeType, final String disposition, final String filename, final byte[] content)
666             throws Exception
667     {
668         assertNotNull("mimeType", mimeType);
669         assertTrue("mimeType must not be empty", mimeType.length() > 0);
670 
671         final Message message = new MimeMessage(Session.getDefaultInstance(new Properties()));
672         message.setContent(new ByteArrayInputStream(content), mimeType);
673         if (null != filename && filename.length() > 0)
674         {
675             message.setFileName(filename);
676         }
677         message.setHeader("Content-Type", mimeType);
678         message.setDisposition(disposition);
679         return message;
680     }
681 }