GH-8577: Revise ImapIdleChannelAdapter logic (#8588)

* GH-8577: Revise `ImapIdleChannelAdapter` logic

Fixes https://github.com/spring-projects/spring-integration/issues/8577

When we process mail messages in async manner, it is possible that we end up
in a race condition situation where the next idle cycle closes the folder.

It is possible to reopen the folder, but feels better to block the current idle
cycle until we are done with the message and therefore keep folder opened.

* Deprecate `ImapIdleChannelAdapter.sendingTaskExecutor` in favor of an `ExecutorChannel`
as an output for this channel adapter or similar async hand-off downstream.
* Make use of `shouldReconnectAutomatically` as it is advertised for this channel adapter
* Optimize the proxy creation for message sending task

* * Remove `ImapIdleChannelAdapter.sendingTaskExecutor`

* Fix language in docs

Co-authored-by: Gary Russell <grussell@vmware.com>

---------

Co-authored-by: Gary Russell <grussell@vmware.com>
This commit is contained in:
Artem Bilan
2023-03-29 10:15:47 -04:00
committed by GitHub
parent 22d47e72e9
commit 4fdbdf180e
9 changed files with 125 additions and 131 deletions

View File

@@ -85,7 +85,7 @@ MailReceiver receiver = new Pop3MailReceiver("pop3://usr:pwd@localhost/INBOX");
Another option for receiving mail is the IMAP `idle` command (if supported by your mail server).
Spring Integration provides the `ImapIdleChannelAdapter`, which is itself a message-producing endpoint.
It delegates to an instance of the `ImapMailReceiver` but enables asynchronous reception of mail messages.
It delegates to an instance of the `ImapMailReceiver`.
The next section has examples of configuring both types of inbound channel adapter with Spring Integration's namespace support in the 'mail' schema.
[[imap-format-important]]
@@ -143,6 +143,10 @@ In this case, the only header populated is the mentioned above `IntegrationMessa
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.
In this case there is nothing to produce downstream for possible logic around `IntegrationMessageHeaderAccessor.CLOSEABLE_RESOURCE` header.
Starting with version 6.0.5, the `ImapIdleChannelAdapter` no longer performs asynchronous message publishing.
This is necessary to block the idle listener loop for message processing downstream (e.g. with big attachments) because the mail folder must remain open.
If an async hand-off is required, an `ExecutorChannel` can be used as the output channel of this channel adapter.
[[mail-mapping]]
=== Inbound Mail Message Mapping
@@ -428,7 +432,7 @@ IMPORTANT: In both configurations, `channel` and `should-delete-messages` are re
You should understand why `should-delete-messages` is required.
The issue is with the POP3 protocol, which does not have any knowledge of messages that were read.
It can only know what has been read within a single session.
This means that, when your POP3 mail adapter runs, emails are successfully consumed as as they become available during each poll and no single email message is delivered more then once.
This means that, when your POP3 mail adapter runs, emails are successfully consumed as they become available during each poll and no single email message is delivered more then once.
However, as soon as you restart your adapter and begin a new session, all the email messages that might have been retrieved in the previous session are retrieved again.
That is the nature of POP3.
Some might argue that `should-delete-messages` should be `true` by default.
@@ -563,7 +567,7 @@ The following example shows what the `Mover` class might look like:
----
public class Mover {
public void process(MimeMessage message) throws Exception{
public void process(MimeMessage message) throws Exception {
Folder folder = message.getFolder();
folder.open(Folder.READ_WRITE);
String messageId = message.getMessageID();
@@ -581,7 +585,7 @@ public class Mover {
}
}
Folder somethingFolder = store.getFolder("SOMETHING"));
Folder somethingFolder = store.getFolder("SOMETHING");
somethingFolder.appendMessages(new MimeMessage[]{message});
folder.expunge();
folder.close(true);
@@ -634,7 +638,7 @@ public class MailApplication {
.handle(Mail.outboundAdapter("gmail")
.port(smtpServer.getPort())
.credentials("user", "pw")
.protocol("smtp")),
.protocol("smtp"),
e -> e.id("sendMailEndpoint"))
.get();
}

View File

@@ -47,3 +47,9 @@ See <<./web-sockets.adoc#web-socket-overview, WebSocket Overview>> for more info
The `JmsInboundGateway`, via its `ChannelPublishingJmsMessageListener`, can now be configured with a `replyToExpression` to resolve a reply destination against the request message at runtime.
See <<./jms.adoc#jms-inbound-gateway, JMS Inbound Gateway>> for more information.
[[x6.1-mail]]
=== Mail Changes
The (previously deprecated) `ImapIdleChannelAdapter.sendingTaskExecutor` property has been removed in favor of an asynchronous message process downstream in the flow.
See <<./mail.adoc#mail-inbound, Mail-receiving Channel Adapter>> for more information.