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 static org.junit.Assert.*;
20  
21  import org.apache.commons.io.FileUtils;
22  import org.apache.commons.io.IOUtils;
23  import org.apache.commons.mail.resolver.DataSourceClassPathResolver;
24  import org.apache.commons.mail.resolver.DataSourceCompositeResolver;
25  import org.apache.commons.mail.resolver.DataSourceUrlResolver;
26  import org.apache.commons.mail.mocks.MockImageHtmlEmailConcrete;
27  import org.apache.commons.mail.util.MimeMessageParser;
28  import org.apache.commons.mail.util.MimeMessageUtils;
29  import org.junit.Before;
30  import org.junit.Test;
31  
32  import javax.activation.DataSource;
33  import javax.mail.internet.MimeMessage;
34  
35  import java.io.File;
36  import java.io.IOException;
37  import java.io.InputStream;
38  import java.net.URL;
39  import java.util.List;
40  import java.util.logging.Level;
41  import java.util.logging.Logger;
42  import java.util.regex.Matcher;
43  import java.util.regex.Pattern;
44  
45  public class ImageHtmlEmailTest extends HtmlEmailTest {
46  
47      private static final boolean TEST_IS_LENIENT = true;
48      private static final URL TEST_IMAGE_URL = ImageHtmlEmailTest.class.getResource("/images/asf_logo_wide.gif");
49      private static final File TEST_IMAGE_DIR = new File(TEST_IMAGE_URL.getPath()).getParentFile();
50      private static final URL TEST_HTML_URL = ImageHtmlEmailTest.class.getResource("/attachments/download_email.cgi.html");
51      private static final URL TEST2_HTML_URL = ImageHtmlEmailTest.class.getResource("/attachments/classpathtest.html");
52  
53      private MockImageHtmlEmailConcrete email;
54  
55      @Before
56      public void setupImageHtmlEmailTest() {
57          // reusable objects to be used across multiple tests
58          email = new MockImageHtmlEmailConcrete();
59      }
60  
61      // ======================================================================
62      // Start of Tests
63      // ======================================================================
64  
65      @Test
66      public void testSendHtml() throws Exception {
67  
68          Logger.getLogger(ImageHtmlEmail.class.getName()).setLevel(Level.FINEST);
69  
70          // Create the email message
71          getMailServer();
72  
73          final String strSubject = "Test HTML Send default";
74  
75          email = new MockImageHtmlEmailConcrete();
76          email.setDataSourceResolver(new DataSourceUrlResolver(TEST_IMAGE_DIR.toURI().toURL(), TEST_IS_LENIENT));
77          email.setHostName(strTestMailServer);
78          email.setSmtpPort(getMailServerPort());
79          email.setFrom(strTestMailFrom);
80          email.addTo(strTestMailTo);
81          email.setSubject(strSubject);
82  
83          final String html = loadUrlContent(TEST_HTML_URL);
84  
85          // set the html message
86          email.setHtmlMsg(html);
87  
88          // set the alternative message
89          email.setTextMsg("Your email client does not support HTML messages");
90  
91          // send the email
92          email.send();
93  
94          fakeMailServer.stop();
95  
96          assertEquals(1, fakeMailServer.getMessages().size());
97          final MimeMessage mimeMessage = fakeMailServer.getMessages().get(0).getMimeMessage();
98  
99          final MimeMessageParser mimeMessageParser = new MimeMessageParser(mimeMessage).parse();
100         assertTrue(mimeMessageParser.getHtmlContent().contains("\"cid:"));
101         assertTrue(mimeMessageParser.getAttachmentList().size() == 3);
102     }
103 
104     @Test
105     public void testSendEmptyHTML() throws Exception {
106         Logger.getLogger(ImageHtmlEmail.class.getName()).setLevel(Level.FINEST);
107 
108         // Create the email message
109         final ImageHtmlEmail email = new ImageHtmlEmail();
110 
111         // set the html message
112         try {
113             email.setHtmlMsg(null);
114             fail("Should fail here!");
115         } catch (final EmailException e) {
116             assertTrue(e.getMessage(), e.getMessage().contains("Invalid message supplied"));
117         }
118     }
119 
120     @Test
121     public void testSendEmptyHTML2() throws Exception {
122         Logger.getLogger(ImageHtmlEmail.class.getName()).setLevel(Level.FINEST);
123 
124         // Create the email message
125         final ImageHtmlEmail email = new ImageHtmlEmail();
126 
127         // set the html message
128         try {
129             email.setHtmlMsg("");
130             fail("Should fail here!");
131         } catch (final EmailException e) {
132             assertTrue(e.getMessage(), e.getMessage().contains("Invalid message supplied"));
133         }
134 
135     }
136 
137     @Test
138     public void testSendHtmlUrl() throws Exception {
139         Logger.getLogger(ImageHtmlEmail.class.getName()).setLevel(Level.FINEST);
140 
141         getMailServer();
142 
143         final String strSubject = "Test HTML Send default with URL";
144 
145         // Create the email message
146         email = new MockImageHtmlEmailConcrete();
147         email.setHostName(strTestMailServer);
148         email.setSmtpPort(getMailServerPort());
149         email.setFrom(strTestMailFrom);
150         email.addTo(strTestMailTo);
151         email.setSubject(strSubject);
152         email.setDataSourceResolver(new DataSourceUrlResolver(TEST_IMAGE_DIR.toURI().toURL(), TEST_IS_LENIENT));
153 
154         // set the html message
155         email.setHtmlMsg(
156                 "<html><body><img src=\"http://www.apache.org/images/feather.gif\"/></body></html>"
157         );
158 
159         // send the email
160         email.send();
161 
162         fakeMailServer.stop();
163         // validate txt message
164         validateSend(fakeMailServer, strSubject, email.getHtmlMsg(),
165                 email.getFromAddress(), email.getToAddresses(),
166                 email.getCcAddresses(), email.getBccAddresses(), true);
167     }
168 
169     @Test
170     public void testSendHTMLAbsoluteLocalFile() throws Exception {
171         Logger.getLogger(ImageHtmlEmail.class.getName()).setLevel(Level.FINEST);
172 
173         // Create the email message
174         getMailServer();
175 
176         final String strSubject = "Test HTML Send default with absolute local path";
177 
178         // Create the email message
179         email = new MockImageHtmlEmailConcrete();
180         email.setHostName(strTestMailServer);
181         email.setSmtpPort(getMailServerPort());
182         email.setFrom(strTestMailFrom);
183         email.addTo(strTestMailTo);
184         email.setSubject(strSubject);
185         email.setDataSourceResolver(new DataSourceUrlResolver(TEST_IMAGE_DIR.toURI().toURL(), TEST_IS_LENIENT));
186 
187         final File file = File.createTempFile("emailtest", ".tst");
188         FileUtils.writeStringToFile(file,
189                 "just some silly data that we won't be able to display anyway");
190 
191         // set the html message
192         email.setHtmlMsg("<html><body><img src=\"" + file.getAbsolutePath()
193                 + "\"/></body></html>"
194         );
195 
196         // send the email
197         email.send();
198 
199         fakeMailServer.stop();
200         // validate txt message
201         validateSend(fakeMailServer, strSubject, email.getHtmlMsg(),
202                 email.getFromAddress(), email.getToAddresses(),
203                 email.getCcAddresses(), email.getBccAddresses(), true);
204     }
205 
206     @Test
207     public void testSendHTMLClassPathFile() throws Exception {
208         Logger.getLogger(ImageHtmlEmail.class.getName()).setLevel(Level.FINEST);
209 
210         // Create the email message
211         getMailServer();
212 
213         final String strSubject = "Test HTML Send default";
214 
215         email = new MockImageHtmlEmailConcrete();
216         email.setDataSourceResolver(new DataSourceClassPathResolver("/", TEST_IS_LENIENT));
217         email.setHostName(strTestMailServer);
218         email.setSmtpPort(getMailServerPort());
219         email.setFrom(strTestMailFrom);
220         email.addTo(strTestMailTo);
221         email.setSubject(strSubject);
222 
223         final String html = loadUrlContent(TEST2_HTML_URL);
224 
225         // set the html message
226         email.setHtmlMsg(html);
227 
228         // set the alternative message
229         email.setTextMsg("Your email client does not support HTML messages");
230 
231         // send the email
232         email.send();
233 
234         fakeMailServer.stop();
235 
236         assertEquals(1, fakeMailServer.getMessages().size());
237         final MimeMessage mimeMessage = fakeMailServer.getMessages().get(0).getMimeMessage();
238         MimeMessageUtils.writeMimeMessage(mimeMessage, new File("./target/test-emails/testSendHTMLClassPathFile.eml"));
239 
240         final MimeMessageParser mimeMessageParser = new MimeMessageParser(mimeMessage).parse();
241         assertTrue(mimeMessageParser.getHtmlContent().contains("\"cid:"));
242         assertTrue(mimeMessageParser.getAttachmentList().size() == 1);
243     }
244 
245     @Test
246     public void testSendClassPathFileWithNullName() throws Exception {
247         Logger.getLogger(ImageHtmlEmail.class.getName()).setLevel(Level.FINEST);
248 
249         // Create the email message
250         getMailServer();
251 
252         final String strSubject = "Test HTML Send default";
253 
254         email = new MockImageHtmlEmailConcrete();
255         email.setDataSourceResolver(new MockDataSourceClassPathResolver("/", TEST_IS_LENIENT));
256         email.setHostName(strTestMailServer);
257         email.setSmtpPort(getMailServerPort());
258         email.setFrom(strTestMailFrom);
259         email.addTo(strTestMailTo);
260         email.setSubject(strSubject);
261 
262         final String html = loadUrlContent(TEST2_HTML_URL);
263 
264         // set the html message
265         email.setHtmlMsg(html);
266 
267         // set the alternative message
268         email.setTextMsg("Your email client does not support HTML messages");
269 
270         // send the email
271         email.send();
272 
273         fakeMailServer.stop();
274 
275         assertEquals(1, fakeMailServer.getMessages().size());
276         final MimeMessage mimeMessage = fakeMailServer.getMessages().get(0).getMimeMessage();
277         MimeMessageUtils.writeMimeMessage(mimeMessage,
278                 new File("./target/test-emails/testSendClassPathFileWithNullName.eml"));
279 
280         final MimeMessageParser mimeMessageParser = new MimeMessageParser(mimeMessage).parse();
281         assertTrue(mimeMessageParser.getHtmlContent().contains("\"cid:"));
282         assertTrue(mimeMessageParser.getAttachmentList().size() == 1);
283     }
284 
285     @Test
286     public void testSendHTMLAutoResolveFile() throws Exception {
287         Logger.getLogger(ImageHtmlEmail.class.getName()).setLevel(Level.FINEST);
288 
289         // Create the email message
290         getMailServer();
291 
292         final String strSubject = "Test HTML Send default";
293 
294         email = new MockImageHtmlEmailConcrete();
295         final DataSourceResolver dataSourceResolvers[] = new DataSourceResolver[2];
296         dataSourceResolvers[0] = new DataSourceUrlResolver(new URL("http://foo"), true);
297         dataSourceResolvers[1] = new DataSourceClassPathResolver("/", true);
298 
299         email.setDataSourceResolver(new DataSourceCompositeResolver(dataSourceResolvers));
300         email.setHostName(strTestMailServer);
301         email.setSmtpPort(getMailServerPort());
302         email.setFrom(strTestMailFrom);
303         email.addTo(strTestMailTo);
304         email.setSubject(strSubject);
305 
306         final String html = loadUrlContent(TEST2_HTML_URL);
307 
308         // set the html message
309         email.setHtmlMsg(html);
310 
311         // set the alternative message
312         email.setTextMsg("Your email client does not support HTML messages");
313 
314         // send the email
315         email.send();
316 
317         fakeMailServer.stop();
318 
319         assertEquals(1, fakeMailServer.getMessages().size());
320         final MimeMessage mimeMessage = fakeMailServer.getMessages().get(0).getMimeMessage();
321         MimeMessageUtils.writeMimeMessage(mimeMessage, new File("./target/test-emails/testSendHTMLAutoFile.eml"));
322 
323         final MimeMessageParser mimeMessageParser = new MimeMessageParser(mimeMessage).parse();
324         assertTrue(mimeMessageParser.getHtmlContent().contains("\"cid:"));
325         assertTrue(mimeMessageParser.getAttachmentList().size() == 1);
326     }
327 
328     @Test
329     public void testSendHTMLAutoResolveMultipleFiles() throws Exception {
330         Logger.getLogger(ImageHtmlEmail.class.getName()).setLevel(Level.FINEST);
331 
332         // Create the email message
333         getMailServer();
334 
335         final String strSubject = "Test HTML Send default";
336 
337         email = new MockImageHtmlEmailConcrete();
338         final DataSourceResolver dataSourceResolver = new DataSourceClassPathResolver("/", true);
339 
340         email.setDataSourceResolver(dataSourceResolver);
341         email.setHostName(strTestMailServer);
342         email.setSmtpPort(getMailServerPort());
343         email.setFrom(strTestMailFrom);
344         email.addTo(strTestMailTo);
345         email.setSubject(strSubject);
346 
347         final String html = "<p>First image  <img src=\"images/contentTypeTest.gif\"/></p>" +
348                       "<p>Second image <img src=\"images/contentTypeTest.jpg\"/></p>" +
349                       "<p>Third image  <img src=\"images/contentTypeTest.png\"/></p>";
350 
351         // set the html message
352         email.setHtmlMsg(html);
353 
354         // set the alternative message
355         email.setTextMsg("Your email client does not support HTML messages");
356 
357         // send the email
358         email.send();
359 
360         fakeMailServer.stop();
361 
362         assertEquals(1, fakeMailServer.getMessages().size());
363         final MimeMessage mimeMessage = fakeMailServer.getMessages().get(0).getMimeMessage();
364         MimeMessageUtils.writeMimeMessage(mimeMessage, new File("./target/test-emails/testSendHTMLAutoMultipleFiles.eml"));
365 
366         final MimeMessageParser mimeMessageParser = new MimeMessageParser(mimeMessage).parse();
367         assertTrue(mimeMessageParser.getHtmlContent().contains("\"cid:"));
368         assertTrue(mimeMessageParser.getAttachmentList().size() == 3);
369     }
370 
371     @Test
372     public void testRegex() {
373         final Pattern pattern = Pattern.compile(ImageHtmlEmail.REGEX_IMG_SRC);
374 
375         // ensure that the regex that we use is catching the cases correctly
376         Matcher matcher = pattern
377                 .matcher("<html><body><img src=\"h\"/></body></html>");
378         assertTrue(matcher.find());
379         assertEquals("h", matcher.group(2));
380 
381         matcher = pattern
382                 .matcher("<html><body><img id=\"laskdasdkj\" src=\"h\"/></body></html>");
383         assertTrue(matcher.find());
384         assertEquals("h", matcher.group(2));
385 
386         // uppercase
387         matcher = pattern
388                 .matcher("<html><body><IMG id=\"laskdasdkj\" SRC=\"h\"/></body></html>");
389         assertTrue(matcher.find());
390         assertEquals("h", matcher.group(2));
391 
392         // matches twice
393         matcher = pattern
394                 .matcher("<html><body><img id=\"laskdasdkj\" src=\"http://dstadler1.org/\"/><img id=\"laskdasdkj\" src=\"http://dstadler2.org/\"/></body></html>");
395         assertTrue(matcher.find());
396         assertEquals("http://dstadler1.org/", matcher.group(2));
397         assertTrue(matcher.find());
398         assertEquals("http://dstadler2.org/", matcher.group(2));
399 
400         // what about newlines
401         matcher = pattern
402                 .matcher("<html><body><img\n \rid=\"laskdasdkj\"\n \rsrc=\"http://dstadler1.org/\"/><img id=\"laskdasdkj\" src=\"http://dstadler2.org/\"/></body></html>");
403         assertTrue(matcher.find());
404         assertEquals("http://dstadler1.org/", matcher.group(2));
405         assertTrue(matcher.find());
406         assertEquals("http://dstadler2.org/", matcher.group(2));
407 
408         // what about newlines and other whitespaces
409         matcher = pattern
410                 .matcher("<html><body><img\n \t\rid=\"laskdasdkj\"\n \rsrc \n =\r  \"http://dstadler1.org/\"/><img  \r  id=\" laskdasdkj\"    src    =   \"http://dstadler2.org/\"/></body></html>");
411         assertTrue(matcher.find());
412         assertEquals("http://dstadler1.org/", matcher.group(2));
413         assertTrue(matcher.find());
414         assertEquals("http://dstadler2.org/", matcher.group(2));
415 
416         // what about some real markup
417         matcher = pattern.matcher("<img alt=\"Chart?ck=xradar&amp;w=120&amp;h=120&amp;c=7fff00|7fff00&amp;m=4&amp;g=0\" src=\"/chart?ck=xradar&amp;w=120&amp;h=120&amp;c=7fff00|7fff00&amp;m=4&amp;g=0.2&amp;l=A,C,S,T&amp;v=3.0,3.0,2.0,2.0\"");
418         assertTrue(matcher.find());
419         assertEquals("/chart?ck=xradar&amp;w=120&amp;h=120&amp;c=7fff00|7fff00&amp;m=4&amp;g=0.2&amp;l=A,C,S,T&amp;v=3.0,3.0,2.0,2.0", matcher.group(2));
420 
421         // had a problem with multiple img-source tags
422         matcher = pattern
423                 .matcher("<img src=\"file1\"/><img src=\"file2\"/>");
424         assertTrue(matcher.find());
425         assertEquals("file1", matcher.group(2));
426         assertTrue(matcher.find());
427         assertEquals("file2", matcher.group(2));
428 
429         matcher = pattern
430                 .matcher("<img src=\"file1\"/><img src=\"file2\"/><img src=\"file3\"/><img src=\"file4\"/><img src=\"file5\"/>");
431         assertTrue(matcher.find());
432         assertEquals("file1", matcher.group(2));
433         assertTrue(matcher.find());
434         assertEquals("file2", matcher.group(2));
435         assertTrue(matcher.find());
436         assertEquals("file3", matcher.group(2));
437         assertTrue(matcher.find());
438         assertEquals("file4", matcher.group(2));
439         assertTrue(matcher.find());
440         assertEquals("file5", matcher.group(2));
441 
442         // try with invalid HTML that is seems sometimes, i.e. without closing "/" or "</img>"
443         matcher = pattern.matcher("<img src=\"file1\"><img src=\"file2\">");
444         assertTrue(matcher.find());
445         assertEquals("file1", matcher.group(2));
446         assertTrue(matcher.find());
447         assertEquals("file2", matcher.group(2));
448     }
449 
450     @Test
451     public void testEmail127() throws Exception {
452         Logger.getLogger(ImageHtmlEmail.class.getName()).setLevel(Level.FINEST);
453 
454         getMailServer();
455 
456         final String strSubject = "Test HTML Send default with URL";
457 
458         // Create the email message
459         email = new MockImageHtmlEmailConcrete();
460         email.setHostName(strTestMailServer);
461         email.setSmtpPort(getMailServerPort());
462         email.setFrom(strTestMailFrom);
463         email.addTo(strTestMailTo);
464         email.setSubject(strSubject);
465         email.setDataSourceResolver(new DataSourceUrlResolver(TEST_IMAGE_DIR.toURI().toURL(), TEST_IS_LENIENT));
466 
467         // set the html message
468         email.setHtmlMsg("<html><body><img title=\"$\" src=\"http://www.apache.org/images/feather.gif\"/></body></html>");
469 
470         // send the email
471         email.send();
472 
473         fakeMailServer.stop();
474         // validate txt message
475         validateSend(fakeMailServer, strSubject, email.getHtmlMsg(),
476                      email.getFromAddress(), email.getToAddresses(),
477                      email.getCcAddresses(), email.getBccAddresses(), true);
478     }
479     
480     private String loadUrlContent(final URL url) throws IOException {
481         final InputStream stream = url.openStream();
482         final StringBuilder html = new StringBuilder();
483         try {
484             final List<String> lines = IOUtils.readLines(stream);
485             for (final String line : lines) {
486                 html.append(line).append("\n");
487             }
488         } finally {
489             stream.close();
490         }
491         return html.toString();
492     }
493     
494     private static final class MockDataSourceClassPathResolver extends DataSourceClassPathResolver {
495 
496         public MockDataSourceClassPathResolver(final String classPathBase, final boolean lenient) {
497             super(classPathBase, lenient);
498         }
499 
500         @Override
501         public DataSource resolve(String resourceLocation, boolean isLenient) throws IOException {
502             javax.mail.util.ByteArrayDataSource ds =
503                     (javax.mail.util.ByteArrayDataSource) super.resolve(resourceLocation, isLenient);
504             ds.setName(null);
505             return ds;
506         }
507         
508     }
509 }