Skip to content

Commit 996daca

Browse files
apinskeartembilan
authored andcommitted
GH-3451: Use GreenMail for testing instead
Fixes #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)
1 parent 13005df commit 996daca

File tree

9 files changed

+223
-140
lines changed

9 files changed

+223
-140
lines changed

build.gradle

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ ext {
6060
derbyVersion = '10.14.2.0'
6161
ftpServerVersion = '1.1.1'
6262
googleJsr305Version = '3.0.2'
63+
greenmailVersion = '1.6.4'
6364
groovyVersion = '3.0.8'
6465
hamcrestVersion = '2.2'
6566
hazelcastVersion = '4.2'
@@ -641,9 +642,9 @@ project('spring-integration-mail') {
641642
api project(':spring-integration-core')
642643
api 'org.springframework:spring-context-support'
643644

644-
providedImplementation "jakarta.mail:jakarta.mail-api:$mailVersion"
645-
providedImplementation "com.sun.mail:imap:$mailVersion"
646645
providedImplementation "com.sun.mail:jakarta.mail:$mailVersion"
646+
testImplementation "com.icegreen:greenmail:$greenmailVersion"
647+
testRuntimeOnly 'org.apache.logging.log4j:log4j-jul'
647648
}
648649
}
649650

spring-integration-mail/src/test/java/org/springframework/integration/mail/ImapMailReceiverTests.java

Lines changed: 90 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,18 @@
3131

3232
import java.io.IOException;
3333
import java.lang.reflect.Field;
34+
import java.util.ArrayList;
3435
import java.util.Arrays;
36+
import java.util.List;
3537
import java.util.Properties;
3638
import java.util.concurrent.CountDownLatch;
3739
import java.util.concurrent.TimeUnit;
3840
import java.util.concurrent.atomic.AtomicInteger;
3941
import java.util.concurrent.atomic.AtomicReference;
42+
import java.util.logging.Handler;
43+
import java.util.logging.Level;
44+
import java.util.logging.LogManager;
45+
import java.util.logging.LogRecord;
4046

4147
import javax.mail.Flags;
4248
import javax.mail.Flags.Flag;
@@ -72,8 +78,6 @@
7278
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
7379
import org.springframework.integration.history.MessageHistory;
7480
import org.springframework.integration.mail.support.DefaultMailHeaderMapper;
75-
import org.springframework.integration.test.mail.TestMailServer;
76-
import org.springframework.integration.test.mail.TestMailServer.ImapServer;
7781
import org.springframework.integration.test.util.TestUtils;
7882
import org.springframework.messaging.MessageHeaders;
7983
import org.springframework.messaging.PollableChannel;
@@ -84,6 +88,11 @@
8488
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
8589
import org.springframework.util.MimeTypeUtils;
8690

91+
import com.icegreen.greenmail.user.GreenMailUser;
92+
import com.icegreen.greenmail.util.GreenMail;
93+
import com.icegreen.greenmail.util.GreenMailUtil;
94+
import com.icegreen.greenmail.util.ServerSetup;
95+
import com.icegreen.greenmail.util.ServerSetupTest;
8796
import com.sun.mail.imap.IMAPFolder;
8897

8998
/**
@@ -100,31 +109,43 @@ public class ImapMailReceiverTests {
100109

101110
private AtomicInteger failed;
102111

103-
private ImapServer imapIdleServer;
112+
private GreenMail imapIdleServer;
113+
114+
private GreenMailUser user;
104115

105116
@Autowired
106117
private ApplicationContext context;
107118

119+
static {
120+
System.setProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager");
121+
}
122+
123+
private final ImapSearchLoggingHandler imapSearches = new ImapSearchLoggingHandler();
124+
108125
@BeforeEach
109-
public void setup() throws InterruptedException {
126+
public void setup() {
127+
LogManager.getLogManager().getLogger("").setLevel(Level.ALL);
128+
imapSearches.searches.clear();
129+
imapSearches.stores.clear();
130+
LogManager.getLogManager().getLogger("").addHandler(imapSearches);
110131
failed = new AtomicInteger(0);
111-
this.imapIdleServer = TestMailServer.imap(0);
112-
int n = 0;
113-
while (n++ < 100 && (!this.imapIdleServer.isListening())) {
114-
Thread.sleep(100);
115-
}
116-
assertThat(n < 100).isTrue();
132+
ServerSetup imap = ServerSetupTest.IMAP.dynamicPort();
133+
imap.setServerStartupTimeout(10000);
134+
imapIdleServer = new GreenMail(imap);
135+
user = imapIdleServer.setUser("user", "pw");
136+
imapIdleServer.start();
117137
}
118138

119139
@AfterEach
120140
public void tearDown() {
121141
this.imapIdleServer.stop();
142+
LogManager.getLogManager().getLogger("").removeHandler(imapSearches);
122143
}
123144

124145
@Test
125146
public void testIdleWithServerCustomSearch() throws Exception {
126147
ImapMailReceiver receiver =
127-
new ImapMailReceiver("imap://user:pw@localhost:" + this.imapIdleServer.getPort() + "/INBOX");
148+
new ImapMailReceiver("imap://user:pw@localhost:" + this.imapIdleServer.getImap().getPort() + "/INBOX");
128149
receiver.setSearchTermStrategy((supportedFlags, folder) -> {
129150
try {
130151
FromTerm fromTerm = new FromTerm(new InternetAddress("bar@baz"));
@@ -140,32 +161,32 @@ public void testIdleWithServerCustomSearch() throws Exception {
140161
@Test
141162
public void testIdleWithServerDefaultSearch() throws Exception {
142163
ImapMailReceiver receiver =
143-
new ImapMailReceiver("imap://user:pw@localhost:" + this.imapIdleServer.getPort() + "/INBOX");
164+
new ImapMailReceiver("imap://user:pw@localhost:" + this.imapIdleServer.getImap().getPort() + "/INBOX");
144165
testIdleWithServerGuts(receiver, false);
145-
assertThat(this.imapIdleServer.assertReceived("searchWithUserFlag")).isTrue();
166+
assertThat(imapSearches.searches.get(0)).contains("testSIUserFlag");
146167
}
147168

148169
@Test
149170
public void testIdleWithMessageMapping() throws Exception {
150171
ImapMailReceiver receiver =
151-
new ImapMailReceiver("imap://user:pw@localhost:" + this.imapIdleServer.getPort() + "/INBOX");
172+
new ImapMailReceiver("imap://user:pw@localhost:" + this.imapIdleServer.getImap().getPort() + "/INBOX");
152173
receiver.setHeaderMapper(new DefaultMailHeaderMapper());
153174
testIdleWithServerGuts(receiver, true);
154175
}
155176

156177
@Test
157178
public void testIdleWithServerDefaultSearchSimple() throws Exception {
158179
ImapMailReceiver receiver =
159-
new ImapMailReceiver("imap://user:pw@localhost:" + this.imapIdleServer.getPort() + "/INBOX");
180+
new ImapMailReceiver("imap://user:pw@localhost:" + this.imapIdleServer.getImap().getPort() + "/INBOX");
160181
receiver.setSimpleContent(true);
161182
testIdleWithServerGuts(receiver, false, true);
162-
assertThat(this.imapIdleServer.assertReceived("searchWithUserFlag")).isTrue();
183+
assertThat(imapSearches.searches.get(0)).contains("testSIUserFlag");
163184
}
164185

165186
@Test
166187
public void testIdleWithMessageMappingSimple() throws Exception {
167188
ImapMailReceiver receiver =
168-
new ImapMailReceiver("imap://user:pw@localhost:" + this.imapIdleServer.getPort() + "/INBOX");
189+
new ImapMailReceiver("imap://user:pw@localhost:" + this.imapIdleServer.getImap().getPort() + "/INBOX");
169190
receiver.setSimpleContent(true);
170191
receiver.setHeaderMapper(new DefaultMailHeaderMapper());
171192
testIdleWithServerGuts(receiver, true, true);
@@ -176,10 +197,6 @@ public void testIdleWithServerGuts(ImapMailReceiver receiver, boolean mapped) th
176197
}
177198

178199
public void testIdleWithServerGuts(ImapMailReceiver receiver, boolean mapped, boolean simple) throws Exception {
179-
Properties mailProps = new Properties();
180-
mailProps.put("mail.debug", "true");
181-
mailProps.put("mail.imap.connectionpool.debug", "true");
182-
receiver.setJavaMailProperties(mailProps);
183200
receiver.setMaxFetchSize(1);
184201
receiver.setShouldDeleteMessages(false);
185202
receiver.setShouldMarkMessagesAsRead(true);
@@ -193,6 +210,14 @@ public void testIdleWithServerGuts(ImapMailReceiver receiver, boolean mapped, bo
193210
adapter.setTaskScheduler(taskScheduler);
194211
adapter.setReconnectDelay(1);
195212
adapter.start();
213+
MimeMessage message =
214+
GreenMailUtil.createTextEmail("Foo <foo@bar>", "Bar <bar@baz>", "Test Email", "foo\r\n",
215+
imapIdleServer.getImap().getServerSetup());
216+
message.setRecipients(Message.RecipientType.CC, "a@b, c@d");
217+
message.setRecipients(Message.RecipientType.BCC, "e@f, g@h");
218+
user.deliver(message);
219+
user.deliver(GreenMailUtil.createTextEmail("to", "Bar <bar@baz>", "subject", "body",
220+
imapIdleServer.getImap().getServerSetup()));
196221
if (!mapped) {
197222
@SuppressWarnings("unchecked")
198223
org.springframework.messaging.Message<MimeMessage> received =
@@ -202,19 +227,19 @@ public void testIdleWithServerGuts(ImapMailReceiver receiver, boolean mapped, bo
202227
assertThat(received.getPayload().getLineCount() > -1).isTrue();
203228
if (simple) {
204229
assertThat(received.getPayload().getContent())
205-
.isEqualTo(TestMailServer.MailServer.MailHandler.BODY + "\r\n");
230+
.isEqualTo("foo\r\n");
206231
}
207232
else {
208233
assertThat(received.getPayload().getContent())
209-
.isEqualTo(TestMailServer.MailServer.MailHandler.MESSAGE + "\r\n");
234+
.isEqualTo("foo");
210235
}
211236
}
212237
else {
213238
org.springframework.messaging.Message<?> received = channel.receive(10000);
214239
assertThat(received).isNotNull();
215240
MessageHeaders headers = received.getHeaders();
216241
assertThat(headers.get(MailHeaders.RAW_HEADERS)).isNotNull();
217-
assertThat(headers.get(MailHeaders.CONTENT_TYPE)).isEqualTo("TEXT/PLAIN; charset=ISO-8859-1");
242+
assertThat(headers.get(MailHeaders.CONTENT_TYPE)).isEqualTo("TEXT/PLAIN; charset=us-ascii");
218243
assertThat(headers.get(MessageHeaders.CONTENT_TYPE)).isEqualTo(MimeTypeUtils.TEXT_PLAIN_VALUE);
219244
assertThat(headers.get(MailHeaders.FROM)).isEqualTo("Bar <bar@baz>");
220245
String[] toHeader = headers.get(MailHeaders.TO, String[].class);
@@ -224,22 +249,24 @@ public void testIdleWithServerGuts(ImapMailReceiver receiver, boolean mapped, bo
224249
assertThat(Arrays.toString(headers.get(MailHeaders.BCC, String[].class))).isEqualTo("[e@f, g@h]");
225250
assertThat(headers.get(MailHeaders.SUBJECT)).isEqualTo("Test Email");
226251
if (simple) {
227-
assertThat(received.getPayload()).isEqualTo(TestMailServer.MailServer.MailHandler.BODY + "\r\n");
252+
assertThat(received.getPayload()).isEqualTo("foo\r\n");
228253
}
229254
else {
230-
assertThat(received.getPayload()).isEqualTo(TestMailServer.MailServer.MailHandler.MESSAGE + "\r\n");
255+
assertThat(received.getPayload()).isEqualTo("foo");
231256
}
232257
}
233258
assertThat(channel.receive(20000)).isNotNull(); // new message after idle
234259
assertThat(channel.receive(100)).isNull(); // no new message after second and third idle
235260

236261
adapter.stop();
237262
taskScheduler.shutdown();
238-
assertThat(this.imapIdleServer.assertReceived("storeUserFlag")).isTrue();
263+
assertThat(imapSearches.stores.get(0)).contains("testSIUserFlag");
239264
}
240265

241266
@Test
242267
public void receiveAndMarkAsReadDontDelete() throws Exception {
268+
user.deliver(GreenMailUtil.createTextEmail("user", "sender", "subject", "body",
269+
imapIdleServer.getImap().getServerSetup()));
243270
AbstractMailReceiver receiver = new ImapMailReceiver();
244271
Message msg1 = mock(MimeMessage.class);
245272
Message msg2 = mock(MimeMessage.class);
@@ -898,4 +925,40 @@ private void setUpScheduler(ImapMailReceiver mailReceiver, ThreadPoolTaskSchedul
898925
mailReceiver.setBeanFactory(bf);
899926
}
900927

928+
929+
private static class ImapSearchLoggingHandler extends Handler {
930+
931+
private final List<String> searches = new ArrayList<>();
932+
933+
private final List<String> stores = new ArrayList<>();
934+
935+
private static final String SEARCH = " SEARCH ";
936+
937+
private static final String STORE = " STORE ";
938+
939+
@Override
940+
public void publish(LogRecord record) {
941+
if ("com.sun.mail.imap.protocol".equals(record.getLoggerName())) {
942+
String message = record.getMessage();
943+
if (!message.startsWith("*")) {
944+
if (message.contains(SEARCH) && !message.contains(" OK ")) {
945+
searches.add(message.substring(message.indexOf(SEARCH) + SEARCH.length()));
946+
}
947+
else if (message.contains(STORE) && !message.contains(" OK ")) {
948+
stores.add(message.substring(message.indexOf(STORE) + STORE.length()));
949+
}
950+
}
951+
}
952+
}
953+
954+
@Override
955+
public void flush() {
956+
}
957+
958+
@Override
959+
public void close() throws SecurityException {
960+
}
961+
962+
}
963+
901964
}

spring-integration-mail/src/test/java/org/springframework/integration/mail/config/Pop3Tests.java

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@
2020

2121
import java.util.Arrays;
2222

23+
import javax.mail.Message.RecipientType;
24+
import javax.mail.MessagingException;
25+
import javax.mail.internet.MimeMessage;
26+
2327
import org.junit.jupiter.api.AfterAll;
2428
import org.junit.jupiter.api.BeforeAll;
2529
import org.junit.jupiter.api.Test;
@@ -28,29 +32,36 @@
2832
import org.springframework.integration.mail.MailReceivingMessageSource;
2933
import org.springframework.integration.mail.Pop3MailReceiver;
3034
import org.springframework.integration.mail.support.DefaultMailHeaderMapper;
31-
import org.springframework.integration.test.mail.TestMailServer;
32-
import org.springframework.integration.test.mail.TestMailServer.Pop3Server;
3335
import org.springframework.messaging.Message;
3436
import org.springframework.messaging.MessageHeaders;
3537

38+
import com.icegreen.greenmail.user.GreenMailUser;
39+
import com.icegreen.greenmail.util.GreenMail;
40+
import com.icegreen.greenmail.util.GreenMailUtil;
41+
import com.icegreen.greenmail.util.ServerSetup;
42+
import com.icegreen.greenmail.util.ServerSetupTest;
43+
3644
/**
3745
* @author Gary Russell
3846
* @author Artem Bilan
47+
* @author Alexander Pinske
3948
*
4049
* @since 5.0
4150
*
4251
*/
4352
public class Pop3Tests {
4453

45-
private static final Pop3Server pop3Server = TestMailServer.pop3(0);
54+
private static GreenMail pop3Server;
55+
56+
private static GreenMailUser user;
4657

4758
@BeforeAll
48-
public static void setup() throws InterruptedException {
49-
int n = 0;
50-
while (n++ < 100 && (!pop3Server.isListening())) {
51-
Thread.sleep(100);
52-
}
53-
assertThat(n < 100).isTrue();
59+
public static void setup() {
60+
ServerSetup pop3 = ServerSetupTest.POP3.dynamicPort();
61+
pop3.setServerStartupTimeout(10000);
62+
pop3Server = new GreenMail(pop3);
63+
user = pop3Server.setUser("user", "pw");
64+
pop3Server.start();
5465
}
5566

5667
@AfterAll
@@ -59,8 +70,15 @@ public static void tearDown() {
5970
}
6071

6172
@Test
62-
public void testPop3() {
63-
Pop3MailReceiver receiver = new Pop3MailReceiver("localhost", pop3Server.getPort(), "user", "pw");
73+
public void testPop3() throws MessagingException {
74+
MimeMessage mimeMessage =
75+
GreenMailUtil.createTextEmail("Foo <foo@bar>", "Bar <bar@baz>, Bar2 <bar2@baz>", "Test Email",
76+
"foo\r\n", pop3Server.getPop3().getServerSetup());
77+
mimeMessage.setRecipients(RecipientType.CC, "a@b, c@d");
78+
mimeMessage.setRecipients(RecipientType.BCC, "e@f, g@h");
79+
user.deliver(mimeMessage);
80+
81+
Pop3MailReceiver receiver = new Pop3MailReceiver("localhost", pop3Server.getPop3().getPort(), "user", "pw");
6482
receiver.setHeaderMapper(new DefaultMailHeaderMapper());
6583
MailReceivingMessageSource source = new MailReceivingMessageSource(receiver);
6684
Message<?> message = source.receive();
@@ -71,7 +89,7 @@ public void testPop3() {
7189
assertThat(Arrays.toString(headers.get(MailHeaders.BCC, String[].class))).isEqualTo("[e@f, g@h]");
7290
assertThat(headers.get(MailHeaders.FROM)).isEqualTo("Bar <bar@baz>,Bar2 <bar2@baz>");
7391
assertThat(headers.get(MailHeaders.SUBJECT)).isEqualTo("Test Email");
74-
assertThat(message.getPayload()).isEqualTo("foo\r\n\r\n");
92+
assertThat(message.getPayload()).isEqualTo("foo\r\n");
7593
}
7694

7795
}

0 commit comments

Comments
 (0)