1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package org.xwiki.mail.integration

File JavaIntegrationTest.java

 

Code metrics

2
89
7
1
338
236
8
0.09
12.71
7
1.14

Classes

Class Line # Actions
JavaIntegrationTest 102 89 0% 8 2
0.9795918598%
 

Contributing tests

This file is covered by 3 tests. .

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package org.xwiki.mail.integration;
21   
22    import java.io.InputStream;
23    import java.util.Arrays;
24    import java.util.Collections;
25    import java.util.HashMap;
26    import java.util.Map;
27    import java.util.Properties;
28   
29    import javax.inject.Provider;
30    import javax.mail.BodyPart;
31    import javax.mail.Message.RecipientType;
32    import javax.mail.MessagingException;
33    import javax.mail.Multipart;
34    import javax.mail.Session;
35    import javax.mail.internet.InternetAddress;
36    import javax.mail.internet.MimeMessage;
37    import javax.mail.internet.MimeMultipart;
38   
39    import org.apache.commons.io.IOUtils;
40    import org.junit.After;
41    import org.junit.Before;
42    import org.junit.Rule;
43    import org.junit.Test;
44    import org.xwiki.bridge.event.ApplicationReadyEvent;
45    import org.xwiki.component.phase.Disposable;
46    import org.xwiki.component.util.DefaultParameterizedType;
47    import org.xwiki.context.Execution;
48    import org.xwiki.context.ExecutionContext;
49    import org.xwiki.context.ExecutionContextManager;
50    import org.xwiki.environment.internal.EnvironmentConfiguration;
51    import org.xwiki.environment.internal.StandardEnvironment;
52    import org.xwiki.mail.MailListener;
53    import org.xwiki.mail.MailSender;
54    import org.xwiki.mail.MailSenderConfiguration;
55    import org.xwiki.mail.MimeBodyPartFactory;
56    import org.xwiki.mail.internal.DefaultMailSender;
57    import org.xwiki.mail.internal.FileSystemMailContentStore;
58    import org.xwiki.mail.internal.MemoryMailListener;
59    import org.xwiki.mail.internal.factory.attachment.AttachmentMimeBodyPartFactory;
60    import org.xwiki.mail.internal.factory.html.HTMLMimeBodyPartFactory;
61    import org.xwiki.mail.internal.factory.text.TextMimeBodyPartFactory;
62    import org.xwiki.mail.internal.thread.MailSenderInitializerListener;
63    import org.xwiki.mail.internal.thread.PrepareMailQueueManager;
64    import org.xwiki.mail.internal.thread.PrepareMailRunnable;
65    import org.xwiki.mail.internal.thread.SendMailQueueManager;
66    import org.xwiki.mail.internal.thread.SendMailRunnable;
67    import org.xwiki.mail.internal.thread.context.Copier;
68    import org.xwiki.model.ModelContext;
69    import org.xwiki.model.reference.WikiReference;
70    import org.xwiki.observation.EventListener;
71    import org.xwiki.test.annotation.BeforeComponent;
72    import org.xwiki.test.annotation.ComponentList;
73    import org.xwiki.test.mockito.MockitoComponentManagerRule;
74   
75    import com.icegreen.greenmail.junit.GreenMailRule;
76    import com.icegreen.greenmail.util.ServerSetupTest;
77    import com.xpn.xwiki.XWikiContext;
78   
79    import static org.junit.Assert.assertEquals;
80    import static org.mockito.Mockito.*;
81   
82    /**
83    * Integration tests to prove that mail sending is working fully end to end with the Java API.
84    *
85    * @version $Id: fab3cb1c92119a3ac8c923d968106cff04c2f61e $
86    * @since 6.1M2
87    */
88    @ComponentList({
89    MailSenderInitializerListener.class,
90    TextMimeBodyPartFactory.class,
91    HTMLMimeBodyPartFactory.class,
92    AttachmentMimeBodyPartFactory.class,
93    StandardEnvironment.class,
94    DefaultMailSender.class,
95    MemoryMailListener.class,
96    SendMailRunnable.class,
97    PrepareMailRunnable.class,
98    PrepareMailQueueManager.class,
99    SendMailQueueManager.class,
100    FileSystemMailContentStore.class
101    })
 
102    public class JavaIntegrationTest
103    {
104    @Rule
105    public GreenMailRule mail = new GreenMailRule(ServerSetupTest.SMTP);
106   
107    @Rule
108    public MockitoComponentManagerRule componentManager = new MockitoComponentManagerRule();
109   
110    private TestMailSenderConfiguration configuration;
111   
112    private MimeBodyPartFactory<String> defaultBodyPartFactory;
113   
114    private MimeBodyPartFactory<String> htmlBodyPartFactory;
115   
116    private MailSender sender;
117   
 
118  3 toggle @BeforeComponent
119    public void registerConfiguration() throws Exception
120    {
121  3 this.configuration = new TestMailSenderConfiguration(
122    this.mail.getSmtp().getPort(), null, null, new Properties());
123  3 this.componentManager.registerComponent(MailSenderConfiguration.class, this.configuration);
124   
125    // Set the current wiki in the Context
126  3 ModelContext modelContext = this.componentManager.registerMockComponent(ModelContext.class);
127  3 when(modelContext.getCurrentEntityReference()).thenReturn(new WikiReference("wiki"));
128   
129  3 XWikiContext xcontext = mock(XWikiContext.class);
130  3 when(xcontext.getWikiId()).thenReturn("wiki");
131   
132  3 Provider<XWikiContext> xwikiContextProvider = this.componentManager.registerMockComponent(
133    XWikiContext.TYPE_PROVIDER);
134  3 when(xwikiContextProvider.get()).thenReturn(xcontext);
135   
136  3 this.componentManager.registerMockComponent(ExecutionContextManager.class);
137  3 this.componentManager.registerMockComponent(Execution.class);
138   
139  3 this.componentManager.registerMockComponent(new DefaultParameterizedType(null, Copier.class,
140    ExecutionContext.class));
141   
142  3 EnvironmentConfiguration environmentConfiguration =
143    this.componentManager.registerMockComponent(EnvironmentConfiguration.class);
144  3 when(environmentConfiguration.getPermanentDirectoryPath()).thenReturn(System.getProperty("java.io.tmpdir"));
145    }
146   
 
147  3 toggle @Before
148    public void initialize() throws Exception
149    {
150  3 this.defaultBodyPartFactory = this.componentManager.getInstance(
151    new DefaultParameterizedType(null, MimeBodyPartFactory.class, String.class));
152  3 this.htmlBodyPartFactory = this.componentManager.getInstance(
153    new DefaultParameterizedType(null, MimeBodyPartFactory.class, String.class), "text/html");
154  3 this.sender = this.componentManager.getInstance(MailSender.class);
155   
156    // Set the EC
157  3 Execution execution = this.componentManager.getInstance(Execution.class);
158  3 ExecutionContext executionContext = new ExecutionContext();
159  3 XWikiContext xContext = new XWikiContext();
160  3 xContext.setWikiId("wiki");
161  3 executionContext.setProperty(XWikiContext.EXECUTIONCONTEXT_KEY, xContext);
162  3 when(execution.getContext()).thenReturn(executionContext);
163   
164  3 Copier<ExecutionContext> executionContextCloner =
165    this.componentManager.getInstance(new DefaultParameterizedType(null, Copier.class, ExecutionContext.class));
166    // Just return the same execution context
167  3 when(executionContextCloner.copy(executionContext)).thenReturn(executionContext);
168   
169    // Simulate receiving the Application Ready Event to start the mail threads
170  3 MailSenderInitializerListener listener =
171    this.componentManager.getInstance(EventListener.class, MailSenderInitializerListener.LISTENER_NAME);
172  3 listener.onEvent(new ApplicationReadyEvent(), null, null);
173    }
174   
 
175  3 toggle @After
176    public void cleanUp() throws Exception
177    {
178    // Make sure we stop the Mail Sender thread after each test (since it's started automatically when looking
179    // up the MailSender component.
180  3 Disposable listener =
181    this.componentManager.getInstance(EventListener.class, MailSenderInitializerListener.LISTENER_NAME);
182  3 listener.dispose();
183    }
184   
 
185  1 toggle @Test
186    public void sendTextMail() throws Exception
187    {
188    // Step 1: Create a JavaMail Session
189  1 Session session = Session.getInstance(this.configuration.getAllProperties());
190   
191    // Step 2: Create the Message to send
192  1 MimeMessage message = new MimeMessage(session);
193  1 message.setSubject("subject");
194  1 message.setRecipient(RecipientType.TO, new InternetAddress("john@doe.com"));
195   
196    // Step 3: Add the Message Body
197  1 Multipart multipart = new MimeMultipart("mixed");
198    // Add text in the body
199  1 multipart.addBodyPart(this.defaultBodyPartFactory.create("some text here",
200    Collections.<String, Object>singletonMap("mimetype", "text/plain")));
201  1 message.setContent(multipart);
202   
203    // We also test using some default BCC addresses from configuration in this test
204  1 this.configuration.setBCCAddresses(Arrays.asList("bcc1@doe.com", "bcc2@doe.com"));
205   
206    // Ensure we do not reuse the same message identifier for multiple similar messages in this test
207  1 MimeMessage message2 = new MimeMessage(message);
208  1 message2.saveChanges();
209  1 MimeMessage message3 = new MimeMessage(message);
210  1 message3.saveChanges();
211   
212    // Step 4: Send the mail and wait for it to be sent
213    // Send 3 mails (3 times the same mail) to verify we can send several emails at once.
214  1 MailListener memoryMailListener = this.componentManager.getInstance(MailListener.class, "memory");
215  1 this.sender.sendAsynchronously(Arrays.asList(message, message2, message3), session, memoryMailListener);
216   
217    // Note: we don't test status reporting from the listener since this is already tested in the
218    // ScriptingIntegrationTest test class.
219   
220    // Verify that the mails have been received (wait maximum 10 seconds).
221  1 this.mail.waitForIncomingEmail(10000L, 3);
222  1 MimeMessage[] messages = this.mail.getReceivedMessages();
223   
224    // Note: we're receiving 9 messages since we sent 3 with 3 recipients (2 BCC and 1 to)!
225  1 assertEquals(9, messages.length);
226   
227    // Assert the email parts that are the same for all mails
228  1 assertEquals("subject", messages[0].getHeader("Subject", null));
229  1 assertEquals(1, ((MimeMultipart) messages[0].getContent()).getCount());
230  1 BodyPart textBodyPart = ((MimeMultipart) messages[0].getContent()).getBodyPart(0);
231  1 assertEquals("text/plain", textBodyPart.getHeader("Content-Type")[0]);
232  1 assertEquals("some text here", textBodyPart.getContent());
233  1 assertEquals("john@doe.com", messages[0].getHeader("To", null));
234   
235    // Note: We cannot assert that the BCC worked since by definition BCC information are not visible in received
236    // messages ;) But we checked that we received 9 emails above so that's good enough.
237    }
238   
 
239  1 toggle @Test
240    public void sendHTMLAndCalendarInvitationMail() throws Exception
241    {
242    // Step 1: Create a JavaMail Session
243  1 Session session = Session.getInstance(this.configuration.getAllProperties());
244   
245    // Step 2: Create the Message to send
246  1 MimeMessage message = new MimeMessage(session);
247  1 message.setSubject("subject");
248  1 message.setRecipient(RecipientType.TO, new InternetAddress("john@doe.com"));
249   
250    // Step 3: Add the Message Body
251  1 Multipart multipart = new MimeMultipart("alternative");
252    // Add an HTML body part
253  1 multipart.addBodyPart(this.htmlBodyPartFactory.create(
254    "<font size=\"\\\"2\\\"\">simple meeting invitation</font>", Collections.<String, Object>emptyMap()));
255    // Add the Calendar invitation body part
256  1 String calendarContent = "BEGIN:VCALENDAR\r\n"
257    + "METHOD:REQUEST\r\n"
258    + "PRODID: Meeting\r\n"
259    + "VERSION:2.0\r\n"
260    + "BEGIN:VEVENT\r\n"
261    + "DTSTAMP:20140616T164100\r\n"
262    + "DTSTART:20140616T164100\r\n"
263    + "DTEND:20140616T194100\r\n"
264    + "SUMMARY:test request\r\n"
265    + "UID:324\r\n"
266    + "ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:MAILTO:john@doe.com\r\n"
267    + "ORGANIZER:MAILTO:john@doe.com\r\n"
268    + "LOCATION:on the net\r\n"
269    + "DESCRIPTION:learn some stuff\r\n"
270    + "SEQUENCE:0\r\n"
271    + "PRIORITY:5\r\n"
272    + "CLASS:PUBLIC\r\n"
273    + "STATUS:CONFIRMED\r\n"
274    + "TRANSP:OPAQUE\r\n"
275    + "BEGIN:VALARM\r\n"
276    + "ACTION:DISPLAY\r\n"
277    + "DESCRIPTION:REMINDER\r\n"
278    + "TRIGGER;RELATED=START:-PT00H15M00S\r\n"
279    + "END:VALARM\r\n"
280    + "END:VEVENT\r\n"
281    + "END:VCALENDAR";
282  1 Map<String, Object> parameters = new HashMap<>();
283  1 parameters.put("mimetype", "text/calendar;method=CANCEL");
284  1 parameters.put("headers", Collections.singletonMap("Content-Class", "urn:content-classes:calendarmessage"));
285  1 multipart.addBodyPart(this.defaultBodyPartFactory.create(calendarContent, parameters));
286   
287  1 message.setContent(multipart);
288   
289    // Step 4: Send the mail and wait for it to be sent
290  1 this.sender.sendAsynchronously(Arrays.asList(message), session, null);
291   
292    // Verify that the mail has been received (wait maximum 10 seconds).
293  1 this.mail.waitForIncomingEmail(10000L, 1);
294  1 MimeMessage[] messages = this.mail.getReceivedMessages();
295   
296  1 assertEquals("subject", messages[0].getHeader("Subject", null));
297  1 assertEquals("john@doe.com", messages[0].getHeader("To", null));
298   
299  1 assertEquals(2, ((MimeMultipart) messages[0].getContent()).getCount());
300   
301  1 BodyPart htmlBodyPart = ((MimeMultipart) messages[0].getContent()).getBodyPart(0);
302  1 assertEquals("text/html; charset=UTF-8", htmlBodyPart.getHeader("Content-Type")[0]);
303  1 assertEquals("<font size=\"\\\"2\\\"\">simple meeting invitation</font>", htmlBodyPart.getContent());
304   
305  1 BodyPart calendarBodyPart = ((MimeMultipart) messages[0].getContent()).getBodyPart(1);
306  1 assertEquals("text/calendar;method=CANCEL", calendarBodyPart.getHeader("Content-Type")[0]);
307  1 InputStream is = (InputStream) calendarBodyPart.getContent();
308  1 assertEquals(calendarContent, IOUtils.toString(is));
309    }
310   
 
311  1 toggle @Test
312    public void sendMailWithCustomMessageId() throws Exception
313    {
314  1 Session session = Session.getInstance(this.configuration.getAllProperties());
315  1 MimeMessage message = new MimeMessage(session) {
 
316  1 toggle @Override
317    protected void updateMessageID() throws MessagingException
318    {
319  1 if (getMessageID() == null) {
320  0 super.updateMessageID();
321    }
322    }
323    };
324  1 message.setRecipient(RecipientType.TO, new InternetAddress("john@doe.com"));
325  1 message.setText("Test message Id support");
326  1 message.setHeader("Message-ID", "<custom@domain>");
327  1 message.setSubject("subject");
328   
329  1 MailListener memoryMailListener = this.componentManager.getInstance(MailListener.class, "memory");
330  1 this.sender.sendAsynchronously(Arrays.asList(message), session, memoryMailListener);
331   
332    // Verify that the mails have been received (wait maximum 10 seconds).
333  1 this.mail.waitForIncomingEmail(10000L, 1);
334  1 MimeMessage[] messages = this.mail.getReceivedMessages();
335   
336  1 assertEquals("<custom@domain>", messages[0].getMessageID());
337    }
338    }