View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
6    */
7   package org.mule.transport.email.functional;
8   
9   import static org.junit.Assert.assertEquals;
10  import static org.junit.Assert.assertNotNull;
11  import static org.junit.Assert.assertTrue;
12  import static org.junit.Assert.fail;
13  
14  import org.mule.DefaultMuleMessage;
15  import org.mule.api.MuleContext;
16  import org.mule.api.MuleMessage;
17  import org.mule.config.i18n.LocaleMessageHandler;
18  import org.mule.module.client.MuleClient;
19  import org.mule.tck.junit4.FunctionalTestCase;
20  import org.mule.tck.junit4.rule.DynamicPort;
21  import org.mule.transport.email.GreenMailUtilities;
22  import org.mule.transport.email.ImapConnector;
23  import org.mule.transport.email.MailProperties;
24  import org.mule.transport.email.Pop3Connector;
25  import org.mule.util.SystemUtils;
26  
27  import com.icegreen.greenmail.util.GreenMail;
28  import com.icegreen.greenmail.util.ServerSetup;
29  
30  import java.util.ArrayList;
31  import java.util.HashMap;
32  import java.util.List;
33  import java.util.Locale;
34  import java.util.Map;
35  
36  import javax.activation.CommandMap;
37  import javax.activation.MailcapCommandMap;
38  import javax.mail.Address;
39  import javax.mail.Message;
40  import javax.mail.internet.MimeMessage;
41  import javax.mail.internet.MimeMultipart;
42  
43  import org.junit.Rule;
44  
45  public abstract class AbstractEmailFunctionalTestCase extends FunctionalTestCase
46  {
47      public static final long DELIVERY_DELAY_MS = 10000;
48  
49      protected static final String CONFIG_BASE = "-functional-test.xml";
50      protected static final boolean MIME_MESSAGE = true;
51      protected static final boolean STRING_MESSAGE = false;
52  
53      protected static final String DEFAULT_EMAIL = "bob@example.com";
54      protected static final String DEFAULT_USER = "bob";
55      protected static final String DEFAULT_MESSAGE = "Test email message";
56      protected static final String DEFAULT_PASSWORD = "password";
57  
58      private String protocol;
59      private boolean isMimeMessage;
60      private int port;
61      private String configFile;
62      protected GreenMail server;
63      private String email;
64      private String user;
65      private String message;
66      private String password;
67      private String charset;
68      private boolean addAttachments;
69      protected ServerSetup setup = null;
70      // for tests which need to send emails in addition to receiving them
71      protected ServerSetup smtpSetup = null;
72      private int smtpPort;
73      private boolean addSmtp = false;
74  
75      @Rule
76      public DynamicPort dynamicPort1 = new DynamicPort("port1");
77  
78      @Rule
79      public DynamicPort dynamicPort2 = new DynamicPort("port2");
80  
81  
82      protected AbstractEmailFunctionalTestCase(boolean isMimeMessage, String protocol)
83      {
84          this(isMimeMessage, protocol, protocol + CONFIG_BASE, null, null);
85      }
86  
87      protected AbstractEmailFunctionalTestCase(boolean isMimeMessage, String protocol, Locale locale, String charset)
88      {
89          this(isMimeMessage, protocol, protocol + CONFIG_BASE, locale, charset);
90      }
91  
92      protected AbstractEmailFunctionalTestCase(boolean isMimeMessage, String protocol, String configFile)
93      {
94          this(isMimeMessage, protocol, configFile, null, null);
95      }
96  
97      protected AbstractEmailFunctionalTestCase(boolean isMimeMessage, String protocol, String configFile, boolean addSmtp)
98      {
99          this(isMimeMessage, protocol, configFile, null, null);
100         this.addSmtp = addSmtp;
101     }    
102     
103     protected AbstractEmailFunctionalTestCase(boolean isMimeMessage, String protocol, String configFile, Locale locale, String charset)
104     {
105         this(isMimeMessage, protocol, configFile,
106                 DEFAULT_EMAIL, DEFAULT_USER, (locale == null ? DEFAULT_MESSAGE : getMessage(locale)), DEFAULT_PASSWORD, charset);
107     }
108 
109     protected AbstractEmailFunctionalTestCase(boolean isMimeMessage, String protocol,
110         String configFile, String email, String user, String message, String password, String charset)
111     {
112         this.isMimeMessage = isMimeMessage;
113         this.protocol = protocol;
114         this.configFile = configFile;
115         this.email = email;
116         this.user = user;
117         this.message = message;
118         this.password = password;
119         this.charset = charset;
120     }
121 
122     @Override
123     protected String getConfigResources()
124     {
125         return configFile;
126     }
127 
128     @Override
129     protected MuleContext createMuleContext() throws Exception
130     {
131         this.port = dynamicPort1.getNumber();
132         this.smtpPort = dynamicPort2.getNumber();
133         startServer();
134         initDefaultCommandMap();
135 
136         return super.createMuleContext();
137     }
138 
139     /**
140      * This is required to make all tests work on JDK5.
141      */
142     private void initDefaultCommandMap()
143     {
144         if (SystemUtils.JAVA_VERSION_FLOAT < 1.6f)
145         {
146             MailcapCommandMap commandMap = (MailcapCommandMap) CommandMap.getDefaultCommandMap();
147             commandMap.addMailcap("application/xml;;  x-java-content-handler=com.sun.mail.handlers.text_plain");
148             commandMap.addMailcap("application/text;; x-java-content-handler=com.sun.mail.handlers.text_plain");
149             CommandMap.setDefaultCommandMap(commandMap);
150         }
151     }
152 
153     @Override
154     public void doTearDown()
155     {
156         server.stop();
157     }
158 
159     protected void doSend() throws Exception
160     {
161         Object msg;
162         if (isMimeMessage)
163         {
164             msg = GreenMailUtilities.toMessage(message, email, charset);
165         }
166         else
167         {
168             msg = message;
169         }
170 
171         MuleClient client = new MuleClient(muleContext);
172         Map<String, Object> props = null;
173         if (charset != null)
174         {
175             props = new HashMap<String, Object>();
176             props.put(MailProperties.CONTENT_TYPE_PROPERTY, "text/plain; charset=" + charset);
177         }
178         if (addAttachments)
179         {
180             MuleMessage muleMessage = new DefaultMuleMessage(msg, props, muleContext);
181             createOutboundAttachments(muleMessage);
182             client.dispatch("vm://send", muleMessage);
183         }
184         else
185         {
186             client.dispatch("vm://send", msg, props);
187         }
188 
189         server.waitForIncomingEmail(DELIVERY_DELAY_MS, 1);
190 
191         MimeMessage[] messages = server.getReceivedMessages();
192         assertNotNull("did not receive any messages", messages);
193         assertEquals("did not receive 1 mail", 1, messages.length);
194         verifyMessage(messages[0]);
195     }
196 
197     protected void verifyMessage(MimeMessage received) throws Exception
198     {
199         if (addAttachments)
200         {
201             assertTrue("Did not receive a multipart message",
202                 received.getContent() instanceof MimeMultipart);
203             verifyMessage((MimeMultipart) received.getContent());
204         }
205         else
206         {
207             assertTrue("Did not receive a message with String contents",
208                 received.getContent() instanceof String);
209             verifyMessage((String) received.getContent());
210         }
211 
212         Address[] recipients = received.getRecipients(Message.RecipientType.TO);
213         assertNotNull(recipients);
214         assertEquals("number of recipients", 1, recipients.length);
215         assertEquals("recipient", email, recipients[0].toString());
216     }
217 
218     protected void verifyMessage(MimeMultipart mimeMultipart) throws Exception
219     {
220         fail("multipart message was not expected");
221     }
222 
223     protected void verifyMessage(String receivedText)
224     {
225         // for some reason, something is adding a newline at the end of messages
226         // so we need to strip that out for comparison
227         assertEquals(message, receivedText.trim());
228     }
229 
230     protected void doRequest() throws Exception
231     {
232         assertEquals(1, server.getReceivedMessages().length);
233 
234         MuleClient client = new MuleClient(muleContext);
235         MuleMessage reply = client.request("vm://receive", RECEIVE_TIMEOUT);
236 
237         assertNotNull(reply);
238         Object payload = reply.getPayload();
239         if (isMimeMessage)
240         {
241             assertTrue("payload is " + payload.getClass().getName(), payload instanceof MimeMessage);
242             verifyMessage((MimeMessage) payload);
243         }
244         else
245         {
246             assertTrue(payload instanceof String);
247             verifyMessage((String) payload);
248         }
249     }
250 
251     private void startServer() throws Exception
252     {
253         logger.debug("starting server on port " + port);
254         
255         setup = new ServerSetup(port, null, protocol);
256         if(addSmtp)
257         {
258             smtpSetup = new ServerSetup(smtpPort, null, "smtp");
259             server = new GreenMail(new ServerSetup[]{setup, smtpSetup});
260         }
261         else
262         {
263             server = new GreenMail(setup);
264         }                
265         server.start();
266         if (protocol.startsWith(Pop3Connector.POP3) || protocol.startsWith(ImapConnector.IMAP))
267         {
268             generateAndStoreEmail();
269         }
270         logger.debug("server started for protocol " + protocol);
271     }
272 
273     /**
274      * Generates and store emails on the server.
275      *
276      * @throws Exception If there's a problem with the storing of the messages in the server.
277      */
278     protected void generateAndStoreEmail() throws Exception
279     {
280         List<MimeMessage> messages = new ArrayList<MimeMessage>();
281         messages.add(GreenMailUtilities.toMessage(message, email, charset));
282         storeEmail(messages);
283     }
284 
285     /**
286      * Helper method to store email on the server. Can be overriden by subclasses if other tests want to store
287      * a different list of messages.
288      *
289      * @param messages The list of messages to be stored.
290      * @throws Exception If there's a problem with the storing of the messages in the server.
291      */
292     protected void storeEmail(List<MimeMessage> messages) throws Exception
293     {
294         for (MimeMessage message : messages)
295         {
296             GreenMailUtilities.storeEmail(server.getManagers().getUserManager(),
297                                           email, user, password, message);
298         }
299     }
300 
301     private void stopServer()
302     {
303         server.stop();
304     }
305 
306     private static String getMessage(Locale locale)
307     {
308         return LocaleMessageHandler.getString("test-data", locale, "AbstractEmailFunctionalTestCase.getMessage", new Object[] {});
309     }
310 
311     public void setAddAttachments(boolean addAttachments)
312     {
313         this.addAttachments = addAttachments;
314     }
315 
316     private void createOutboundAttachments(MuleMessage msg) throws Exception
317     {
318         msg.addOutboundAttachment("hello", "hello", "text/plain");
319         msg.addOutboundAttachment("goodbye", "<a/>", "text/xml");
320     }
321 }