Skip to content

Commit 802d217

Browse files
artembilangaryrussell
authored andcommitted
Close mail folder if no messages to produce
Related to https://stackoverflow.com/questions/71667731/spring-integration-mimemessage-gmail-folder-is-not-open-exception If no mail messages pulled from the folder or all of them are filtered out, there is nothing to produce downstream. Therefore, always close the folder in the end of `AbstractMailReceiver.receive()` when no messages and even if `autoCloseFolder == false` **Cherry-pick to `5.5.x`**
1 parent f013aa8 commit 802d217

File tree

3 files changed

+21
-7
lines changed

3 files changed

+21
-7
lines changed

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

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2021 the original author or authors.
2+
* Copyright 2002-2022 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.
@@ -53,6 +53,7 @@
5353
import org.springframework.util.Assert;
5454
import org.springframework.util.FileCopyUtils;
5555
import org.springframework.util.MimeTypeUtils;
56+
import org.springframework.util.ObjectUtils;
5657

5758
/**
5859
* Base class for {@link MailReceiver} implementations.
@@ -362,6 +363,7 @@ private Folder obtainFolderInstance() throws MessagingException {
362363
public Object[] receive() throws jakarta.mail.MessagingException {
363364
this.folderReadLock.lock(); // NOSONAR - guarded with the getReadHoldCount()
364365
try {
366+
Object[] messagesToReturn = null;
365367
try {
366368
Folder folderToCheck = getFolder();
367369
if (folderToCheck == null || !folderToCheck.isOpen()) {
@@ -375,10 +377,11 @@ public Object[] receive() throws jakarta.mail.MessagingException {
375377
this.folderWriteLock.unlock();
376378
}
377379
}
378-
return convertMessagesIfNecessary(searchAndFilterMessages());
380+
messagesToReturn = convertMessagesIfNecessary(searchAndFilterMessages());
381+
return messagesToReturn;
379382
}
380383
finally {
381-
if (this.autoCloseFolder) {
384+
if (this.autoCloseFolder || ObjectUtils.isEmpty(messagesToReturn)) {
382385
closeFolder();
383386
}
384387
}

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

+12-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2021 the original author or authors.
2+
* Copyright 2014-2022 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.
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.integration.mail;
1818

19+
import static org.assertj.core.api.Assertions.assertThat;
20+
import static org.mockito.ArgumentMatchers.anyBoolean;
1921
import static org.mockito.Mockito.doNothing;
2022
import static org.mockito.Mockito.doReturn;
2123
import static org.mockito.Mockito.mock;
@@ -46,31 +48,37 @@
4648
public class MailReceiverTests {
4749

4850
@Test
49-
public void testStoreConnect() throws Exception {
51+
public void testStoreConnectAndFolderCloseWhenNoMessages() throws Exception {
5052
AbstractMailReceiver receiver = new AbstractMailReceiver() {
5153

5254
@Override
5355
protected Message[] searchForNewMessages() {
54-
return null;
56+
return new Message[0];
5557
}
5658

5759
};
5860
Properties props = new Properties();
5961
Session session = Session.getInstance(props);
6062
receiver.setSession(session);
6163
receiver.setProtocol("imap");
64+
receiver.setAutoCloseFolder(false);
6265
Store store = session.getStore("imap");
6366
store = spy(store);
6467
new DirectFieldAccessor(receiver).setPropertyValue("store", store);
6568
when(store.isConnected()).thenReturn(false);
6669
Folder folder = mock(Folder.class);
6770
when(folder.exists()).thenReturn(true);
68-
when(folder.isOpen()).thenReturn(false);
71+
when(folder.isOpen()).thenReturn(false, true);
6972
doReturn(folder).when(store).getFolder((URLName) null);
7073
doNothing().when(store).connect();
7174
receiver.openFolder();
7275
receiver.openFolder();
7376
verify(store, times(2)).connect();
77+
78+
Object[] receive = receiver.receive();
79+
assertThat(receive).isEmpty();
80+
81+
verify(folder).close(anyBoolean());
7482
}
7583

7684
}

src/reference/asciidoc/mail.adoc

+3
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,9 @@ This functionality is enabled with this combination of options: no `headerMapper
140140
The `MimeMessage` is present as the payload of the Spring message produced.
141141
In this case, the only header populated is the mentioned above `IntegrationMessageHeaderAccessor.CLOSEABLE_RESOURCE` for the folder which must be closed when processing of the `MimeMessage` is complete.
142142

143+
Starting with version 5.5.11, the folder is closed automatically after `AbstractMailReceiver.receive()` if no messages received or all of them are filtered out independently of the `autoCloseFolder` flag.
144+
In this case there is nothing to produce downstream for possible logic around `IntegrationMessageHeaderAccessor.CLOSEABLE_RESOURCE` header.
145+
143146
[[mail-mapping]]
144147
=== Inbound Mail Message Mapping
145148

0 commit comments

Comments
 (0)