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