View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.mail;
18  
19  import java.io.File;
20  import java.io.IOException;
21  import java.net.URL;
22  import java.util.List;
23  
24  import javax.activation.DataSource;
25  import javax.activation.FileDataSource;
26  import javax.mail.internet.MimeMessage;
27  
28  import org.apache.commons.mail.mocks.MockHtmlEmailConcrete;
29  import org.apache.commons.mail.settings.EmailConfiguration;
30  import org.apache.commons.mail.util.MimeMessageParser;
31  
32  import org.junit.runner.RunWith;
33  import org.powermock.core.classloader.annotations.PrepareForTest;
34  import org.powermock.modules.junit4.PowerMockRunner;
35  
36  /**
37   * JUnit test case for HtmlEmail Class.
38   *
39   * @since 1.0
40   * @author <a href="mailto:corey.scott@gmail.com">Corey Scott</a>
41   * @version $Id: HtmlEmailTest.java 1429506 2013-01-06 12:33:56Z tn $
42   */
43  @RunWith(PowerMockRunner.class)
44  @PrepareForTest( { MockHtmlEmailConcrete.class })
45  public class HtmlEmailTest extends BaseEmailTestCase
46  {
47      /** */
48      private MockHtmlEmailConcrete email;
49  
50      /**
51       * @param name name
52       */
53      public HtmlEmailTest(String name)
54      {
55          super(name);
56      }
57  
58      @Override
59      protected void setUp() throws Exception
60      {
61          super.setUp();
62          // reusable objects to be used across multiple tests
63          this.email = new MockHtmlEmailConcrete();
64      }
65  
66      public void testGetSetTextMsg() throws EmailException
67      {
68          // ====================================================================
69          // Test Success
70          // ====================================================================
71          for (int i = 0; i < testCharsValid.length; i++)
72          {
73              this.email.setTextMsg(testCharsValid[i]);
74              assertEquals(testCharsValid[i], this.email.getTextMsg());
75          }
76  
77          // ====================================================================
78          // Test Exception
79          // ====================================================================
80          for (int i = 0; i < this.testCharsNotValid.length; i++)
81          {
82              try
83              {
84                  this.email.setTextMsg(this.testCharsNotValid[i]);
85                  fail("Should have thrown an exception");
86              }
87              catch (EmailException e)
88              {
89                  assertTrue(true);
90              }
91          }
92  
93      }
94  
95      public void testGetSetHtmlMsg() throws EmailException
96      {
97          // ====================================================================
98          // Test Success
99          // ====================================================================
100         for (int i = 0; i < testCharsValid.length; i++)
101         {
102             this.email.setHtmlMsg(testCharsValid[i]);
103             assertEquals(testCharsValid[i], this.email.getHtmlMsg());
104         }
105 
106         // ====================================================================
107         // Test Exception
108         // ====================================================================
109         for (int i = 0; i < this.testCharsNotValid.length; i++)
110         {
111             try
112             {
113                 this.email.setHtmlMsg(this.testCharsNotValid[i]);
114                 fail("Should have thrown an exception");
115             }
116             catch (EmailException e)
117             {
118                 assertTrue(true);
119             }
120         }
121 
122     }
123 
124     public void testGetSetMsg() throws EmailException
125     {
126         // ====================================================================
127         // Test Success
128         // ====================================================================
129         for (int i = 0; i < testCharsValid.length; i++)
130         {
131             this.email.setMsg(testCharsValid[i]);
132             assertEquals(testCharsValid[i], this.email.getTextMsg());
133 
134             assertTrue(
135                 this.email.getHtmlMsg().indexOf(testCharsValid[i]) != -1);
136         }
137 
138         // ====================================================================
139         // Test Exception
140         // ====================================================================
141         for (int i = 0; i < this.testCharsNotValid.length; i++)
142         {
143             try
144             {
145                 this.email.setMsg(this.testCharsNotValid[i]);
146                 fail("Should have thrown an exception");
147             }
148             catch (EmailException e)
149             {
150                 assertTrue(true);
151             }
152         }
153 
154     }
155 
156     public void testEmbedUrl() throws Exception
157     {
158         // ====================================================================
159         // Test Success
160         // ====================================================================
161 
162         String strEmbed =
163             this.email.embed(new URL(this.strTestURL), "Test name");
164         assertNotNull(strEmbed);
165         assertEquals(HtmlEmail.CID_LENGTH, strEmbed.length());
166 
167         // if we embed the same name again, do we get the same content ID
168         // back?
169         String testCid =
170             this.email.embed(new URL(this.strTestURL), "Test name");
171         assertEquals(strEmbed, testCid);
172 
173         // if we embed the same URL under a different name, is the content ID
174         // unique?
175         String newCid =
176             this.email.embed(new URL(this.strTestURL), "Test name 2");
177         assertFalse(strEmbed.equals(newCid));
178 
179         // ====================================================================
180         // Test Exceptions
181         // ====================================================================
182 
183         // Does an invalid URL throw an exception?
184         try
185         {
186             this.email.embed(createInvalidURL(), "Bad URL");
187             fail("Should have thrown an exception");
188         }
189         catch (EmailException e)
190         {
191             // expected
192         }
193 
194         // if we try to embed a different URL under a previously used name,
195         // does it complain?
196         try
197         {
198             this.email.embed(new URL("http://www.google.com"), "Test name");
199             fail("shouldn't be able to use an existing name with a different URL!");
200         }
201         catch (EmailException e)
202         {
203             // expected
204         }
205     }
206 
207     public void testEmbedFile() throws Exception
208     {
209         // ====================================================================
210         // Test Success
211         // ====================================================================
212 
213         File file = File.createTempFile("testEmbedFile", "txt");
214         file.deleteOnExit();
215         String strEmbed = this.email.embed(file);
216         assertNotNull(strEmbed);
217         assertEquals("generated CID has wrong length",
218                 HtmlEmail.CID_LENGTH, strEmbed.length());
219 
220         // if we embed the same file again, do we get the same content ID
221         // back?
222         String testCid =
223             this.email.embed(file);
224         assertEquals("didn't get same CID after embedding same file twice",
225                 strEmbed, testCid);
226 
227         // if we embed a new file, is the content ID unique?
228         File otherFile = File.createTempFile("testEmbedFile2", "txt");
229         otherFile.deleteOnExit();
230         String newCid = this.email.embed(otherFile);
231         assertFalse("didn't get unique CID from embedding new file",
232                 strEmbed.equals(newCid));
233     }
234 
235     public void testEmbedUrlAndFile() throws Exception
236     {
237         File tmpFile = File.createTempFile("testfile", "txt");
238         tmpFile.deleteOnExit();
239         String fileCid = this.email.embed(tmpFile);
240 
241         URL fileUrl = tmpFile.toURI().toURL();
242         String urlCid = this.email.embed(fileUrl, "urlName");
243 
244         assertFalse("file and URL cids should be different even for same resource",
245                 fileCid.equals(urlCid));
246     }
247 
248     public void testEmbedDataSource() throws Exception
249     {
250         File tmpFile = File.createTempFile("testEmbedDataSource", "txt");
251         tmpFile.deleteOnExit();
252         FileDataSource dataSource = new FileDataSource(tmpFile);
253 
254         // does embedding a datasource without a name fail?
255         try
256         {
257             this.email.embed(dataSource, "");
258             fail("embedding with an empty string for a name should fail");
259         }
260         catch (EmailException e)
261         {
262             // expected
263         }
264 
265         // properly embed the datasource
266         String cid = this.email.embed(dataSource, "testname");
267 
268         // does embedding the same datasource under the same name return
269         // the original cid?
270         String sameCid = this.email.embed(dataSource, "testname");
271         assertEquals("didn't get same CID for embedding same datasource twice",
272                 cid, sameCid);
273 
274         // does embedding another datasource under the same name fail?
275         File anotherFile = File.createTempFile("testEmbedDataSource2", "txt");
276         anotherFile.deleteOnExit();
277         FileDataSource anotherDS = new FileDataSource(anotherFile);
278         try
279         {
280             this.email.embed(anotherDS, "testname");
281         }
282         catch (EmailException e)
283         {
284             // expected
285         }
286     }
287 
288     /**
289      * @throws EmailException when bad addresses and attachments are used
290      * @throws IOException if creating a temp file, URL or sending fails
291      */
292     public void testSend() throws EmailException, IOException
293     {
294         EmailAttachment attachment = new EmailAttachment();
295         File testFile = null;
296 
297         /** File to used to test file attachments (Must be valid) */
298         testFile = File.createTempFile("commons-email-testfile", ".txt");
299         testFile.deleteOnExit();
300 
301         // ====================================================================
302         // Test Success
303         // ====================================================================
304         this.getMailServer();
305 
306         String strSubject = "Test HTML Send #1 Subject (w charset)";
307 
308         this.email = new MockHtmlEmailConcrete();
309         this.email.setHostName(this.strTestMailServer);
310         this.email.setSmtpPort(this.getMailServerPort());
311         this.email.setFrom(this.strTestMailFrom);
312         this.email.addTo(this.strTestMailTo);
313 
314         /** File to used to test file attachmetns (Must be valid) */
315         attachment.setName("Test Attachment");
316         attachment.setDescription("Test Attachment Desc");
317         attachment.setPath(testFile.getAbsolutePath());
318         this.email.attach(attachment);
319 
320         this.email.setAuthentication(this.strTestUser, this.strTestPasswd);
321 
322         this.email.setCharset(EmailConstants.ISO_8859_1);
323         this.email.setSubject(strSubject);
324 
325         URL url = new URL(EmailConfiguration.TEST_URL);
326         String cid = this.email.embed(url, "Apache Logo");
327 
328         String strHtmlMsg =
329             "<html>The Apache logo - <img src=\"cid:" + cid + "\"><html>";
330 
331         this.email.setHtmlMsg(strHtmlMsg);
332         this.email.setTextMsg(
333             "Your email client does not support HTML emails");
334 
335         this.email.send();
336         this.fakeMailServer.stop();
337         // validate txt message
338         validateSend(
339             this.fakeMailServer,
340             strSubject,
341             this.email.getTextMsg(),
342             this.email.getFromAddress(),
343             this.email.getToAddresses(),
344             this.email.getCcAddresses(),
345             this.email.getBccAddresses(),
346             true);
347 
348         // validate html message
349         validateSend(
350             this.fakeMailServer,
351             strSubject,
352             this.email.getHtmlMsg(),
353             this.email.getFromAddress(),
354             this.email.getToAddresses(),
355             this.email.getCcAddresses(),
356             this.email.getBccAddresses(),
357             false);
358 
359         // validate attachment
360         validateSend(
361             this.fakeMailServer,
362             strSubject,
363             attachment.getName(),
364             this.email.getFromAddress(),
365             this.email.getToAddresses(),
366             this.email.getCcAddresses(),
367             this.email.getBccAddresses(),
368             false);
369 
370         this.getMailServer();
371 
372         this.email = new MockHtmlEmailConcrete();
373         this.email.setHostName(this.strTestMailServer);
374         this.email.setSmtpPort(this.getMailServerPort());
375         this.email.setFrom(this.strTestMailFrom);
376         this.email.addTo(this.strTestMailTo);
377 
378         if (this.strTestUser != null && this.strTestPasswd != null)
379         {
380             this.email.setAuthentication(
381                 this.strTestUser,
382                 this.strTestPasswd);
383         }
384 
385         strSubject = "Test HTML Send #1 Subject (wo charset)";
386         this.email.setSubject(strSubject);
387         this.email.setTextMsg("Test message");
388 
389         this.email.send();
390         this.fakeMailServer.stop();
391         // validate txt message
392         validateSend(
393             this.fakeMailServer,
394             strSubject,
395             this.email.getTextMsg(),
396             this.email.getFromAddress(),
397             this.email.getToAddresses(),
398             this.email.getCcAddresses(),
399             this.email.getBccAddresses(),
400             true);
401     }
402 
403     public void testSend2() throws Exception
404     {
405         // ====================================================================
406         // Test Success
407         // ====================================================================
408 
409         this.getMailServer();
410 
411         this.email = new MockHtmlEmailConcrete();
412         this.email.setHostName(this.strTestMailServer);
413         this.email.setSmtpPort(this.getMailServerPort());
414         this.email.setFrom(this.strTestMailFrom);
415         this.email.addTo(this.strTestMailTo);
416 
417         if (this.strTestUser != null && this.strTestPasswd != null)
418         {
419             this.email.setAuthentication(
420                 this.strTestUser,
421                 this.strTestPasswd);
422         }
423 
424         String strSubject = "Test HTML Send #2 Subject (wo charset)";
425         this.email.setSubject(strSubject);
426         this.email.setMsg("Test txt msg");
427 
428         this.email.send();
429         this.fakeMailServer.stop();
430         // validate txt message
431         validateSend(
432             this.fakeMailServer,
433             strSubject,
434             this.email.getTextMsg(),
435             this.email.getFromAddress(),
436             this.email.getToAddresses(),
437             this.email.getCcAddresses(),
438             this.email.getBccAddresses(),
439             true);
440 
441         // validate html message
442         validateSend(
443             this.fakeMailServer,
444             strSubject,
445             this.email.getHtmlMsg(),
446             this.email.getFromAddress(),
447             this.email.getToAddresses(),
448             this.email.getCcAddresses(),
449             this.email.getBccAddresses(),
450             false);
451 
452         this.getMailServer();
453 
454         this.email = new MockHtmlEmailConcrete();
455         this.email.setHostName(this.strTestMailServer);
456         this.email.setFrom(this.strTestMailFrom);
457         this.email.setSmtpPort(this.getMailServerPort());
458         this.email.addTo(this.strTestMailTo);
459 
460         if (this.strTestUser != null && this.strTestPasswd != null)
461         {
462             this.email.setAuthentication(
463                 this.strTestUser,
464                 this.strTestPasswd);
465         }
466 
467         strSubject = "Test HTML Send #2 Subject (w charset)";
468         this.email.setCharset(EmailConstants.ISO_8859_1);
469         this.email.setSubject(strSubject);
470         this.email.setMsg("Test txt msg");
471 
472         this.email.send();
473         this.fakeMailServer.stop();
474         // validate txt message
475         validateSend(
476             this.fakeMailServer,
477             strSubject,
478             this.email.getTextMsg(),
479             this.email.getFromAddress(),
480             this.email.getToAddresses(),
481             this.email.getCcAddresses(),
482             this.email.getBccAddresses(),
483             true);
484 
485         // validate html message
486         validateSend(
487             this.fakeMailServer,
488             strSubject,
489             this.email.getHtmlMsg(),
490             this.email.getFromAddress(),
491             this.email.getToAddresses(),
492             this.email.getCcAddresses(),
493             this.email.getBccAddresses(),
494             false);
495 
496     }
497 
498     /**
499      * Create a HTML email containing an URL pointing to a ZIP file
500      * to be downloaded. According to EMAIL-93 the resulting URL
501      * "http://paradisedelivery.homeip.net/delivery/?file=TZC268X93337..zip"
502      * contains TWO dots instead of one dot which breaks the link.
503      */
504     public void testAddZipUrl() throws Exception
505     {
506         String htmlMsg =
507                 "Please click on the following link: <br><br>" +
508                 "<a href=\"http://paradisedelivery.homeip.net/delivery/?file=3DTZC268X93337.zip\">" +
509                 "http://paradisedelivery.homeip.net/delivery/?file=3DTZC268X93337.zip" +
510                 "</a><br><br>Customer satisfaction is very important for us.";
511 
512         this.getMailServer();
513 
514         this.email = new MockHtmlEmailConcrete();
515         this.email.setHostName(this.strTestMailServer);
516         this.email.setSmtpPort(this.getMailServerPort());
517         this.email.setFrom(this.strTestMailFrom);
518         this.email.addTo(this.strTestMailTo);
519         this.email.setCharset(EmailConstants.ISO_8859_1);
520 
521         if (this.strTestUser != null && this.strTestPasswd != null)
522         {
523             this.email.setAuthentication(
524                 this.strTestUser,
525                 this.strTestPasswd);
526         }
527 
528         String strSubject = "A dot (\".\") is appended to some ULRs of a HTML mail.";
529         this.email.setSubject(strSubject);
530         this.email.setHtmlMsg(htmlMsg);
531 
532         this.email.send();
533         this.fakeMailServer.stop();
534 
535         // validate html message
536         validateSend(
537             this.fakeMailServer,
538             strSubject,
539             this.email.getHtmlMsg(),
540             this.email.getFromAddress(),
541             this.email.getToAddresses(),
542             this.email.getCcAddresses(),
543             this.email.getBccAddresses(),
544             false);
545         
546         // make sure that no double dots show up
547         assertTrue(this.email.getHtmlMsg().indexOf("3DTZC268X93337.zip") >= 0);
548         assertFalse(this.email.getHtmlMsg().indexOf("3DTZC268X93337..zip") >= 0);
549     }
550 
551     /**
552      * According to EMAIL-95 calling buildMimeMessage() before calling send()
553      * causes duplicate mime parts - now we throw an exception to catch the
554      * problem
555      */
556     public void testCallingBuildMimeMessageBeforeSent() throws Exception {
557 
558         String htmlMsg = "<b>Hello World</b>";
559 
560         this.email = new MockHtmlEmailConcrete();
561         this.email.setHostName(this.strTestMailServer);
562         this.email.setSmtpPort(this.getMailServerPort());
563         this.email.setFrom(this.strTestMailFrom);
564         this.email.addTo(this.strTestMailTo);
565         this.email.setCharset(EmailConstants.ISO_8859_1);
566 
567         if (this.strTestUser != null && this.strTestPasswd != null)
568         {
569             this.email.setAuthentication(
570                 this.strTestUser,
571                 this.strTestPasswd);
572         }
573 
574         String strSubject = "testCallingBuildMimeMessageBeforeSent";
575         this.email.setSubject(strSubject);
576         this.email.setHtmlMsg(htmlMsg);
577 
578         // this should NOT be called when sending a message
579         this.email.buildMimeMessage();
580 
581         try
582         {
583             this.email.send();
584         }
585         catch(IllegalStateException e)
586         {
587             return;
588         }
589 
590         fail("Expecting an exception when calling buildMimeMessage() before send() ...");
591     }
592 
593     /**
594      * EMAIL-73 - check that providing a plain text content using setMsg()
595      * creates a plain content and HTML content using <pre> tags.
596      */
597     public void testSendWithPlainTextButNoHtmlContent() throws EmailException, IOException
598     {
599         this.getMailServer();
600 
601         String strSubject = "testSendWithPlainTextButNoHtmlContent";
602 
603         this.email = new MockHtmlEmailConcrete();
604         this.email.setHostName(this.strTestMailServer);
605         this.email.setSmtpPort(this.getMailServerPort());
606         this.email.setFrom(this.strTestMailFrom);
607         this.email.addTo(this.strTestMailTo);
608         this.email.setAuthentication(this.strTestUser, this.strTestPasswd);
609         this.email.setCharset(EmailConstants.ISO_8859_1);
610         this.email.setSubject(strSubject);
611         this.email.setMsg("This is a plain text content : <b><&npsb;></html></b>");
612 
613         this.email.send();
614 
615         this.fakeMailServer.stop();
616 
617         // validate text message
618         validateSend(
619             this.fakeMailServer,
620             strSubject,
621             this.email.getTextMsg(),
622             this.email.getFromAddress(),
623             this.email.getToAddresses(),
624             this.email.getCcAddresses(),
625             this.email.getBccAddresses(),
626             true);
627     }
628 
629     /**
630      * Test that the specified Content-ID is used when embedding a File
631      * object in an HtmlEmail.
632      *
633      * Rolled back the changes since they broke real emails therefore
634      * the test is currently disabled.
635      *
636      * see https://issues.apache.org/jira/browse/EMAIL-101
637      */
638     public void testEmbedFileWithCID() throws Exception
639     {
640          // ====================================================================
641          // Test Success
642          // ====================================================================
643 
644          File file = File.createTempFile("testEmbedFile", "txt");
645          file.deleteOnExit();
646 
647          String testCid = "Test CID";
648          String encodedCid = EmailUtils.encodeUrl(testCid);
649 
650          // if we embed a new file, do we get the content ID we specified back?
651          String strEmbed = this.email.embed(file, testCid);
652          assertNotNull(strEmbed);
653          assertEquals("didn't get same CID when embedding with a specified CID", encodedCid, strEmbed);
654 
655          // if we embed the same file again, do we get the same content ID
656          // back?
657          String returnedCid = this.email.embed(file);
658          assertEquals("didn't get same CID after embedding same file twice", encodedCid, returnedCid);
659      }
660 
661     public void testHtmlMailMimeLayout() throws Exception
662     {
663         assertCorrectContentType("contentTypeTest.gif", "image/gif");
664         assertCorrectContentType("contentTypeTest.jpg", "image/jpeg");
665         assertCorrectContentType("contentTypeTest.png", "image/png");
666     }
667 
668     private void assertCorrectContentType(String picture, String contentType) throws Exception {
669         HtmlEmail htmlEmail = createDefaultHtmlEmail();
670         String cid = htmlEmail.embed(new File("./src/test/resources/images/" + picture), "Apache Logo");
671         String htmlMsg = "<html><img src=\"cid:" + cid + "\"><html>";
672         htmlEmail.setHtmlMsg(htmlMsg);
673         htmlEmail.buildMimeMessage();
674 
675         MimeMessage mm = htmlEmail.getMimeMessage();
676         mm.saveChanges();
677         MimeMessageParser mmp = new MimeMessageParser(mm);
678         mmp.parse();
679 
680         List<?> attachments = mmp.getAttachmentList();
681         assertEquals("Attachment size", 1, attachments.size());
682 
683         DataSource ds = (DataSource) attachments.get(0);
684         assertEquals("Content type", contentType, ds.getContentType());
685     }
686 
687     private HtmlEmail createDefaultHtmlEmail() throws EmailException {
688         HtmlEmail htmlEmail = new HtmlEmail();
689         htmlEmail.setHostName(this.strTestMailServer);
690         htmlEmail.setSmtpPort(this.getMailServerPort());
691         htmlEmail.setFrom("a@b.com");
692         htmlEmail.addTo("c@d.com");
693         return htmlEmail;
694     }
695 }