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