1   /*
2    * Created by IntelliJ IDEA.
3    * User: owen
4    * Date: Nov 25, 2002
5    * Time: 9:20:50 AM
6    * CVS Revision: $Revision: 1.10 $
7    * Last CVS Commit: $Date: 2004/01/06 05:43:19 $
8    * Author of last CVS Commit: $Author: dloeng $
9    * To change this template use Options | File Templates.
10   */
11  package test.atlassian.mail.server;
12  
13  import com.atlassian.mail.Email;
14  import com.atlassian.mail.MailException;
15  import com.atlassian.mail.MailUtils;
16  import com.atlassian.mail.server.SMTPMailServer;
17  import com.atlassian.mail.server.impl.SMTPMailServerImpl;
18  import com.sun.mail.util.PropUtil;
19  import org.junit.Before;
20  import org.junit.Test;
21  import org.junit.runner.RunWith;
22  import org.mockito.ArgumentCaptor;
23  import org.powermock.api.mockito.PowerMockito;
24  import org.powermock.core.classloader.annotations.PrepareForTest;
25  import org.powermock.modules.junit4.PowerMockRunner;
26  import test.mock.mail.server.MockSMTPMailServer;
27  
28  import javax.mail.Address;
29  import javax.mail.Message;
30  import javax.mail.MessagingException;
31  import javax.mail.Multipart;
32  import javax.mail.NoSuchProviderException;
33  import javax.mail.Session;
34  import javax.mail.Transport;
35  import javax.mail.URLName;
36  import javax.mail.internet.AddressException;
37  import javax.mail.internet.InternetAddress;
38  import javax.mail.internet.MimeBodyPart;
39  import javax.mail.internet.MimeMessage;
40  import javax.mail.internet.MimeMultipart;
41  import javax.naming.NamingException;
42  
43  import java.io.IOException;
44  import java.util.Properties;
45  
46  import static org.junit.Assert.assertArrayEquals;
47  import static org.junit.Assert.assertEquals;
48  import static org.junit.Assert.assertFalse;
49  import static org.junit.Assert.assertNotNull;
50  import static org.junit.Assert.assertTrue;
51  import static org.junit.Assert.fail;
52  import static org.mockito.AdditionalMatchers.aryEq;
53  import static org.mockito.Matchers.eq;
54  import static org.mockito.Mockito.mock;
55  import static org.mockito.Mockito.verify;
56  import static org.mockito.Mockito.when;
57  
58  /**
59   *
60   * Mails are basically sent by the thisSession.getTransport("smtp").send() method in the SMTPMailServerImpl class
61   *
62   * Now uses Mockito to mock the Transpoirt and  Session objects
63   *
64   */
65  @RunWith(PowerMockRunner.class)
66  @PrepareForTest({Session.class, PropUtil.class})
67  public class TestSMTPMailServer
68  {
69  
70      private Session mockSession;
71      private Transport mockTransport;
72  
73  
74      @Before
75      public void setupMockSessionAndTransport() throws NoSuchProviderException {
76          mockSession = PowerMockito.mock(Session.class);
77          PowerMockito.mockStatic(PropUtil.class);
78          when(PropUtil.getBooleanSessionProperty(mockSession, "mail.mime.address.strict", true)).thenReturn(false);
79          mockTransport = mock(Transport.class);
80          when(mockSession.getTransport("smtp")).thenReturn(mockTransport);
81      }
82  
83      @Test
84      public void testConstructor()
85      {
86          SMTPMailServer sms = new SMTPMailServerImpl(new Long(1), "name", "desc", "owen@atlassian.com", "[OWEN]", false, "mail.atlassian.com", "ofellows", "owen01");
87          assertEquals("Expected from","owen@atlassian.com", sms.getDefaultFrom());
88          assertEquals("Expected prefix", "[OWEN]", sms.getPrefix());
89          assertFalse("Expected the mail server not to be a session server", sms.isSessionServer());
90      }
91  
92  
93      @Test
94      public void testGetsSets()
95      {
96          SMTPMailServer sms = new SMTPMailServerImpl(new Long(1), "name", "desc", "", "", false, "mail.atlassian.com", "ofellows", "owen01");
97          sms.setDefaultFrom("owen@atlassian.com");
98          assertEquals("Expected default from to be owen@atlassian.com","owen@atlassian.com", sms.getDefaultFrom());
99          sms.setPrefix("[OWEN]");
100         assertEquals("Expected prefix to be [OWEN]", "[OWEN]", sms.getPrefix());
101         sms.setSessionServer(true);
102         assertTrue(sms.isSessionServer());
103     }
104 
105     @Test
106     public void testGetSessionNoUser() throws NamingException, MailException
107     {
108         SMTPMailServer sms = new SMTPMailServerImpl(new Long(1), "name", "desc", "owen@atlassian.com", "[OWEN]", false, "mail.atlassian.com", null, null);
109         assertNotNull(sms.getSession());
110     }
111 
112     @Test
113     public void testGetSessionWithUser() throws NamingException, MailException
114     {
115 
116 
117         // just for this test case we want SMTPMailServerImpl.getSession() functionality, combined with the
118         // getAuthenticator from SMTPMailServer (in order to return a MockAuthenticator for this tests)
119         SMTPMailServer sms = new SMTPMailServerImpl(new Long(1), "name", "desc", "owen@atlassian.com", "[OWEN]", false, "mail.atlassian.com", "ofellows", "owen01");
120         Session session = sms.getSession();
121         assertNotNull(session);
122         assertEquals("ofellows", session.getPasswordAuthentication(new URLName("smtp", "mail.atlassian.com", 25, null, null, null)).getUserName());
123         assertEquals("owen01", session.getPasswordAuthentication(new URLName("smtp", "mail.atlassian.com", 25, null, null, null)).getPassword());
124     }
125 
126     @Test
127     public void testSend() throws NamingException, MessagingException, AddressException, MailException, IOException {
128 
129         MimeMessage expectedMessage = setupExpectedMessage("owen@atlassian.com", "scott@atlassian.com", "mike@atlassian.con", "james@atlassian.com", "[OWEN] Test Subject", "Test Body", "text/plain");
130 
131         SMTPMailServer mockSmtpMailServer = new MockSMTPMailServer(new Long(1), "name", "desc", "owen@atlassian.com", "[OWEN]", false, "mail.atlassian.com", "ofellows", "owen01", mockSession);
132         Address[] expectedDestinations = new Address[] {new InternetAddress("scott@atlassian.com"), new InternetAddress("mike@atlassian.com"), new InternetAddress("james@atlassian.com")};
133 
134         Email email = new Email("scott@atlassian.com").setSubject("Test Subject").setBody("Test Body").setBcc("james@atlassian.com").setCc("mike@atlassian.com").setFrom("owen@atlassian.com");
135         mockSmtpMailServer.send(email);
136         verifySentMessage(mockTransport, expectedMessage, expectedDestinations);
137     }
138 
139 
140     @Test
141     public void testSendWithAttachment() throws NamingException, MessagingException, AddressException, MailException, IOException
142     {
143         SMTPMailServer mockSmtpMailServer = new MockSMTPMailServer(new Long(1), "name", "desc", "owen@atlassian.com", "[OWEN]", false, "mail.atlassian.com", "ofellows", "owen01", mockSession);
144 
145         Multipart multipart = new MimeMultipart();
146 
147         MimeBodyPart exportZip = MailUtils.createAttachmentMimeBodyPart("C:/export.zip");
148         MimeBodyPart logTxt = MailUtils.createAttachmentMimeBodyPart("C:/log.txt");
149         multipart.addBodyPart(exportZip);
150         multipart.addBodyPart(logTxt);
151 
152         // create the message part and add to multipart
153         MimeBodyPart messageBodyPart = new MimeBodyPart();
154         messageBodyPart.setText("Test Body", "text/plain");
155 
156         multipart.addBodyPart(messageBodyPart);
157 
158         MimeMessage expectedMessage = setupExpectedMessage("owen@atlassian.com", "scott@atlassian.com", "mike@atlassian.com", null, "[OWEN] Test Subject", multipart, null);
159 
160         // remove body part from the multipart constructed and pass into send method where it will be added back
161         multipart.removeBodyPart(messageBodyPart);
162 
163         try
164         {
165             Email email = new Email("scott@atlassian.com").setCc("mike@atlassian.com").setSubject("Test Subject").setBody("Test Body").setFrom("owen@atlassian.com").setMultipart(multipart);
166             mockSmtpMailServer.send(email);
167         }
168         catch (Exception e)
169         {
170             fail();
171         }
172 
173         verifySentMessage(mockTransport, expectedMessage, new InternetAddress[]{new InternetAddress("scott@atlassian.com"), new InternetAddress("mike@atlassian.com") });
174     }
175 
176 
177     /**
178      * Test case to verify JRA-1436
179      */
180     @Test
181     public void testGetJNDIServer() throws NamingException, MailException
182     {
183         final javax.mail.Session sessionInstance = javax.mail.Session.getInstance(new Properties(), null);
184 
185         SMTPMailServer sms = new SMTPMailServerImpl(new Long(1), "name", "desc", "owen@atlassian.com", "[OWEN]", true, "mail.atlassian.com", null, null)
186         {
187             protected Object getJndiSession() throws NamingException
188             {
189                 return sessionInstance;
190             }
191         };
192 
193         Session session = sms.getSession();
194         assertEquals(sessionInstance, session);
195 
196     }
197 
198     /**
199      * Test that if the class at the specified jndi location is not of the correct type, that an illegalargument
200      * exception is thrown.
201      */
202     @Test
203     public void testIncorrectJndiClass() throws NamingException, MailException
204     {
205         SMTPMailServer sms = new SMTPMailServerImpl(new Long(1), "name", "desc", "owen@atlassian.com", "[OWEN]", true, "mail.atlassian.com", null, null)
206         {
207             protected Object getJndiSession() throws NamingException
208             {
209                 return new Object();
210             }
211         };
212 
213         try
214         {
215             sms.getSession();
216             fail("Expected IllegalArgumentException when wrong class type in jdni location");
217         }
218         catch (IllegalArgumentException e)
219         {
220             //this is what we want
221         }
222     }
223 
224     /**
225      * Following tests moved over from TestMailFactory (since all send methods have been removed from there
226      */
227 
228     @Test
229     public void testSendFail() throws Exception
230     {
231         SMTPMailServer mailServer = new SMTPMailServerImpl(null, "default", "", "", "", false, "mail.atlassian.com", "", "");
232         try
233         {
234             Email email = new Email("mike@atlassian.com").setSubject("Test Subject").setBody("Test Body");
235             mailServer.send(email);
236             fail();
237         }
238         catch (MailException e)
239         {
240             assertEquals("Tried to send mail (Test Subject) from no one (no 'from' and 'default from' specified).", e.getMessage());
241         }
242     }
243 
244     @Test
245     public void testSendMail1() throws Exception
246     {
247 
248         SMTPMailServer mockSMTPMailServer = new MockSMTPMailServer(new Long(-1), "default", "", "owen@atlassian.com", "", false, "mail.atlassian.com", "", "", mockSession);
249 
250         MimeMessage expectedMessage = setupExpectedMessage("owen@atlassian.com", "mike@altassian.com", null, null ,"Test Subject 1", "Test 1", "text/plain");
251 
252         Email email = new Email("mike@atlassian.com").setSubject("Test Subject 1").setBody("Test 1").setFrom("owen@atlassian.com");
253         mockSMTPMailServer.send(email);
254 
255         verifySentMessage(mockTransport, expectedMessage, new Address[] {new InternetAddress("mike@atlassian.com")});
256     }
257 
258     @Test
259     public void testSendMail2() throws Exception
260     {
261         SMTPMailServer mockSMTPMailServer = new MockSMTPMailServer(new Long(-1), "default", "", "owen@atlassian.com", "", false, "mail.atlassian.com", "", "", mockSession);
262 
263         MimeMessage expectedMessage = setupExpectedMessage("owen@atlassian.com", "mike@altassian.com", "scott@atlassian.con", null ,"Test Subject 2", "/testing/Test 2", "text/plain");
264 
265         Email email = new Email("mike@atlassian.com").setSubject("Test Subject 2").setCc("scott@atlassian.com").setBody("/testing/Test 2").setFrom("owen@atlassian.com");
266         mockSMTPMailServer.send(email);
267 
268         verifySentMessage(mockTransport, expectedMessage, new Address[] {new InternetAddress("mike@atlassian.com"), new InternetAddress("scott@atlassian.com")});
269     }
270 
271     @Test
272     public void testSendMail3() throws Exception
273     {
274         SMTPMailServer mockSMTPMailServer = new MockSMTPMailServer(new Long(-1), "default", "", "owen@atlassian.com", "", false, "mail.atlassian.com", "", "", mockSession);
275 
276         MimeMessage expectedMessage = setupExpectedMessage("owen@atlassian.com", "mike@altassian.com", null, null ,"Test Subject 3", "/testing/Test 3", "UTF-8");
277 
278 
279 
280         Email email = new Email("mike@atlassian.com").setSubject("Test Subject 3").setBody("/testing/Test 3").setFrom("owen@atlassian.com");
281         mockSMTPMailServer.send(email);
282 
283         verifySentMessage(mockTransport, expectedMessage, new Address[] {new InternetAddress("mike@atlassian.com")});
284     }
285 
286     private void verifySentMessage(Transport mockTransport, MimeMessage expectedMessage, Address[] expectedDestinations) throws MessagingException, IOException
287     {
288         ArgumentCaptor<MimeMessage>  capturedMessage = ArgumentCaptor.forClass(MimeMessage.class);
289         verify(mockTransport).sendMessage(capturedMessage.capture(), aryEq(expectedDestinations));
290         MimeMessage actualMessageSent = capturedMessage.getValue();
291         assertEquals("Subject should be set correctly", expectedMessage.getSubject(), actualMessageSent.getSubject());
292         assertEquals("The content must be the same", expectedMessage.getContent(), actualMessageSent.getContent());
293         assertArrayEquals("The sender must be the same", expectedMessage.getFrom(), actualMessageSent.getFrom());
294     }
295 
296     private MimeMessage setupExpectedMessage(String fromAddress, String toAddress, String ccAddress, String bccAddress, String subject, Object body, String mimeType) throws MessagingException {
297           MimeMessage expectedMessage = new MimeMessage(mockSession);
298 
299         expectedMessage.setFrom(new InternetAddress(fromAddress));
300         expectedMessage.setRecipients(Message.RecipientType.TO, toAddress);
301         if (ccAddress != null)
302         {
303             expectedMessage.setRecipients(Message.RecipientType.CC, ccAddress);
304         }
305         if (bccAddress != null)
306         {
307             expectedMessage.setRecipients(Message.RecipientType.BCC, bccAddress);
308         }
309         expectedMessage.setSubject(subject);
310         if (body instanceof Multipart)
311         {
312             expectedMessage.setContent((Multipart)body);
313         }
314         else
315         {
316             expectedMessage.setContent(body, mimeType);
317         }
318         return expectedMessage;
319       }
320 
321 }