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.ByteArrayOutputStream;
20  import java.io.File;
21  import java.net.URL;
22  import java.util.ArrayList;
23  import java.util.List;
24  
25  import javax.activation.DataSource;
26  import javax.activation.URLDataSource;
27  import javax.mail.Session;
28  import javax.mail.Transport;
29  import javax.mail.internet.MimeMessage;
30  
31  import org.apache.commons.io.FileUtils;
32  import org.apache.commons.io.IOUtils;
33  import org.apache.commons.mail.resolver.DataSourceUrlResolver;
34  import org.apache.commons.mail.settings.EmailConfiguration;
35  import org.junit.Before;
36  import org.junit.Test;
37  
38  /**
39   * This are regression test sending REAL email to REAL mail
40   * servers using REAL recipients.
41   *
42   * The intention is to field-test certain aspects
43   * of email using a variety of mail clients since I'm not a mockist
44   * (see http://martinfowler.com/articles/mocksArentStubs.html#ClassicalAndMockistTesting).
45   */
46  public class EmailLiveTest extends AbstractEmailTest
47  {
48      @Before
49      public void setUpLiveTest()
50      {
51          // enforce a default charset UTF-8 otherwise non-ASCII attachment names will not work
52          System.setProperty("mail.mime.charset", "utf-8");
53  
54          // enforce encoding of non-ASCII characters (violating the MIME specification - see
55          // http://java.sun.com/products/javamail/javadocs/javax/mail/internet/package-summary.html
56          System.setProperty("mail.mime.encodefilename", "true");
57      }
58  
59      protected Email send(final Email email) throws EmailException {
60  
61          if( EmailConfiguration.MAIL_FORCE_SEND ) {
62              email.send();
63          }
64          else {
65              email.buildMimeMessage();
66          }
67  
68          return email;
69      }
70  
71      protected String getFromUrl(final URL url) throws Exception {
72  
73          final URLDataSource dataSource = new URLDataSource(url);
74          final ByteArrayOutputStream baos = new ByteArrayOutputStream();
75          IOUtils.copy(dataSource.getInputStream(), baos);
76          return new String(baos.toByteArray(), "UTF-8");
77      }
78  
79      /**
80       * Factory method to create a pre-configured email instance.
81       *
82       * @param clazz the requested implementation class
83       * @return the new instance
84       * @throws Exception creating the Email instance failed
85       */
86      private Email create(final Class<? extends Email> clazz) throws Exception {
87  
88          final Email email = clazz.newInstance();
89  
90          email.setStartTLSEnabled(EmailConfiguration.MAIL_USE_STARTTLS);
91          email.setStartTLSRequired(EmailConfiguration.MAIL_STARTTLS_REQUIRED);
92          email.setSSLOnConnect(EmailConfiguration.MAIL_USE_SSL);
93          email.setSSLCheckServerIdentity(EmailConfiguration.MAIL_SSL_CHECKSERVERIDENTITY);
94          email.setHostName(EmailConfiguration.MAIL_SERVER);
95          email.setSmtpPort(EmailConfiguration.MAIL_SERVER_PORT);
96          email.setBounceAddress(EmailConfiguration.TEST_FROM);
97          email.setDebug(EmailConfiguration.MAIL_DEBUG);
98          email.setCharset(EmailConfiguration.MAIL_CHARSET);
99          email.setFrom(EmailConfiguration.TEST_FROM);
100         email.addTo(EmailConfiguration.TEST_TO);
101 
102         if(EmailConfiguration.TEST_USER != null) {
103             email.setAuthenticator(new DefaultAuthenticator(EmailConfiguration.TEST_USER, EmailConfiguration.TEST_PASSWD));
104         }
105 
106         return email;
107     }
108 
109     // ======================================================================
110     // Start of Tests
111     // ======================================================================
112 
113     /**
114      * A sanity check that a simple email also works in reality.
115      *
116      * @throws Exception the test failed
117      */
118     @Test
119     public void testSimpleEmail() throws Exception
120     {
121         final SimpleEmail email = (SimpleEmail) create(SimpleEmail.class);
122         email.setSubject("TestSimpleMail");
123         email.setMsg("This is a test mail ... :-)");
124 
125         EmailUtils.writeMimeMessage( new File("./target/test-emails/simplemail.eml"), send(email).getMimeMessage());
126     }
127 
128     /**
129      * A sanity check that a header folding works correctly.
130      *
131      * @throws Exception the test failed
132      */
133     @Test
134     public void testFoldedHeaderValue() throws Exception
135     {
136         final SimpleEmail email = (SimpleEmail) create(SimpleEmail.class);
137         email.setSubject("TestFoldedHeaderMail");
138         email.setMsg("This is a test mail with a folded header value... :-)");
139         email.addHeader("X-TestHeader", "This is a very long header value which should be folded into two lines, hopefully");
140 
141         EmailUtils.writeMimeMessage( new File("./target/test-emails/foldedheader.eml"), send(email).getMimeMessage());
142     }
143 
144     /**
145      * A sanity check that a simple email also works in reality.
146      *
147      * @throws Exception the test failed
148      */
149     @Test
150     public void testMultiPartEmail() throws Exception
151     {
152         final MultiPartEmail email = (MultiPartEmail) create(MultiPartEmail.class);
153         email.setSubject("TestMultiPartMail");
154         email.setMsg("This is a test mail ... :-)");
155         email.attach(new File("./src/test/resources/attachments/logo.pdf"));
156 
157         EmailUtils.writeMimeMessage( new File("./target/test-emails/multipart.eml"), send(email).getMimeMessage());
158     }
159 
160     /**
161      * This test checks the various options of building a HTML email.
162      *
163      * https://issues.apache.org/jira/browse/EMAIL-65
164      *
165      * @throws Exception the test failed
166      */
167     @Test
168     public void testHtmlMailMimeLayout() throws Exception
169     {
170         String textMsg;
171         String htmlMsg;
172 
173         // prepare attachments
174 
175         String cid;
176 
177         final URL url = new URL(EmailConfiguration.TEST_URL);
178         final File imageFile = new File("./src/test/resources/images/asf_logo_wide.gif");
179 
180         final EmailAttachment attachment = new EmailAttachment();
181         final File attachmentFile = new File("./src/test/resources/attachments/logo.pdf");
182         attachment.setName("logo.pdf");
183         attachment.setDescription("The official Apache logo");
184         attachment.setPath(attachmentFile.getAbsolutePath());
185 
186         // 1) text + html content
187 
188         final HtmlEmail htmlEmail1 = (HtmlEmail) create(HtmlEmail.class);
189         textMsg = "Your email client does not support HTML messages";
190         htmlMsg = "<html><b>This is a HTML message without any image</b><html>";
191 
192         htmlEmail1.setSubject( "[email] 1.Test: text + html content");
193         htmlEmail1.setTextMsg(textMsg);
194         htmlEmail1.setHtmlMsg(htmlMsg);
195 
196         EmailUtils.writeMimeMessage( new File("./target/test-emails/htmlemail1.eml"), send(htmlEmail1).getMimeMessage());
197 
198         // 2) text + html content + image as attachment
199 
200         final HtmlEmail htmlEmail2 = (HtmlEmail) create(HtmlEmail.class);
201         textMsg = "Your email client does not support HTML messages";
202         htmlMsg = "<html><b>This is a HTML message with an image attachment</b><html>";
203 
204         htmlEmail2.setSubject( "[email] 2.Test: text + html content + image as attachment");
205         htmlEmail2.setTextMsg(textMsg);
206         htmlEmail2.setHtmlMsg(htmlMsg);
207         htmlEmail2.attach(url, "Apache Logo", "The official Apache logo" );
208 
209         EmailUtils.writeMimeMessage( new File("./target/test-emails/htmlemail2.eml"), send(htmlEmail2).getMimeMessage());
210 
211         // 3) text + html content + inline image
212 
213         final HtmlEmail htmlEmail3 = (HtmlEmail) create(HtmlEmail.class);
214         textMsg = "Your email client does not support HTML messages";
215         cid = htmlEmail3.embed(imageFile, "Apache Logo");
216 
217         htmlMsg = "<html><b>This is a HTML message with an inline image - <img src=\"cid:"
218             + cid + "\"> and NO attachment</b><html>";
219 
220         htmlEmail3.setSubject( "[email] 3.Test: text + html content + inline image");
221         htmlEmail3.setTextMsg(textMsg);
222         htmlEmail3.setHtmlMsg(htmlMsg);
223 
224         EmailUtils.writeMimeMessage( new File("./target/test-emails/htmlemail3.eml"), send(htmlEmail3).getMimeMessage());
225 
226         // 4) text + html content + inline image + attachment
227 
228         final HtmlEmail htmlEmail4 = (HtmlEmail) create(HtmlEmail.class);
229         textMsg = "Your email client does not support HTML messages";
230         cid = htmlEmail4.embed(imageFile, "Apache Logo");
231         htmlMsg = "<html><b>This is a HTML message with an inline image - <img src=\"cid:" + cid + "\"> and attachment</b><html>";
232 
233         htmlEmail4.setSubject( "[email] 4.Test: text + html content + inline image + attachment");
234         htmlEmail4.setTextMsg(textMsg);
235         htmlEmail4.setHtmlMsg(htmlMsg);
236         htmlEmail4.attach(attachment);
237 
238         EmailUtils.writeMimeMessage( new File("./target/test-emails/htmlemail4.eml"), send(htmlEmail4).getMimeMessage());        
239     }
240 
241     /**
242      * This test checks the correct character encoding when sending
243      * non-ASCII content using SimpleEmail.
244      *
245      * https://issues.apache.org/jira/browse/EMAIL-79
246      *
247      * @throws Exception the test failed
248      */
249     @Test
250     public void testCorrectCharacterEncoding() throws Exception
251     {
252         // U+03B1 : GREEK SMALL LETTER ALPHA
253         // U+03B2 : GREEK SMALL LETTER BETA
254         // U+03B3 : GREEK SMALL LETTER GAMMA
255 
256         final String subject = "[email] 5.Test: Subject with three greek UTF-8 characters : \u03B1\u03B2\u03B3";
257         final String textMsg = "My test body with with three greek UTF-8 characters : \u03B1\u03B2\u03B3\n";
258         final String attachmentName = "\u03B1\u03B2\u03B3.txt";
259 
260         // make sure to set the charset before adding the message content
261         final MultiPartEmail email = (MultiPartEmail) create(MultiPartEmail.class);
262         email.setSubject(subject);
263         email.setMsg(textMsg);
264 
265         // create a proper UTF-8 sequence for the text attachment (matching our default charset)
266         final DataSource attachment = new javax.mail.util.ByteArrayDataSource(textMsg.getBytes("utf-8"), "text/plain");
267         email.attach(attachment, attachmentName, "Attachment in Greek");
268 
269         EmailUtils.writeMimeMessage( new File("./target/test-emails/correct-encoding.eml"), send(email).getMimeMessage());
270     }
271 
272     /**
273      * Test sending a image HTML mail bases on a local HTML page and local image.
274      *
275      * @throws Exception the test failed
276      */
277     @Test
278     public void testImageHtmlEmailLocal() throws Exception
279     {
280         // use a simple HTML page with one image
281 
282         final File htmlFile = new File("./src/test/resources/html/www.apache.org.html");
283         final String htmlMsg1 = FileUtils.readFileToString(htmlFile, "ISO-8859-1");
284 
285         final ImageHtmlEmail email = (ImageHtmlEmail) create(ImageHtmlEmail.class);
286         email.setDataSourceResolver(new DataSourceUrlResolver(htmlFile.getParentFile().toURI().toURL(), false));
287         email.setSubject("[testImageHtmlEmail] 1.Test: simple html content");
288         email.setHtmlMsg(htmlMsg1);
289 
290         EmailUtils.writeMimeMessage( new File("./target/test-emails/testImageHtmlEmailLocal.eml"), send(email).getMimeMessage());
291     }
292 
293     /**
294      * Test sending a image HTML mail based on a real world website. We
295      * would expect to see the ApacheCon logo at the bottom of the email.
296      * Please note that not all major email clients can display the email
297      * properly.
298      *
299      * @throws Exception the test failed
300      */
301     @Test
302     public void testImageHtmlEmailRemote() throws Exception
303     {
304         if(EmailConfiguration.MAIL_FORCE_SEND)
305         {
306             final URL url = new URL("http://commons.apache.org/email/");
307             // URL url = new URL("http://www.dzone.com/links/index.html");
308             final String htmlMsg = getFromUrl(url);
309 
310             final ImageHtmlEmail email = (ImageHtmlEmail) create(ImageHtmlEmail.class);
311             email.setDataSourceResolver(new DataSourceUrlResolver(url, true));
312             email.setSubject("[testImageHtmlEmail] 2.Test: complex html content");
313             email.setHtmlMsg(htmlMsg);
314 
315             EmailUtils.writeMimeMessage( new File("./target/test-emails/testImageHtmlEmailRemote.eml"), send(email).getMimeMessage());
316         }
317     }
318 
319     /**
320      * Testing if we are able to send a few emails in a batch, i.e.
321      * using a single authenticated <code>Transport</code> instance.
322      * Use a single instance speeds up processing since the
323      * authorization is only done once.
324      *
325      * https://issues.apache.org/jira/browse/EMAIL-72
326      *
327      * @throws Exception the test failed.
328      */
329     @Test
330     public void testSendingEmailsInBatch() throws Exception
331     {
332         final List<SimpleEmail> emails = new ArrayList<SimpleEmail>();
333 
334         // we need to instantiate an email to provide the mail session - a bit ugly
335         final Session session = create(SimpleEmail.class).getMailSession();
336         final Transport transport = session.getTransport();
337 
338         // simulate creating a bunch of emails using an existing mail session
339         for(int i = 0; i<3; i++)
340         {
341             final SimpleEmail personalizedEmail = (SimpleEmail) create(SimpleEmail.class);
342             personalizedEmail.setMailSession(session);
343             personalizedEmail.setSubject("Personalized Test Mail Nr. " + i);
344             personalizedEmail.setMsg("This is a personalized test mail ... :-)");
345             personalizedEmail.buildMimeMessage();
346             emails.add(personalizedEmail);
347         }
348 
349         // send the list of emails using a single 'Transport' instance.
350         if( EmailConfiguration.MAIL_FORCE_SEND )
351         {
352             transport.connect();
353 
354             for (final SimpleEmail personalizedEmail : emails)
355             {
356                 final MimeMessage mimeMessage = personalizedEmail.getMimeMessage();
357                 Transport.send(mimeMessage);
358                 System.out.println("Successfully sent the following email : " + mimeMessage.getMessageID());
359             }
360 
361             transport.close();
362          }
363     }
364 
365     /**
366      * Testing if we are able to send a partial email with an invalid address.
367      *
368      * https://issues.apache.org/jira/browse/EMAIL-132
369      *
370      * @throws Exception the test failed.
371      */
372     @Test
373     public void testPartialSend() throws Exception
374     {
375         final SimpleEmail email = (SimpleEmail) create(SimpleEmail.class);
376         email.addTo(EmailConfiguration.TEST_TO);
377         email.addTo("nobody@is.invalid");
378         email.setSubject("TestPartialMail");
379         email.setMsg("This is a test mail ... :-)");
380 
381         email.setSendPartial(true);
382 
383         EmailUtils.writeMimeMessage( new File("./target/test-emails/partialmail.eml"), send(email).getMimeMessage());
384     }
385 
386 }