/* * Copyright (C) 2006-2016 DLR, Germany * * All rights reserved * * http://www.rcenvironment.de/ */ package de.rcenvironment.core.mail.internal; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import javax.mail.MessagingException; import org.easymock.EasyMock; import org.junit.Ignore; import org.junit.Test; import com.icegreen.greenmail.util.GreenMail; import com.icegreen.greenmail.util.ServerSetupTest; import de.rcenvironment.core.mail.InvalidMailException; import de.rcenvironment.core.mail.MailDispatchResult; import de.rcenvironment.core.mail.MailDispatchResultListener; /** * Test case for the class {@link MailServiceImpl}. * * @author Tobias Rodehutskors */ public class MailServiceImplTest extends AbstractMailServiceImplTest { private static final String GREENMAIL_IMPLICIT_ENCRYPTION_JSON = "/greenmail_implicit_encryption.json"; private static final String NOT_IMPLEMENTED_YET = "Not implemented yet"; private static final int TWO_SECS_IN_MILLIS = 2000; /** * Tests if the mail dispatch fails with an incomplete configuration, which only specifies the host and port but nothing else. * * @throws InterruptedException unexpected * @throws ExecutionException unexpected * @throws IOException unexpected * @throws InvalidMailException unexpected */ @Test public void testSendMailWithInvalidConfig() throws InterruptedException, ExecutionException, IOException, InvalidMailException { boolean configured = setupMailService("/invalidConfig.json"); assertFalse(configured); Future<?> sendMail = mailServiceImpl.sendMail(createDefaultMail(), new MailDispatchResultListener() { @Override public void receiveResult(MailDispatchResult result, String message) { assertEquals(MailDispatchResult.FAILURE_MAIL_SERVICE_NOT_CONFIGURED, result); assertEquals(null, message); } }); sendMail.get(); } /** * This test will attempt to establish a connection with explicit security using the STARTTLS command. However, the server does not * support STARTTLS. Therefore, we expect a permanent failure. * * @throws IOException unexpected * @throws InterruptedException unexpected * @throws ExecutionException unexpected * @throws InvalidMailException unexpected */ @Test public void testConnectWithExplicitSecurityButServerDoesNotSupportStartTLS() throws IOException, InterruptedException, ExecutionException, InvalidMailException { GreenMail greenmail = new GreenMail(ServerSetupTest.SMTP); // port 3025 greenmail.start(); boolean configured = setupMailService("/greenmail_explicit_encryption.json"); assertTrue(configured); final Future<?> sendMail = mailServiceImpl.sendMail(createDefaultMail(), new MailDispatchResultListener() { @Override public void receiveResult(MailDispatchResult result, String message) { assertEquals(MailDispatchResult.FAILURE, result); assertTrue(message.contains("STARTTLS is required but host does not support STARTTLS")); } }); sendMail.get(); greenmail.stop(); } /** * This test will attempt to establish a connection with implicit security to a SMTP port. Therefore, we expect a permanent failure. * * @throws IOException unexpected * @throws InterruptedException unexpected * @throws ExecutionException unexpected * @throws InvalidMailException unexpected */ @Test public void testConnectWithImplicitSecurityButServerExpectsExplicitSecurity() throws IOException, InvalidMailException, InterruptedException, ExecutionException { GreenMail greenmail = new GreenMail(ServerSetupTest.SMTP); // port 3025 greenmail.start(); boolean configured = setupMailService("/greenmail_implicit_encryption_port3025.json"); assertTrue(configured); final Future<?> sendMail = mailServiceImpl.sendMail(createDefaultMail(), new MailDispatchResultListener() { @Override public void receiveResult(MailDispatchResult result, String message) { assertEquals(MailDispatchResult.FAILURE, result); assertTrue(message.contains("Could not connect to SMTP host")); } }); sendMail.get(); greenmail.stop(); } /** * Attempts to connect to the Greenmail dummy server over an implicitly secured connection. * * @throws IOException unexpected * @throws InterruptedException unexpected * @throws ExecutionException unexpected * @throws InvalidMailException unexpected * @throws MessagingException unexpected */ @Test public void testConnectWithImplicitSecurity() throws IOException, InterruptedException, ExecutionException, InvalidMailException, MessagingException { // opens an SMTPS server on port 3465 which awaits SSL/TLS connections GreenMail greenmail = new GreenMail(ServerSetupTest.SMTPS); greenmail.getManagers().getUserManager().setAuthRequired(true); greenmail.start(); boolean configured = setupMailService(GREENMAIL_IMPLICIT_ENCRYPTION_JSON); assertTrue(configured); mailServiceImpl.trustAllCertificates(); assertTrue(mailServiceImpl.canConnectToServer()); greenmail.stop(); } /** * Attempts to connect to the Greenmail dummy server with an invalid certificate over an implicitly secured connection. * * @throws IOException unexpected * @throws InterruptedException unexpected * @throws ExecutionException unexpected * @throws InvalidMailException unexpected * @throws MessagingException unexpected */ @Test public void testConnectWithImplicitSecurityAndInvalidCertificate() throws IOException, InterruptedException, ExecutionException, InvalidMailException, MessagingException { // opens an SMTPS server on port 3465 which awaits SSL/TLS connections GreenMail greenmail = new GreenMail(ServerSetupTest.SMTPS); greenmail.getManagers().getUserManager().setAuthRequired(true); greenmail.start(); boolean configured = setupMailService(GREENMAIL_IMPLICIT_ENCRYPTION_JSON); assertTrue(configured); assertFalse(mailServiceImpl.canConnectToServer()); greenmail.stop(); } /** * Attempts to send a mail to the Greenmail dummy server over an implicitly secured connection. * * @throws IOException unexpected * @throws InvalidMailException unexpected * @throws ExecutionException unexpected * @throws InterruptedException unexpected * @throws MessagingException unexpected */ @Test public void testMailDispatchWithImplicitSecurity() throws IOException, InvalidMailException, InterruptedException, ExecutionException, MessagingException { // opens an SMTPS server on port 3465 which awaits SSL/TLS connections GreenMail greenmail = new GreenMail(ServerSetupTest.SMTPS); greenmail.getManagers().getUserManager().setAuthRequired(true); greenmail.start(); boolean configured = setupMailService(GREENMAIL_IMPLICIT_ENCRYPTION_JSON); // Since Greenmail uses self-signed certificates, we need to disable certificate validation. mailServiceImpl.trustAllCertificates(); assertTrue(configured); Future<?> sendMail = mailServiceImpl.sendMail(createDefaultMail(), new MailDispatchResultListener() { @Override public void receiveResult(MailDispatchResult result, String message) { assertEquals(MailDispatchResult.SUCCESS, result); assertEquals(null, message); } }); // wait till the mail is send sendMail.get(); validateDefaultMail(greenmail.getReceivedMessages()); greenmail.stop(); } /** * Tests if the mail delivery is retried after an initial connection failure. * * @throws IOException unexpected * @throws InvalidMailException unexpected * @throws InterruptedException unexpected * @throws ExecutionException unexpected * @throws MessagingException unexpected */ @Test public void testMailDispatchIsReattempted() throws IOException, InvalidMailException, InterruptedException, ExecutionException, MessagingException { // opens an SMTPS server on port 3465 which awaits SSL/TLS connections final GreenMail greenmail = new GreenMail(ServerSetupTest.SMTPS); greenmail.getManagers().getUserManager().setAuthRequired(true); // do not start the server here boolean configured = setupMailService(GREENMAIL_IMPLICIT_ENCRYPTION_JSON); // Since Greenmail uses self-signed certificates, we need to disable certificate validation. mailServiceImpl.trustAllCertificates(); assertTrue(configured); Future<?> sendMail = mailServiceImpl.sendMail(createDefaultMail(), new MailDispatchResultListener() { private boolean firstRun = true; @Override public void receiveResult(MailDispatchResult result, String message) { // since the mail server is not running, we expect a failure if (firstRun) { assertEquals(MailDispatchResult.FAILURE_RETRY, result); assertEquals(null, message); // activate the server greenmail.start(); firstRun = false; } else { // we expect a retry and a successful mail delivery after the start of the server assertEquals(MailDispatchResult.SUCCESS, result); assertEquals(null, message); } } }); // wait till the mail is send sendMail.get(); validateDefaultMail(greenmail.getReceivedMessages()); greenmail.stop(); } /** * Tests if the mail delivery can be canceled while a retry is attempted. * * @throws IOException unexpected * @throws InvalidMailException unexpected * @throws InterruptedException unexpected * @throws ExecutionException unexpected */ @Test public void testCancelFutureWhileMailDispatchIsReattempted() throws IOException, InvalidMailException, InterruptedException, ExecutionException { // Do not start a Greenmail server, since we want to check the behavior during a retry boolean configured = setupMailService(GREENMAIL_IMPLICIT_ENCRYPTION_JSON); assertTrue(configured); MailDispatchResultListener listenerMock = EasyMock.createStrictMock(MailDispatchResultListener.class); listenerMock.receiveResult(MailDispatchResult.FAILURE_RETRY, null); EasyMock.expectLastCall().once(); listenerMock.receiveResult(EasyMock.eq(MailDispatchResult.FAILURE), EasyMock.contains("interrupted")); EasyMock.expectLastCall().once(); EasyMock.replay(listenerMock); Future<?> sendMail = mailServiceImpl.sendMail(createDefaultMail(), listenerMock); Thread.sleep(TWO_SECS_IN_MILLIS); boolean canceled = sendMail.cancel(true); assertTrue(canceled); expectedException.expect(CancellationException.class); sendMail.get(); } /** * This test will attempt to establish a connection with explicit security using the STARTTLS command. * * TODO Greenmail currently does not support STARTTLS at all. Therefore, this test should be created as soon as Greenmail supports * STARTTLS. */ @Ignore public void testConnectWithExplicitSecurity() { throw new UnsupportedOperationException(NOT_IMPLEMENTED_YET); } /** * This test will attempt to establish a connection and authenticate with invalid credentials. * * TODO Greenmail 1.5.1 does not verify users, but will accept any password. However, future version probably will support this feature: * https://github.com/greenmail-mail-test/greenmail/issues/127 . It would be nice to have an integration test that checks how our code * behaves if the wrong user credentials are used when connecting to the server. */ @Ignore public void testConnectWithInvalidCredentials() { throw new UnsupportedOperationException(NOT_IMPLEMENTED_YET); } /** * Tests the mail service deactivation during waiting for reattempt of mail delivery. * * TODO */ @Ignore public void testDeactivateMailService() { throw new UnsupportedOperationException(NOT_IMPLEMENTED_YET); } }