GH-3451: Use GreenMail for testing instead
Fixes https://github.com/spring-projects/spring-integration/issues/3451 The GreenMail provides a comprehensive support for e-mail scenarios testing. * Use GreenMail instead our own `TestMailServer` for better and broader support * Convert SmtpTests and Pop3Tests to GreenMail * Document that Pop3MailReceiver does not support autoCloseFolder=false * Pop3MailReceiver uses `folder.getMessageCount()` to determine if there are new messages. This count only gets updated when opening the folder. * Use GreenMail for remaining mail tests * convert MailTests and ImapMailReceiverTests to GreenMail * remove duplicate mail dependencies * route com.sun.mail logging to log4j (via jul and slf4j)
This commit is contained in:
committed by
Artem Bilan
parent
13005dfdcd
commit
996daca228
@@ -60,6 +60,7 @@ ext {
|
||||
derbyVersion = '10.14.2.0'
|
||||
ftpServerVersion = '1.1.1'
|
||||
googleJsr305Version = '3.0.2'
|
||||
greenmailVersion = '1.6.4'
|
||||
groovyVersion = '3.0.8'
|
||||
hamcrestVersion = '2.2'
|
||||
hazelcastVersion = '4.2'
|
||||
@@ -641,9 +642,9 @@ project('spring-integration-mail') {
|
||||
api project(':spring-integration-core')
|
||||
api 'org.springframework:spring-context-support'
|
||||
|
||||
providedImplementation "jakarta.mail:jakarta.mail-api:$mailVersion"
|
||||
providedImplementation "com.sun.mail:imap:$mailVersion"
|
||||
providedImplementation "com.sun.mail:jakarta.mail:$mailVersion"
|
||||
testImplementation "com.icegreen:greenmail:$greenmailVersion"
|
||||
testRuntimeOnly 'org.apache.logging.log4j:log4j-jul'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,12 +31,18 @@ import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.LogManager;
|
||||
import java.util.logging.LogRecord;
|
||||
|
||||
import javax.mail.Flags;
|
||||
import javax.mail.Flags.Flag;
|
||||
@@ -72,8 +78,6 @@ import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
|
||||
import org.springframework.integration.history.MessageHistory;
|
||||
import org.springframework.integration.mail.support.DefaultMailHeaderMapper;
|
||||
import org.springframework.integration.test.mail.TestMailServer;
|
||||
import org.springframework.integration.test.mail.TestMailServer.ImapServer;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
import org.springframework.messaging.PollableChannel;
|
||||
@@ -84,6 +88,11 @@ import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
|
||||
import com.icegreen.greenmail.user.GreenMailUser;
|
||||
import com.icegreen.greenmail.util.GreenMail;
|
||||
import com.icegreen.greenmail.util.GreenMailUtil;
|
||||
import com.icegreen.greenmail.util.ServerSetup;
|
||||
import com.icegreen.greenmail.util.ServerSetupTest;
|
||||
import com.sun.mail.imap.IMAPFolder;
|
||||
|
||||
/**
|
||||
@@ -100,31 +109,43 @@ public class ImapMailReceiverTests {
|
||||
|
||||
private AtomicInteger failed;
|
||||
|
||||
private ImapServer imapIdleServer;
|
||||
private GreenMail imapIdleServer;
|
||||
|
||||
private GreenMailUser user;
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext context;
|
||||
|
||||
static {
|
||||
System.setProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager");
|
||||
}
|
||||
|
||||
private final ImapSearchLoggingHandler imapSearches = new ImapSearchLoggingHandler();
|
||||
|
||||
@BeforeEach
|
||||
public void setup() throws InterruptedException {
|
||||
public void setup() {
|
||||
LogManager.getLogManager().getLogger("").setLevel(Level.ALL);
|
||||
imapSearches.searches.clear();
|
||||
imapSearches.stores.clear();
|
||||
LogManager.getLogManager().getLogger("").addHandler(imapSearches);
|
||||
failed = new AtomicInteger(0);
|
||||
this.imapIdleServer = TestMailServer.imap(0);
|
||||
int n = 0;
|
||||
while (n++ < 100 && (!this.imapIdleServer.isListening())) {
|
||||
Thread.sleep(100);
|
||||
}
|
||||
assertThat(n < 100).isTrue();
|
||||
ServerSetup imap = ServerSetupTest.IMAP.dynamicPort();
|
||||
imap.setServerStartupTimeout(10000);
|
||||
imapIdleServer = new GreenMail(imap);
|
||||
user = imapIdleServer.setUser("user", "pw");
|
||||
imapIdleServer.start();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void tearDown() {
|
||||
this.imapIdleServer.stop();
|
||||
LogManager.getLogManager().getLogger("").removeHandler(imapSearches);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIdleWithServerCustomSearch() throws Exception {
|
||||
ImapMailReceiver receiver =
|
||||
new ImapMailReceiver("imap://user:pw@localhost:" + this.imapIdleServer.getPort() + "/INBOX");
|
||||
new ImapMailReceiver("imap://user:pw@localhost:" + this.imapIdleServer.getImap().getPort() + "/INBOX");
|
||||
receiver.setSearchTermStrategy((supportedFlags, folder) -> {
|
||||
try {
|
||||
FromTerm fromTerm = new FromTerm(new InternetAddress("bar@baz"));
|
||||
@@ -140,15 +161,15 @@ public class ImapMailReceiverTests {
|
||||
@Test
|
||||
public void testIdleWithServerDefaultSearch() throws Exception {
|
||||
ImapMailReceiver receiver =
|
||||
new ImapMailReceiver("imap://user:pw@localhost:" + this.imapIdleServer.getPort() + "/INBOX");
|
||||
new ImapMailReceiver("imap://user:pw@localhost:" + this.imapIdleServer.getImap().getPort() + "/INBOX");
|
||||
testIdleWithServerGuts(receiver, false);
|
||||
assertThat(this.imapIdleServer.assertReceived("searchWithUserFlag")).isTrue();
|
||||
assertThat(imapSearches.searches.get(0)).contains("testSIUserFlag");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIdleWithMessageMapping() throws Exception {
|
||||
ImapMailReceiver receiver =
|
||||
new ImapMailReceiver("imap://user:pw@localhost:" + this.imapIdleServer.getPort() + "/INBOX");
|
||||
new ImapMailReceiver("imap://user:pw@localhost:" + this.imapIdleServer.getImap().getPort() + "/INBOX");
|
||||
receiver.setHeaderMapper(new DefaultMailHeaderMapper());
|
||||
testIdleWithServerGuts(receiver, true);
|
||||
}
|
||||
@@ -156,16 +177,16 @@ public class ImapMailReceiverTests {
|
||||
@Test
|
||||
public void testIdleWithServerDefaultSearchSimple() throws Exception {
|
||||
ImapMailReceiver receiver =
|
||||
new ImapMailReceiver("imap://user:pw@localhost:" + this.imapIdleServer.getPort() + "/INBOX");
|
||||
new ImapMailReceiver("imap://user:pw@localhost:" + this.imapIdleServer.getImap().getPort() + "/INBOX");
|
||||
receiver.setSimpleContent(true);
|
||||
testIdleWithServerGuts(receiver, false, true);
|
||||
assertThat(this.imapIdleServer.assertReceived("searchWithUserFlag")).isTrue();
|
||||
assertThat(imapSearches.searches.get(0)).contains("testSIUserFlag");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIdleWithMessageMappingSimple() throws Exception {
|
||||
ImapMailReceiver receiver =
|
||||
new ImapMailReceiver("imap://user:pw@localhost:" + this.imapIdleServer.getPort() + "/INBOX");
|
||||
new ImapMailReceiver("imap://user:pw@localhost:" + this.imapIdleServer.getImap().getPort() + "/INBOX");
|
||||
receiver.setSimpleContent(true);
|
||||
receiver.setHeaderMapper(new DefaultMailHeaderMapper());
|
||||
testIdleWithServerGuts(receiver, true, true);
|
||||
@@ -176,10 +197,6 @@ public class ImapMailReceiverTests {
|
||||
}
|
||||
|
||||
public void testIdleWithServerGuts(ImapMailReceiver receiver, boolean mapped, boolean simple) throws Exception {
|
||||
Properties mailProps = new Properties();
|
||||
mailProps.put("mail.debug", "true");
|
||||
mailProps.put("mail.imap.connectionpool.debug", "true");
|
||||
receiver.setJavaMailProperties(mailProps);
|
||||
receiver.setMaxFetchSize(1);
|
||||
receiver.setShouldDeleteMessages(false);
|
||||
receiver.setShouldMarkMessagesAsRead(true);
|
||||
@@ -193,6 +210,14 @@ public class ImapMailReceiverTests {
|
||||
adapter.setTaskScheduler(taskScheduler);
|
||||
adapter.setReconnectDelay(1);
|
||||
adapter.start();
|
||||
MimeMessage message =
|
||||
GreenMailUtil.createTextEmail("Foo <foo@bar>", "Bar <bar@baz>", "Test Email", "foo\r\n",
|
||||
imapIdleServer.getImap().getServerSetup());
|
||||
message.setRecipients(Message.RecipientType.CC, "a@b, c@d");
|
||||
message.setRecipients(Message.RecipientType.BCC, "e@f, g@h");
|
||||
user.deliver(message);
|
||||
user.deliver(GreenMailUtil.createTextEmail("to", "Bar <bar@baz>", "subject", "body",
|
||||
imapIdleServer.getImap().getServerSetup()));
|
||||
if (!mapped) {
|
||||
@SuppressWarnings("unchecked")
|
||||
org.springframework.messaging.Message<MimeMessage> received =
|
||||
@@ -202,11 +227,11 @@ public class ImapMailReceiverTests {
|
||||
assertThat(received.getPayload().getLineCount() > -1).isTrue();
|
||||
if (simple) {
|
||||
assertThat(received.getPayload().getContent())
|
||||
.isEqualTo(TestMailServer.MailServer.MailHandler.BODY + "\r\n");
|
||||
.isEqualTo("foo\r\n");
|
||||
}
|
||||
else {
|
||||
assertThat(received.getPayload().getContent())
|
||||
.isEqualTo(TestMailServer.MailServer.MailHandler.MESSAGE + "\r\n");
|
||||
.isEqualTo("foo");
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -214,7 +239,7 @@ public class ImapMailReceiverTests {
|
||||
assertThat(received).isNotNull();
|
||||
MessageHeaders headers = received.getHeaders();
|
||||
assertThat(headers.get(MailHeaders.RAW_HEADERS)).isNotNull();
|
||||
assertThat(headers.get(MailHeaders.CONTENT_TYPE)).isEqualTo("TEXT/PLAIN; charset=ISO-8859-1");
|
||||
assertThat(headers.get(MailHeaders.CONTENT_TYPE)).isEqualTo("TEXT/PLAIN; charset=us-ascii");
|
||||
assertThat(headers.get(MessageHeaders.CONTENT_TYPE)).isEqualTo(MimeTypeUtils.TEXT_PLAIN_VALUE);
|
||||
assertThat(headers.get(MailHeaders.FROM)).isEqualTo("Bar <bar@baz>");
|
||||
String[] toHeader = headers.get(MailHeaders.TO, String[].class);
|
||||
@@ -224,10 +249,10 @@ public class ImapMailReceiverTests {
|
||||
assertThat(Arrays.toString(headers.get(MailHeaders.BCC, String[].class))).isEqualTo("[e@f, g@h]");
|
||||
assertThat(headers.get(MailHeaders.SUBJECT)).isEqualTo("Test Email");
|
||||
if (simple) {
|
||||
assertThat(received.getPayload()).isEqualTo(TestMailServer.MailServer.MailHandler.BODY + "\r\n");
|
||||
assertThat(received.getPayload()).isEqualTo("foo\r\n");
|
||||
}
|
||||
else {
|
||||
assertThat(received.getPayload()).isEqualTo(TestMailServer.MailServer.MailHandler.MESSAGE + "\r\n");
|
||||
assertThat(received.getPayload()).isEqualTo("foo");
|
||||
}
|
||||
}
|
||||
assertThat(channel.receive(20000)).isNotNull(); // new message after idle
|
||||
@@ -235,11 +260,13 @@ public class ImapMailReceiverTests {
|
||||
|
||||
adapter.stop();
|
||||
taskScheduler.shutdown();
|
||||
assertThat(this.imapIdleServer.assertReceived("storeUserFlag")).isTrue();
|
||||
assertThat(imapSearches.stores.get(0)).contains("testSIUserFlag");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void receiveAndMarkAsReadDontDelete() throws Exception {
|
||||
user.deliver(GreenMailUtil.createTextEmail("user", "sender", "subject", "body",
|
||||
imapIdleServer.getImap().getServerSetup()));
|
||||
AbstractMailReceiver receiver = new ImapMailReceiver();
|
||||
Message msg1 = mock(MimeMessage.class);
|
||||
Message msg2 = mock(MimeMessage.class);
|
||||
@@ -898,4 +925,40 @@ public class ImapMailReceiverTests {
|
||||
mailReceiver.setBeanFactory(bf);
|
||||
}
|
||||
|
||||
|
||||
private static class ImapSearchLoggingHandler extends Handler {
|
||||
|
||||
private final List<String> searches = new ArrayList<>();
|
||||
|
||||
private final List<String> stores = new ArrayList<>();
|
||||
|
||||
private static final String SEARCH = " SEARCH ";
|
||||
|
||||
private static final String STORE = " STORE ";
|
||||
|
||||
@Override
|
||||
public void publish(LogRecord record) {
|
||||
if ("com.sun.mail.imap.protocol".equals(record.getLoggerName())) {
|
||||
String message = record.getMessage();
|
||||
if (!message.startsWith("*")) {
|
||||
if (message.contains(SEARCH) && !message.contains(" OK ")) {
|
||||
searches.add(message.substring(message.indexOf(SEARCH) + SEARCH.length()));
|
||||
}
|
||||
else if (message.contains(STORE) && !message.contains(" OK ")) {
|
||||
stores.add(message.substring(message.indexOf(STORE) + STORE.length()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws SecurityException {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,6 +20,10 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.mail.Message.RecipientType;
|
||||
import javax.mail.MessagingException;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -28,29 +32,36 @@ import org.springframework.integration.mail.MailHeaders;
|
||||
import org.springframework.integration.mail.MailReceivingMessageSource;
|
||||
import org.springframework.integration.mail.Pop3MailReceiver;
|
||||
import org.springframework.integration.mail.support.DefaultMailHeaderMapper;
|
||||
import org.springframework.integration.test.mail.TestMailServer;
|
||||
import org.springframework.integration.test.mail.TestMailServer.Pop3Server;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
|
||||
import com.icegreen.greenmail.user.GreenMailUser;
|
||||
import com.icegreen.greenmail.util.GreenMail;
|
||||
import com.icegreen.greenmail.util.GreenMailUtil;
|
||||
import com.icegreen.greenmail.util.ServerSetup;
|
||||
import com.icegreen.greenmail.util.ServerSetupTest;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
* @author Alexander Pinske
|
||||
*
|
||||
* @since 5.0
|
||||
*
|
||||
*/
|
||||
public class Pop3Tests {
|
||||
|
||||
private static final Pop3Server pop3Server = TestMailServer.pop3(0);
|
||||
private static GreenMail pop3Server;
|
||||
|
||||
private static GreenMailUser user;
|
||||
|
||||
@BeforeAll
|
||||
public static void setup() throws InterruptedException {
|
||||
int n = 0;
|
||||
while (n++ < 100 && (!pop3Server.isListening())) {
|
||||
Thread.sleep(100);
|
||||
}
|
||||
assertThat(n < 100).isTrue();
|
||||
public static void setup() {
|
||||
ServerSetup pop3 = ServerSetupTest.POP3.dynamicPort();
|
||||
pop3.setServerStartupTimeout(10000);
|
||||
pop3Server = new GreenMail(pop3);
|
||||
user = pop3Server.setUser("user", "pw");
|
||||
pop3Server.start();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
@@ -59,8 +70,15 @@ public class Pop3Tests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPop3() {
|
||||
Pop3MailReceiver receiver = new Pop3MailReceiver("localhost", pop3Server.getPort(), "user", "pw");
|
||||
public void testPop3() throws MessagingException {
|
||||
MimeMessage mimeMessage =
|
||||
GreenMailUtil.createTextEmail("Foo <foo@bar>", "Bar <bar@baz>, Bar2 <bar2@baz>", "Test Email",
|
||||
"foo\r\n", pop3Server.getPop3().getServerSetup());
|
||||
mimeMessage.setRecipients(RecipientType.CC, "a@b, c@d");
|
||||
mimeMessage.setRecipients(RecipientType.BCC, "e@f, g@h");
|
||||
user.deliver(mimeMessage);
|
||||
|
||||
Pop3MailReceiver receiver = new Pop3MailReceiver("localhost", pop3Server.getPop3().getPort(), "user", "pw");
|
||||
receiver.setHeaderMapper(new DefaultMailHeaderMapper());
|
||||
MailReceivingMessageSource source = new MailReceivingMessageSource(receiver);
|
||||
Message<?> message = source.receive();
|
||||
@@ -71,7 +89,7 @@ public class Pop3Tests {
|
||||
assertThat(Arrays.toString(headers.get(MailHeaders.BCC, String[].class))).isEqualTo("[e@f, g@h]");
|
||||
assertThat(headers.get(MailHeaders.FROM)).isEqualTo("Bar <bar@baz>,Bar2 <bar2@baz>");
|
||||
assertThat(headers.get(MailHeaders.SUBJECT)).isEqualTo("Test Email");
|
||||
assertThat(message.getPayload()).isEqualTo("foo\r\n\r\n");
|
||||
assertThat(message.getPayload()).isEqualTo("foo\r\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,10 @@ package org.springframework.integration.mail.config;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import javax.mail.Message.RecipientType;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -25,28 +29,31 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.integration.mail.MailHeaders;
|
||||
import org.springframework.integration.mail.MailSendingMessageHandler;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.test.mail.TestMailServer;
|
||||
import org.springframework.integration.test.mail.TestMailServer.SmtpServer;
|
||||
import org.springframework.mail.javamail.JavaMailSenderImpl;
|
||||
|
||||
import com.icegreen.greenmail.util.GreenMail;
|
||||
import com.icegreen.greenmail.util.ServerSetup;
|
||||
import com.icegreen.greenmail.util.ServerSetupTest;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
* @author Alexander Pinske
|
||||
*
|
||||
* @since 5.0
|
||||
*
|
||||
*/
|
||||
public class SmtpTests {
|
||||
|
||||
private static final SmtpServer smtpServer = TestMailServer.smtp(0);
|
||||
private static GreenMail smtpServer;
|
||||
|
||||
@BeforeAll
|
||||
public static void setup() throws InterruptedException {
|
||||
int n = 0;
|
||||
while (n++ < 100 && (!smtpServer.isListening())) {
|
||||
Thread.sleep(100);
|
||||
}
|
||||
assertThat(n < 100).isTrue();
|
||||
public static void setup() {
|
||||
ServerSetup smtp = ServerSetupTest.SMTP.dynamicPort();
|
||||
smtp.setServerStartupTimeout(10000);
|
||||
smtpServer = new GreenMail(smtp);
|
||||
smtpServer.setUser("user", "pw");
|
||||
smtpServer.start();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
@@ -58,7 +65,7 @@ public class SmtpTests {
|
||||
public void testSmtp() throws Exception {
|
||||
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
|
||||
mailSender.setHost("localhost");
|
||||
mailSender.setPort(smtpServer.getPort());
|
||||
mailSender.setPort(smtpServer.getSmtp().getPort());
|
||||
mailSender.setUsername("user");
|
||||
mailSender.setPassword("pw");
|
||||
MailSendingMessageHandler handler = new MailSendingMessageHandler(mailSender);
|
||||
@@ -69,19 +76,14 @@ public class SmtpTests {
|
||||
.setHeader(MailHeaders.SUBJECT, "foo")
|
||||
.build());
|
||||
|
||||
int n = 0;
|
||||
while (n++ < 100 && smtpServer.getMessages().size() == 0) {
|
||||
Thread.sleep(100);
|
||||
}
|
||||
assertThat(smtpServer.waitForIncomingEmail(10000, 1)).isTrue();
|
||||
|
||||
assertThat(smtpServer.getMessages().size() > 0).isTrue();
|
||||
String message = smtpServer.getMessages().get(0);
|
||||
assertThat(message)
|
||||
.endsWith("foo\n")
|
||||
.contains("foo@bar")
|
||||
.contains("bar@baz")
|
||||
.contains("user:user")
|
||||
.contains("password:pw");
|
||||
assertThat(smtpServer.getReceivedMessages().length > 0).isTrue();
|
||||
MimeMessage message = smtpServer.getReceivedMessages()[0];
|
||||
assertThat(message.getFrom()).containsOnly(new InternetAddress("foo@bar"));
|
||||
assertThat(message.getRecipients(RecipientType.TO)).containsOnly(new InternetAddress("bar@baz"));
|
||||
assertThat(message.getSubject()).isEqualTo("foo");
|
||||
assertThat(message.getContent()).asString().isEqualTo("foo\r\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ package org.springframework.integration.mail.dsl;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.mail.Flags;
|
||||
@@ -33,12 +32,12 @@ import javax.mail.search.FlagTerm;
|
||||
import javax.mail.search.FromTerm;
|
||||
import javax.mail.search.SearchTerm;
|
||||
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.SmartLifecycle;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.integration.IntegrationMessageHeaderAccessor;
|
||||
@@ -51,10 +50,6 @@ import org.springframework.integration.mail.MailHeaders;
|
||||
import org.springframework.integration.mail.support.DefaultMailHeaderMapper;
|
||||
import org.springframework.integration.mapping.HeaderMapper;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.test.mail.TestMailServer;
|
||||
import org.springframework.integration.test.mail.TestMailServer.ImapServer;
|
||||
import org.springframework.integration.test.mail.TestMailServer.Pop3Server;
|
||||
import org.springframework.integration.test.mail.TestMailServer.SmtpServer;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
@@ -64,31 +59,41 @@ import org.springframework.messaging.PollableChannel;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
|
||||
import com.icegreen.greenmail.util.GreenMail;
|
||||
import com.icegreen.greenmail.util.GreenMailUtil;
|
||||
import com.icegreen.greenmail.util.ServerSetup;
|
||||
import com.icegreen.greenmail.util.ServerSetupTest;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
* @author Alexander Pinske
|
||||
*/
|
||||
@SpringJUnitConfig
|
||||
@DirtiesContext
|
||||
public class MailTests {
|
||||
|
||||
private static final SmtpServer smtpServer = TestMailServer.smtp(0);
|
||||
|
||||
private static final Pop3Server pop3Server = TestMailServer.pop3(0);
|
||||
|
||||
private static final ImapServer imapServer = TestMailServer.imap(0);
|
||||
|
||||
private static final ImapServer imapIdleServer = TestMailServer.imap(0);
|
||||
|
||||
private static GreenMail mailServer;
|
||||
|
||||
@BeforeAll
|
||||
public static void setup() throws InterruptedException {
|
||||
int n = 0;
|
||||
while (n++ < 100 && (!smtpServer.isListening() || !pop3Server.isListening()
|
||||
|| !imapServer.isListening()) || !imapIdleServer.isListening()) {
|
||||
Thread.sleep(100);
|
||||
}
|
||||
assertThat(n < 100).isTrue();
|
||||
public static void setup() {
|
||||
ServerSetup smtp = ServerSetupTest.SMTP.dynamicPort();
|
||||
smtp.setServerStartupTimeout(10000);
|
||||
ServerSetup imap = ServerSetupTest.IMAP.dynamicPort();
|
||||
imap.setServerStartupTimeout(10000);
|
||||
ServerSetup pop3 = ServerSetupTest.POP3.dynamicPort();
|
||||
pop3.setServerStartupTimeout(10000);
|
||||
mailServer = new GreenMail(new ServerSetup[]{ smtp, pop3, imap });
|
||||
mailServer.setUser("bar@baz", "smtpuser", "pw");
|
||||
mailServer.setUser("popuser", "pw");
|
||||
mailServer.setUser("imapuser", "pw");
|
||||
mailServer.setUser("imapidleuser", "pw");
|
||||
mailServer.start();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void tearDown() {
|
||||
mailServer.stop();
|
||||
}
|
||||
|
||||
@Autowired
|
||||
@@ -120,56 +125,72 @@ public class MailTests {
|
||||
|
||||
this.sendMailChannel.send(MessageBuilder.withPayload("foo").build());
|
||||
|
||||
int n = 0;
|
||||
while (n++ < 100 && smtpServer.getMessages().size() == 0) {
|
||||
Thread.sleep(100);
|
||||
}
|
||||
mailServer.waitForIncomingEmail(10000, 1);
|
||||
|
||||
assertThat(smtpServer.getMessages().size() > 0).isTrue();
|
||||
String message = smtpServer.getMessages().get(0);
|
||||
assertThat(message).endsWith("foo\n");
|
||||
assertThat(message).contains("foo@bar");
|
||||
assertThat(message).contains("bar@baz");
|
||||
assertThat(message).contains("user:user");
|
||||
assertThat(message).contains("password:pw");
|
||||
assertThat(mailServer.getReceivedMessagesForDomain("baz").length > 0).isTrue();
|
||||
MimeMessage message = mailServer.getReceivedMessagesForDomain("baz")[0];
|
||||
assertThat(message.getFrom()).containsOnly(new InternetAddress("foo@bar"));
|
||||
assertThat(message.getRecipients(RecipientType.TO)).containsOnly(new InternetAddress("bar@baz"));
|
||||
assertThat(message.getSubject()).isEqualTo("foo");
|
||||
assertThat(message.getContent()).asString().isEqualTo("foo\r\n");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPop3() throws IOException {
|
||||
public void testPop3() throws Exception {
|
||||
MimeMessage mimeMessage =
|
||||
GreenMailUtil.createTextEmail("Foo <foo@bar>", "Bar <bar@baz>, Bar2 <bar2@baz>", "Test Email",
|
||||
"foo\r\n", mailServer.getPop3().getServerSetup());
|
||||
mimeMessage.setRecipients(RecipientType.CC, "a@b, c@d");
|
||||
mimeMessage.setRecipients(RecipientType.BCC, "e@f, g@h");
|
||||
mailServer.getUserManager().getUser("popuser").deliver(mimeMessage);
|
||||
|
||||
Message<?> message = this.pop3Channel.receive(10000);
|
||||
assertThat(message).isNotNull();
|
||||
MessageHeaders headers = message.getHeaders();
|
||||
assertThat(headers.get(MailHeaders.TO, String[].class)).containsExactly("Foo <foo@bar>");
|
||||
assertThat(headers.get(MailHeaders.FROM)).isEqualTo("Bar <bar@baz>,Bar2 <bar2@baz>");
|
||||
assertThat(headers.get(MailHeaders.SUBJECT)).isEqualTo("Test Email");
|
||||
assertThat(message.getPayload()).isEqualTo("foo\r\n\r\n");
|
||||
assertThat(message.getHeaders().containsKey(IntegrationMessageHeaderAccessor.CLOSEABLE_RESOURCE)).isTrue();
|
||||
message.getHeaders().get(IntegrationMessageHeaderAccessor.CLOSEABLE_RESOURCE, Closeable.class).close();
|
||||
assertThat(message.getPayload()).isEqualTo("foo\r\n");
|
||||
assertThat(message.getHeaders().containsKey(IntegrationMessageHeaderAccessor.CLOSEABLE_RESOURCE)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testImap() throws Exception {
|
||||
MimeMessage mimeMessage =
|
||||
GreenMailUtil.createTextEmail("Foo <foo@bar>", "Bar <bar@baz>", "Test Email", "foo\r\n",
|
||||
mailServer.getImap().getServerSetup());
|
||||
mimeMessage.setRecipients(RecipientType.CC, "a@b, c@d");
|
||||
mimeMessage.setRecipients(RecipientType.BCC, "e@f, g@h");
|
||||
mailServer.getUserManager().getUser("imapuser").deliver(mimeMessage);
|
||||
|
||||
Message<?> message = this.imapChannel.receive(10000);
|
||||
assertThat(message).isNotNull();
|
||||
MimeMessage mm = (MimeMessage) message.getPayload();
|
||||
assertThat(mm.getRecipients(RecipientType.TO)[0].toString()).isEqualTo("Foo <foo@bar>");
|
||||
assertThat(mm.getFrom()[0].toString()).isEqualTo("Bar <bar@baz>");
|
||||
assertThat(mm.getSubject()).isEqualTo("Test Email");
|
||||
assertThat(mm.getContent()).isEqualTo(TestMailServer.MailServer.MailHandler.BODY + "\r\n");
|
||||
assertThat(mm.getContent()).isEqualTo("foo\r\n");
|
||||
assertThat(message.getHeaders().containsKey(IntegrationMessageHeaderAccessor.CLOSEABLE_RESOURCE)).isTrue();
|
||||
message.getHeaders().get(IntegrationMessageHeaderAccessor.CLOSEABLE_RESOURCE, Closeable.class).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testImapIdle() {
|
||||
public void testImapIdle() throws Exception {
|
||||
MimeMessage mimeMessage =
|
||||
GreenMailUtil.createTextEmail("Foo <foo@bar>", "Bar <bar@baz>", "Test Email", "foo\r\n",
|
||||
mailServer.getImap().getServerSetup());
|
||||
mimeMessage.setRecipients(RecipientType.CC, "a@b, c@d");
|
||||
mimeMessage.setRecipients(RecipientType.BCC, "e@f, g@h");
|
||||
mailServer.getUserManager().getUser("imapidleuser").deliver(mimeMessage);
|
||||
|
||||
Message<?> message = this.imapIdleChannel.receive(10000);
|
||||
assertThat(message).isNotNull();
|
||||
MessageHeaders headers = message.getHeaders();
|
||||
assertThat(headers.get(MailHeaders.TO, String[].class)).containsExactly("Foo <foo@bar>");
|
||||
assertThat(headers.get(MailHeaders.FROM)).isEqualTo("Bar <bar@baz>");
|
||||
assertThat(headers.get(MailHeaders.SUBJECT)).isEqualTo("Test Email");
|
||||
assertThat(message.getPayload()).isEqualTo(TestMailServer.MailServer.MailHandler.BODY + "\r\n");
|
||||
assertThat(message.getPayload()).isEqualTo("foo\r\n");
|
||||
assertThat(message.getHeaders().containsKey(IntegrationMessageHeaderAccessor.CLOSEABLE_RESOURCE)).isTrue();
|
||||
this.imapIdleAdapter.stop();
|
||||
assertThat(TestUtils.getPropertyValue(this.imapIdleAdapter, "shouldReconnectAutomatically", Boolean.class))
|
||||
@@ -180,35 +201,6 @@ public class MailTests {
|
||||
@EnableIntegration
|
||||
public static class ContextConfiguration {
|
||||
|
||||
@Bean
|
||||
public SmartLifecycle serverStopper() {
|
||||
return new SmartLifecycle() {
|
||||
|
||||
@Override
|
||||
public int getPhase() {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
smtpServer.stop();
|
||||
pop3Server.stop();
|
||||
imapServer.stop();
|
||||
imapIdleServer.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRunning() {
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow sendMailFlow() {
|
||||
return IntegrationFlows.from("sendMailChannel")
|
||||
@@ -217,8 +209,8 @@ public class MailTests {
|
||||
.from("foo@bar")
|
||||
.toFunction(m -> new String[]{ "bar@baz" }))
|
||||
.handle(Mail.outboundAdapter("localhost")
|
||||
.port(smtpServer.getPort())
|
||||
.credentials("user", "pw")
|
||||
.port(mailServer.getSmtp().getPort())
|
||||
.credentials("smtpuser", "pw")
|
||||
.protocol("smtp")
|
||||
.javaMailProperties(p -> p.put("mail.debug", "false")),
|
||||
e -> e.id("sendMailEndpoint"))
|
||||
@@ -228,9 +220,9 @@ public class MailTests {
|
||||
@Bean
|
||||
public IntegrationFlow pop3MailFlow() {
|
||||
return IntegrationFlows
|
||||
.from(Mail.pop3InboundAdapter("localhost", pop3Server.getPort(), "user", "pw")
|
||||
.from(Mail.pop3InboundAdapter("localhost", mailServer.getPop3().getPort(), "popuser", "pw")
|
||||
.javaMailProperties(p -> p.put("mail.debug", "false"))
|
||||
.autoCloseFolder(false)
|
||||
.autoCloseFolder(true)
|
||||
.headerMapper(mailHeaderMapper()),
|
||||
e -> e.autoStartup(true).poller(p -> p.fixedDelay(1000)))
|
||||
.enrichHeaders(s -> s.headerExpressions(c -> c.put(MailHeaders.SUBJECT, "payload.subject")
|
||||
@@ -242,7 +234,7 @@ public class MailTests {
|
||||
@Bean
|
||||
public IntegrationFlow imapMailFlow() {
|
||||
return IntegrationFlows
|
||||
.from(Mail.imapInboundAdapter("imap://user:pw@localhost:" + imapServer.getPort() + "/INBOX")
|
||||
.from(Mail.imapInboundAdapter("imap://imapuser:pw@localhost:" + mailServer.getImap().getPort() + "/INBOX")
|
||||
.searchTermStrategy(this::fromAndNotSeenTerm)
|
||||
.userFlag("testSIUserFlag")
|
||||
.autoCloseFolder(false)
|
||||
@@ -257,7 +249,7 @@ public class MailTests {
|
||||
@Bean
|
||||
public IntegrationFlow imapIdleFlow() {
|
||||
return IntegrationFlows
|
||||
.from(Mail.imapIdleAdapter("imap://user:pw@localhost:" + imapIdleServer.getPort() + "/INBOX")
|
||||
.from(Mail.imapIdleAdapter("imap://imapidleuser:pw@localhost:" + mailServer.getImap().getPort() + "/INBOX")
|
||||
.autoStartup(true)
|
||||
.searchTermStrategy(this::fromAndNotSeenTerm)
|
||||
.userFlag("testSIUserFlag")
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
<Loggers>
|
||||
<Logger name="org.springframework.integration" level="warn"/>
|
||||
<Logger name="org.springframework.integration.mail" level="warn"/>
|
||||
<Logger name="com.icegreen.greenmail" level="warn"/>
|
||||
<Logger name="com.sun.mail" level="warn"/>
|
||||
<Root level="warn">
|
||||
<AppenderRef ref="STDOUT" />
|
||||
</Root>
|
||||
|
||||
@@ -48,7 +48,10 @@ import org.springframework.util.Base64Utils;
|
||||
*
|
||||
* @since 5.0
|
||||
*
|
||||
* @deprecated since 5.5 in favor of GreenMail library for mail testing.
|
||||
*
|
||||
*/
|
||||
@Deprecated
|
||||
public final class TestMailServer {
|
||||
|
||||
public static SmtpServer smtp(int port) {
|
||||
|
||||
@@ -119,6 +119,7 @@ It now allows body-only rendering when a header mapper is provided.
|
||||
|
||||
Starting with version 5.2, the `autoCloseFolder` option is provided on the mail receiver.
|
||||
Setting it to `false` doesn't close the folder automatically after a fetch, but instead an `IntegrationMessageHeaderAccessor.CLOSEABLE_RESOURCE` header (see <<./message.adoc#message-header-accessor,`MessageHeaderAccessor` API>> for more information) is populated into every message to producer from the channel adapter.
|
||||
This does not work with `Pop3MailReceiver` as it relies on opening and closing the folder to get new messages.
|
||||
It is the target application's responsibility to call the `close()` on this header whenever it is necessary in the downstream flow:
|
||||
|
||||
====
|
||||
|
||||
@@ -33,6 +33,7 @@ Examples of such tools include the following:
|
||||
* Gemfire and Hazelcast can be run as real-data grid nodes in the tests.
|
||||
* The Curator Framework provides a `TestingServer` for Zookeeper interaction.
|
||||
* Apache Kafka provides admin tools to embed a Kafka Broker in the tests.
|
||||
* The GreenMail is an open source, intuitive and easy-to-use test suite of email servers for testing purposes.
|
||||
|
||||
Most of these tools and libraries are used in Spring Integration tests.
|
||||
Also, from the GitHub https://github.com/spring-projects/spring-integration[repository] (in the `test` directory of each module), you can discover ideas for how to build your own tests for integration solutions.
|
||||
@@ -97,7 +98,7 @@ private UdpSyslogReceivingChannelAdapter adapter;
|
||||
|
||||
@Autowired
|
||||
private PollableChannel sysLogs;
|
||||
...
|
||||
|
||||
@Test
|
||||
public void testSimplestUdp() throws Exception {
|
||||
int port = TestUtils.getPropertyValue(adapter1, "udpAdapter.port", Integer.class);
|
||||
@@ -145,7 +146,7 @@ PollerMetadata poller;
|
||||
|
||||
@Autowired
|
||||
OnlyOnceTrigger testTrigger;
|
||||
...
|
||||
|
||||
@Test
|
||||
@DirtiesContext
|
||||
public void testWithEntityClass() throws Exception {
|
||||
@@ -363,7 +364,7 @@ assertEquals("FOO", receive.getPayload());
|
||||
Unlike the Mockito `MessageSource` mock object, the `MockMessageHandler` is a regular `AbstractMessageProducingHandler` extension with a chain API to stub handling for incoming messages.
|
||||
The `MockMessageHandler` provides `handleNext(Consumer<Message<?>>)` to specify a one-way stub for the next request message.
|
||||
It is used to mock message handlers that do not produce replies.
|
||||
`handleNextAndReply(Function<Message<?>, ?>)` is provided for performing the same stub logic for the next request message and producing a reply for it.
|
||||
The `handleNextAndReply(Function<Message<?>, ?>)` is provided for performing the same stub logic for the next request message and producing a reply for it.
|
||||
They can be chained to simulate any arbitrary request-reply scenarios for all expected request messages variants.
|
||||
These consumers and functions are applied to the incoming messages, one at a time from the stack, until the last, which is then used for all remaining messages.
|
||||
The behavior is similar to the Mockito `Answer` or `doReturn()` API.
|
||||
|
||||
Reference in New Issue
Block a user