Skip to content

Commit c189a12

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 b12540d commit c189a12

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;
@@ -100,6 +101,7 @@
100101
* @author Gary Russell
101102
* @author Artem Bilan
102103
* @author Alexander Pinske
104+
* @author Dominik Simmen
103105
*/
104106
@SpringJUnitConfig
105107
@ContextConfiguration(
@@ -336,6 +338,53 @@ public void receiveAndMarkAsReadDontDeleteFiltered() throws Exception {
336338
verify(receiver, times(0)).deleteMessages(Mockito.any());
337339
}
338340

341+
@Test
342+
public void receiveAndDebugIsDisabledNotLogFiltered() throws Exception {
343+
AbstractMailReceiver receiver = new ImapMailReceiver();
344+
345+
LogAccessor logger = spy(TestUtils.getPropertyValue(receiver, "logger", LogAccessor.class));
346+
new DirectFieldAccessor(receiver).setPropertyValue("logger", logger);
347+
when(logger.isDebugEnabled()).thenReturn(false);
348+
349+
Message msg1 = mock(MimeMessage.class);
350+
Message msg2 = mock(MimeMessage.class);
351+
Expression selectorExpression = new SpelExpressionParser().parseExpression("false");
352+
receiver.setSelectorExpression(selectorExpression);
353+
receiveAndMarkAsReadDontDeleteGuts(receiver, msg1, msg2);
354+
verify(logger, times(2)).isDebugEnabled();
355+
verify(msg1, never()).isExpunged();
356+
verify(msg2, never()).isExpunged();
357+
verify(msg1, never()).getSubject();
358+
verify(msg2, never()).getSubject();
359+
verify(logger, never()).debug(Mockito.startsWith("Expunged message received"));
360+
verify(logger, never()).debug(org.mockito.ArgumentMatchers.contains("will be discarded by the matching filter"));
361+
}
362+
363+
@Test
364+
public void receiveExpungedAndNotExpungedLogFiltered() throws Exception {
365+
AbstractMailReceiver receiver = new ImapMailReceiver();
366+
367+
LogAccessor logger = spy(TestUtils.getPropertyValue(receiver, "logger", LogAccessor.class));
368+
new DirectFieldAccessor(receiver).setPropertyValue("logger", logger);
369+
when(logger.isDebugEnabled()).thenReturn(true);
370+
371+
Message msg1 = mock(MimeMessage.class);
372+
Message msg2 = mock(MimeMessage.class);
373+
given(msg1.isExpunged()).willReturn(true);
374+
given(msg1.getSubject()).willReturn("msg1");
375+
given(msg2.getSubject()).willReturn("msg2");
376+
Expression selectorExpression = new SpelExpressionParser().parseExpression("false");
377+
receiver.setSelectorExpression(selectorExpression);
378+
receiveAndMarkAsReadDontDeleteGuts(receiver, msg1, msg2);
379+
verify(logger, times(2)).isDebugEnabled();
380+
verify(msg1).isExpunged();
381+
verify(msg2).isExpunged();
382+
verify(msg1, never()).getSubject();
383+
verify(msg2).getSubject();
384+
verify(logger).debug(Mockito.startsWith("Expunged message discarded"));
385+
verify(logger).debug(org.mockito.ArgumentMatchers.contains("'msg2' will be discarded by the matching filter"));
386+
}
387+
339388

340389
@Test
341390
public void receiveMarkAsReadAndDelete() throws Exception {

0 commit comments

Comments
 (0)