Skip to content

Commit c20f0b6

Browse files
domi-87artembilan
authored andcommitted
Safely read expunged IMAP messages
If application is connected to a Domino mail server via IMAP, it can happen from time to time that a message is expunged. This leads to a `MessageRemovedException` when calling `IMAPMessage#getSubject`. And although debug is set to false this again leads to a `MessageException` and the whole integration flow stops. * Check for `isExpunged()` before logging a filtered message * Add `@author` * Fix debug message for expunged to reflect reality * Clean up new unit tests a bit **Cherry-pick to `5.4.x`**
1 parent d7a7bbb commit c20f0b6

File tree

2 files changed

+60
-6
lines changed

2 files changed

+60
-6
lines changed

spring-integration-mail/src/main/java/org/springframework/integration/mail/AbstractMailReceiver.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2020 the original author or authors.
2+
* Copyright 2002-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -64,6 +64,7 @@
6464
* @author Oleg Zhurakousky
6565
* @author Gary Russell
6666
* @author Artem Bilan
67+
* @author Dominik Simmen
6768
*/
6869
public abstract class AbstractMailReceiver extends IntegrationObjectSupport implements MailReceiver, DisposableBean {
6970

@@ -551,11 +552,15 @@ private MimeMessage[] filterMessagesThruSelector(Message[] messages) throws Mess
551552
this.selectorExpression.getValue(this.evaluationContext, message, Boolean.class))) {
552553
filteredMessages.add(message);
553554
}
554-
else {
555-
String subject = message.getSubject();
556-
this.logger.debug(() ->
557-
"Fetched email with subject '" + subject
558-
+ "' will be discarded by the matching filter and will not be flagged as SEEN.");
555+
else if (this.logger.isDebugEnabled()) {
556+
if (message.isExpunged()) {
557+
this.logger.debug("Expunged message discarded and will not be further processed.");
558+
}
559+
else {
560+
String subject = message.getSubject();
561+
this.logger.debug("Fetched email with subject '" + subject +
562+
"' will be discarded by the matching filter and will not be flagged as SEEN.");
563+
}
559564
}
560565
}
561566
else {

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

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import static org.mockito.Mockito.spy;
2929
import static org.mockito.Mockito.times;
3030
import static org.mockito.Mockito.verify;
31+
import static org.mockito.Mockito.when;
3132

3233
import java.io.IOException;
3334
import java.lang.reflect.Field;
@@ -91,6 +92,7 @@
9192
* @author Gary Russell
9293
* @author Artem Bilan
9394
* @author Alexander Pinske
95+
* @author Dominik Simmen
9496
*/
9597
@SpringJUnitConfig
9698
@ContextConfiguration(
@@ -309,6 +311,53 @@ public void receiveAndMarkAsReadDontDeleteFiltered() throws Exception {
309311
verify(receiver, times(0)).deleteMessages(Mockito.any());
310312
}
311313

314+
@Test
315+
public void receiveAndDebugIsDisabledNotLogFiltered() throws Exception {
316+
AbstractMailReceiver receiver = new ImapMailReceiver();
317+
318+
LogAccessor logger = spy(TestUtils.getPropertyValue(receiver, "logger", LogAccessor.class));
319+
new DirectFieldAccessor(receiver).setPropertyValue("logger", logger);
320+
when(logger.isDebugEnabled()).thenReturn(false);
321+
322+
Message msg1 = mock(MimeMessage.class);
323+
Message msg2 = mock(MimeMessage.class);
324+
Expression selectorExpression = new SpelExpressionParser().parseExpression("false");
325+
receiver.setSelectorExpression(selectorExpression);
326+
receiveAndMarkAsReadDontDeleteGuts(receiver, msg1, msg2);
327+
verify(logger, times(2)).isDebugEnabled();
328+
verify(msg1, never()).isExpunged();
329+
verify(msg2, never()).isExpunged();
330+
verify(msg1, never()).getSubject();
331+
verify(msg2, never()).getSubject();
332+
verify(logger, never()).debug(Mockito.startsWith("Expunged message received"));
333+
verify(logger, never()).debug(org.mockito.ArgumentMatchers.contains("will be discarded by the matching filter"));
334+
}
335+
336+
@Test
337+
public void receiveExpungedAndNotExpungedLogFiltered() throws Exception {
338+
AbstractMailReceiver receiver = new ImapMailReceiver();
339+
340+
LogAccessor logger = spy(TestUtils.getPropertyValue(receiver, "logger", LogAccessor.class));
341+
new DirectFieldAccessor(receiver).setPropertyValue("logger", logger);
342+
when(logger.isDebugEnabled()).thenReturn(true);
343+
344+
Message msg1 = mock(MimeMessage.class);
345+
Message msg2 = mock(MimeMessage.class);
346+
given(msg1.isExpunged()).willReturn(true);
347+
given(msg1.getSubject()).willReturn("msg1");
348+
given(msg2.getSubject()).willReturn("msg2");
349+
Expression selectorExpression = new SpelExpressionParser().parseExpression("false");
350+
receiver.setSelectorExpression(selectorExpression);
351+
receiveAndMarkAsReadDontDeleteGuts(receiver, msg1, msg2);
352+
verify(logger, times(2)).isDebugEnabled();
353+
verify(msg1).isExpunged();
354+
verify(msg2).isExpunged();
355+
verify(msg1, never()).getSubject();
356+
verify(msg2).getSubject();
357+
verify(logger).debug(Mockito.startsWith("Expunged message discarded"));
358+
verify(logger).debug(org.mockito.ArgumentMatchers.contains("'msg2' will be discarded by the matching filter"));
359+
}
360+
312361

313362
@Test
314363
public void receiveMarkAsReadAndDelete() throws Exception {

0 commit comments

Comments
 (0)