/* * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.xwiki.mail.integration; import java.security.Security; import java.util.Arrays; import java.util.Collections; import java.util.Properties; import javax.inject.Provider; import javax.mail.BodyPart; import javax.mail.Message.RecipientType; import javax.mail.Multipart; import javax.mail.Session; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.mockito.Mockito; import org.xwiki.bridge.event.ApplicationReadyEvent; import org.xwiki.component.phase.Disposable; import org.xwiki.component.util.DefaultParameterizedType; import org.xwiki.context.Execution; import org.xwiki.context.ExecutionContext; import org.xwiki.context.ExecutionContextManager; import org.xwiki.environment.internal.EnvironmentConfiguration; import org.xwiki.environment.internal.StandardEnvironment; import org.xwiki.mail.MailSender; import org.xwiki.mail.MailSenderConfiguration; import org.xwiki.mail.MimeBodyPartFactory; import org.xwiki.mail.XWikiAuthenticator; import org.xwiki.mail.internal.DefaultMailSender; import org.xwiki.mail.internal.FileSystemMailContentStore; import org.xwiki.mail.internal.MemoryMailListener; import org.xwiki.mail.internal.configuration.DefaultMailSenderConfiguration; import org.xwiki.mail.internal.factory.attachment.AttachmentMimeBodyPartFactory; import org.xwiki.mail.internal.factory.text.TextMimeBodyPartFactory; import org.xwiki.mail.internal.thread.MailSenderInitializerListener; import org.xwiki.mail.internal.thread.PrepareMailQueueManager; import org.xwiki.mail.internal.thread.PrepareMailRunnable; import org.xwiki.mail.internal.thread.SendMailQueueManager; import org.xwiki.mail.internal.thread.SendMailRunnable; import org.xwiki.mail.internal.thread.context.Copier; import org.xwiki.model.ModelContext; import org.xwiki.model.reference.WikiReference; import org.xwiki.observation.EventListener; import org.xwiki.test.annotation.BeforeComponent; import org.xwiki.test.annotation.ComponentList; import org.xwiki.test.mockito.MockitoComponentManagerRule; import com.icegreen.greenmail.junit.GreenMailRule; import com.icegreen.greenmail.util.DummySSLSocketFactory; import com.icegreen.greenmail.util.ServerSetupTest; import com.xpn.xwiki.XWikiContext; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.when; /** * Integration tests to prove that mail sending is working fully end to end with the Java API when using an * authenticating SMTP server that requires SSL. * * @version $Id: 9f954108c3bf93dfd2468ea32374976c53b788ec $ * @since 6.4M1 */ // @formatter:off @ComponentList({ MailSenderInitializerListener.class, TextMimeBodyPartFactory.class, AttachmentMimeBodyPartFactory.class, StandardEnvironment.class, DefaultMailSender.class, MemoryMailListener.class, SendMailRunnable.class, PrepareMailRunnable.class, PrepareMailQueueManager.class, SendMailQueueManager.class, FileSystemMailContentStore.class }) // @formatter:on public class AuthenticatingIntegrationTest { // Required by GreenMail. static { Security.setProperty("ssl.SocketFactory.provider", DummySSLSocketFactory.class.getName()); } @Rule public GreenMailRule mail = new GreenMailRule(ServerSetupTest.SMTPS); @Rule public MockitoComponentManagerRule componentManager = new MockitoComponentManagerRule(); private MailSenderConfiguration configuration; private MimeBodyPartFactory<String> defaultBodyPartFactory; private MailSender sender; @BeforeComponent public void registerConfiguration() throws Exception { Properties properties = new Properties(); properties.setProperty("mail.smtp.starttls.enable", "true"); // Required by GreenMail. When using XWiki with Gmail for example this is not required. properties.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); this.configuration = new TestMailSenderConfiguration(this.mail.getSmtps().getPort(), "peter", "password", properties); this.componentManager.registerComponent(MailSenderConfiguration.class, this.configuration); // Set the current wiki in the Context ModelContext modelContext = this.componentManager.registerMockComponent(ModelContext.class); when(modelContext.getCurrentEntityReference()).thenReturn(new WikiReference("wiki")); Provider<XWikiContext> xwikiContextProvider = this.componentManager.registerMockComponent(XWikiContext.TYPE_PROVIDER); when(xwikiContextProvider.get()).thenReturn(Mockito.mock(XWikiContext.class)); this.componentManager.registerMockComponent(ExecutionContextManager.class); this.componentManager.registerMockComponent(Execution.class); this.componentManager.registerMockComponent(new DefaultParameterizedType(null, Copier.class, ExecutionContext.class)); EnvironmentConfiguration environmentConfiguration = this.componentManager.registerMockComponent(EnvironmentConfiguration.class); when(environmentConfiguration.getPermanentDirectoryPath()).thenReturn(System.getProperty("java.io.tmpdir")); } @Before public void initialize() throws Exception { // Create a user in the SMTP server. this.mail.setUser("peter@doe.com", "peter", "password"); this.defaultBodyPartFactory = this.componentManager.getInstance(new DefaultParameterizedType(null, MimeBodyPartFactory.class, String.class)); this.sender = this.componentManager.getInstance(MailSender.class); // Simulate receiving the Application Ready Event to start the mail threads MailSenderInitializerListener listener = this.componentManager.getInstance(EventListener.class, MailSenderInitializerListener.LISTENER_NAME); listener.onEvent(new ApplicationReadyEvent(), null, null); } @After public void cleanUp() throws Exception { // Make sure we stop the Mail Sender thread after each test (since it's started automatically when looking // up the MailSender component. Disposable listener = this.componentManager.getInstance(EventListener.class, MailSenderInitializerListener.LISTENER_NAME); listener.dispose(); } @Test public void sendTextMail() throws Exception { // Set the EC Execution execution = this.componentManager.getInstance(Execution.class); ExecutionContext executionContext = new ExecutionContext(); XWikiContext xContext = new XWikiContext(); xContext.setWikiId("wiki"); executionContext.setProperty(XWikiContext.EXECUTIONCONTEXT_KEY, xContext); when(execution.getContext()).thenReturn(executionContext); Copier<ExecutionContext> executionContextCloner = this.componentManager.getInstance(new DefaultParameterizedType(null, Copier.class, ExecutionContext.class)); // Just return the same execution context when(executionContextCloner.copy(executionContext)).thenReturn(executionContext); // Step 1: Create a JavaMail Session Properties properties = this.configuration.getAllProperties(); assertEquals("true", properties.getProperty(DefaultMailSenderConfiguration.JAVAMAIL_SMTP_AUTH)); Session session = Session.getInstance(properties, new XWikiAuthenticator(this.configuration)); // Step 2: Create the Message to send MimeMessage message = new MimeMessage(session); message.setSubject("subject"); message.setRecipient(RecipientType.TO, new InternetAddress("john@doe.com")); // Step 3: Add the Message Body Multipart multipart = new MimeMultipart("mixed"); // Add text in the body multipart.addBodyPart(this.defaultBodyPartFactory.create("some text here", Collections.<String, Object>singletonMap("mimetype", "text/plain"))); message.setContent(multipart); // Step 4: Send the mail this.sender.sendAsynchronously(Arrays.asList(message), session, null); // Verify that the mail has been received (wait maximum 30 seconds). this.mail.waitForIncomingEmail(30000L, 1); MimeMessage[] messages = this.mail.getReceivedMessages(); assertEquals(1, messages.length); assertEquals("subject", messages[0].getHeader("Subject", null)); assertEquals("john@doe.com", messages[0].getHeader("To", null)); assertEquals(1, ((MimeMultipart) messages[0].getContent()).getCount()); BodyPart textBodyPart = ((MimeMultipart) messages[0].getContent()).getBodyPart(0); assertEquals("text/plain", textBodyPart.getHeader("Content-Type")[0]); assertEquals("some text here", textBodyPart.getContent()); } }