You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2020/02/19 19:22:57 UTC

[camel] branch master updated: CAMEL-14588:New setting to allow mails to be moved after processing (#3587)

This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/master by this push:
     new 41cb193  CAMEL-14588:New setting to allow mails to be moved after processing (#3587)
41cb193 is described below

commit 41cb1934fc85239bf2c6fe01e18f63a3e5a6076a
Author: Manuel <48...@users.noreply.github.com>
AuthorDate: Wed Feb 19 20:22:44 2020 +0100

    CAMEL-14588:New setting to allow mails to be moved after processing (#3587)
---
 .../camel-mail/src/main/docs/mail-component.adoc   |   1 +
 .../camel/component/mail/MailConfiguration.java    |  15 +++
 .../apache/camel/component/mail/MailConsumer.java  |  34 +++---
 .../camel/component/mail/MailMoveToTest.java       | 119 +++++++++++++++++++++
 4 files changed, 157 insertions(+), 12 deletions(-)

diff --git a/components/camel-mail/src/main/docs/mail-component.adoc b/components/camel-mail/src/main/docs/mail-component.adoc
index 1f3fd34..5c81e46 100644
--- a/components/camel-mail/src/main/docs/mail-component.adoc
+++ b/components/camel-mail/src/main/docs/mail-component.adoc
@@ -144,6 +144,7 @@ with the following path and query parameters:
 | *bridgeErrorHandler* (consumer) | Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored. | false | boolean
 | *closeFolder* (consumer) | Whether the consumer should close the folder after polling. Setting this option to false and having disconnect=false as well, then the consumer keep the folder open between polls. | true | boolean
 | *copyTo* (consumer) | After processing a mail message, it can be copied to a mail folder with the given name. You can override this configuration value, with a header with the key copyTo, allowing you to copy messages to folder names configured at runtime. |  | String
+| *moveTo* (consumer) | After processing a mail message, it can be copied to a mail folder with the given name. You can override this configuration value, with a header with the key moveTo, allowing you to move messages to folder names configured at runtime. |  | String
 | *delete* (consumer) | Deletes the messages after they have been processed. This is done by setting the DELETED flag on the mail message. If false, the SEEN flag is set instead. As of Camel 2.10 you can override this configuration option by setting a header with the key delete to determine if the mail should be deleted or not. | false | boolean
 | *disconnect* (consumer) | Whether the consumer should disconnect after polling. If enabled this forces Camel to connect on each poll. | false | boolean
 | *handleFailedMessage* (consumer) | If the mail consumer cannot retrieve a given mail message, then this option allows to handle the caused exception by the consumer's error handler. By enable the bridge error handler on the consumer, then the Camel routing error handler can handle the exception instead. The default behavior would be the consumer throws an exception and no mails from the batch would be able to be routed by Camel. | false | boolean
diff --git a/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailConfiguration.java b/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailConfiguration.java
index 7637168..8e9a334 100644
--- a/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailConfiguration.java
+++ b/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailConfiguration.java
@@ -76,6 +76,8 @@ public class MailConfiguration implements Cloneable {
     private boolean delete;
     @UriParam @Metadata(label = "consumer")
     private String copyTo;
+    @UriParam @Metadata(label = "consumer")
+    private String moveTo;
     @UriParam(defaultValue = "true") @Metadata(label = "consumer")
     private boolean unseen = true;
     @UriParam(label = "advanced")
@@ -675,6 +677,19 @@ public class MailConfiguration implements Cloneable {
         return copyTo;
     }
 
+    public String getMoveTo() {
+        return moveTo;
+    }
+
+    /**
+     * After processing a mail message, it can be moved to a mail folder with the given name.
+     * You can override this configuration value, with a header with the key moveTo, allowing you to move messages
+     * to folder names configured at runtime.
+     */
+    public void setMoveTo(String moveTo) {
+        this.moveTo = moveTo;
+    }
+
     /**
      * After processing a mail message, it can be copied to a mail folder with the given name.
      * You can override this configuration value, with a header with the key copyTo, allowing you to copy messages
diff --git a/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailConsumer.java b/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailConsumer.java
index aad7939..1945180 100644
--- a/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailConsumer.java
+++ b/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailConsumer.java
@@ -472,27 +472,19 @@ public class MailConsumer extends ScheduledBatchPollingConsumer {
             MailConfiguration config = getEndpoint().getConfiguration();
             // header values override configuration values
             String copyTo = in.getHeader("copyTo", config.getCopyTo(), String.class);
+            String moveTo = in.getHeader("moveTo", config.getMoveTo(), String.class);
             boolean delete = in.getHeader("delete", config.isDelete(), boolean.class);
 
-            // Copy message into different imap folder if asked
-            if (config.getProtocol().equals(MailUtils.PROTOCOL_IMAP) || config.getProtocol().equals(MailUtils.PROTOCOL_IMAPS)) {
-                if (copyTo != null) {
-                    LOG.trace("IMAP message needs to be copied to {}", copyTo);
-                    Folder destFolder = store.getFolder(copyTo);
-                    if (!destFolder.exists()) {
-                        destFolder.create(Folder.HOLDS_MESSAGES);
-                    }
-                    folder.copyMessages(new Message[]{mail}, destFolder);
-                    LOG.trace("IMAP message {} copied to {}", mail, copyTo);
-                }
-            }
+            copyOrMoveMessageIfRequired(config, mail, copyTo, false);
 
             if (delete) {
                 LOG.trace("Exchange processed, so flagging message as DELETED");
+                copyOrMoveMessageIfRequired(config, mail, moveTo, true);
                 mail.setFlag(Flags.Flag.DELETED, true);
             } else {
                 LOG.trace("Exchange processed, so flagging message as SEEN");
                 mail.setFlag(Flags.Flag.SEEN, true);
+                copyOrMoveMessageIfRequired(config, mail, moveTo, true);
             }
 
             // need to confirm or remove on commit at last
@@ -509,6 +501,24 @@ public class MailConsumer extends ScheduledBatchPollingConsumer {
         }
     }
 
+
+    private void copyOrMoveMessageIfRequired(MailConfiguration config, Message mail, String destinationFolder, boolean moveMessage) throws MessagingException {
+        if (config.getProtocol().equals(MailUtils.PROTOCOL_IMAP) || config.getProtocol().equals(MailUtils.PROTOCOL_IMAPS)) {
+            if (destinationFolder != null) {
+                LOG.trace("IMAP message needs to be {} to {}", moveMessage ? "moved" : "copied", destinationFolder);
+                Folder destFolder = store.getFolder(destinationFolder);
+                if (!destFolder.exists()) {
+                    destFolder.create(Folder.HOLDS_MESSAGES);
+                }
+                folder.copyMessages(new Message[]{mail}, destFolder);
+                if (moveMessage) {
+                    mail.setFlag(Flags.Flag.DELETED, true);
+                }
+                LOG.trace("IMAP message {} {} to {}", mail, moveMessage ? "moved" : "copied", destinationFolder);
+            }
+        }
+    }
+
     /**
      * Strategy when processing the exchange failed.
      *
diff --git a/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailMoveToTest.java b/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailMoveToTest.java
new file mode 100644
index 0000000..83daae5
--- /dev/null
+++ b/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailMoveToTest.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.mail;
+
+import javax.mail.Flags;
+import javax.mail.Folder;
+import javax.mail.Message;
+import javax.mail.Store;
+import javax.mail.internet.MimeMessage;
+
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.jvnet.mock_javamail.Mailbox;
+
+/**
+ * Unit test for moveTo.
+ */
+public class MailMoveToTest extends CamelTestSupport {
+
+    @Override
+    @Before
+    public void setUp() throws Exception {
+        prepareMailbox();
+        super.setUp();
+    }
+
+    @Test
+    public void testMoveToWithMarkAsSeen() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(5);
+        assertMockEndpointsSatisfied();
+
+        Thread.sleep(500);
+
+        assertEquals(0, Mailbox.get("jones@localhost").size());
+        assertEquals(0, Mailbox.get("jones@localhost").getNewMessageCount());
+        assertEquals(5, Mailbox.get("moveToFolder-jones@localhost").getNewMessageCount());
+
+        Assert.assertTrue(Mailbox.get("moveToFolder-jones@localhost").get(0).getFlags().contains(Flags.Flag.SEEN));
+        Assert.assertTrue(Mailbox.get("moveToFolder-jones@localhost").get(1).getFlags().contains(Flags.Flag.SEEN));
+        Assert.assertTrue(Mailbox.get("moveToFolder-jones@localhost").get(2).getFlags().contains(Flags.Flag.SEEN));
+        Assert.assertTrue(Mailbox.get("moveToFolder-jones@localhost").get(3).getFlags().contains(Flags.Flag.SEEN));
+        Assert.assertTrue(Mailbox.get("moveToFolder-jones@localhost").get(4).getFlags().contains(Flags.Flag.SEEN));
+    }
+
+    @Test
+    public void testMoveToWithDelete() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:result2");
+        mock.expectedMessageCount(5);
+        assertMockEndpointsSatisfied();
+
+        Thread.sleep(500);
+
+        assertEquals(0, Mailbox.get("jones2@localhost").size());
+        assertEquals(0, Mailbox.get("jones2@localhost").getNewMessageCount());
+        assertEquals(5, Mailbox.get("moveToFolder-jones2@localhost").getNewMessageCount());
+
+        Assert.assertFalse(Mailbox.get("moveToFolder-jones2@localhost").get(0).getFlags().contains(Flags.Flag.SEEN));
+        Assert.assertFalse(Mailbox.get("moveToFolder-jones2@localhost").get(1).getFlags().contains(Flags.Flag.SEEN));
+        Assert.assertFalse(Mailbox.get("moveToFolder-jones2@localhost").get(2).getFlags().contains(Flags.Flag.SEEN));
+        Assert.assertFalse(Mailbox.get("moveToFolder-jones2@localhost").get(3).getFlags().contains(Flags.Flag.SEEN));
+        Assert.assertFalse(Mailbox.get("moveToFolder-jones2@localhost").get(4).getFlags().contains(Flags.Flag.SEEN));
+    }
+
+    private void prepareMailbox() throws Exception {
+        Mailbox.clearAll();
+        String[] mailUser = new String[] {"jones", "jones2"};
+        for (String username : mailUser) {
+            JavaMailSender sender = new DefaultJavaMailSender();
+            Store store = sender.getSession().getStore("pop3");
+            store.connect("localhost", 25, username, "secret");
+            Folder folder = store.getFolder("INBOX");
+            folder.open(Folder.READ_WRITE);
+            folder.expunge();
+
+            // inserts 5 new messages
+            Message[] messages = new Message[5];
+            for (int i = 0; i < 5; i++) {
+                messages[i] = new MimeMessage(sender.getSession());
+                messages[i].setHeader("Message-ID", "" + i);
+                messages[i].setText("Message " + i);
+            }
+            folder.appendMessages(messages);
+            folder.close(true);
+        }
+    }
+
+    @Override
+    protected RoutesBuilder[] createRouteBuilders() {
+        return new RoutesBuilder[] {new RouteBuilder() {
+            public void configure() throws Exception {
+                from("imap://jones@localhost?password=secret&delete=false&moveTo=moveToFolder&initialDelay=100&delay=100").to("mock:result");
+            }
+        }, new RouteBuilder() {
+            public void configure() throws Exception {
+                from("imap://jones2@localhost?password=secret&delete=true&moveTo=moveToFolder&initialDelay=100&delay=100").to("mock:result2");
+            }
+        } };
+    }
+}