This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push: new bf26c4e561b CAMEL-17586: camel-mail - Add option to either warn or exception on duplicate file attachments. Thanks to Manuel Shenavai for unit test. bf26c4e561b is described below commit bf26c4e561b2be3646821cb0a465dbd0b3944824 Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Mon Sep 5 20:47:23 2022 +0200 CAMEL-17586: camel-mail - Add option to either warn or exception on duplicate file attachments. Thanks to Manuel Shenavai for unit test. --- .../component/mail/MailComponentConfigurer.java | 6 ++ .../component/mail/MailEndpointConfigurer.java | 6 ++ .../component/mail/MailEndpointUriFactory.java | 3 +- .../org/apache/camel/component/mail/imap.json | 2 + .../org/apache/camel/component/mail/imaps.json | 2 + .../org/apache/camel/component/mail/pop3.json | 2 + .../org/apache/camel/component/mail/pop3s.json | 2 + .../org/apache/camel/component/mail/smtp.json | 2 + .../org/apache/camel/component/mail/smtps.json | 2 + .../apache/camel/component/mail/MailBinding.java | 34 +++++++- .../camel/component/mail/MailConfiguration.java | 15 ++++ .../apache/camel/component/mail/MailEndpoint.java | 3 +- ...MailBindingAttachmentDuplicateFileNameTest.java | 98 ++++++++++++++++++++++ 13 files changed, 173 insertions(+), 4 deletions(-) diff --git a/components/camel-mail/src/generated/java/org/apache/camel/component/mail/MailComponentConfigurer.java b/components/camel-mail/src/generated/java/org/apache/camel/component/mail/MailComponentConfigurer.java index fdbef1121b3..9fb5fb10496 100644 --- a/components/camel-mail/src/generated/java/org/apache/camel/component/mail/MailComponentConfigurer.java +++ b/components/camel-mail/src/generated/java/org/apache/camel/component/mail/MailComponentConfigurer.java @@ -58,6 +58,8 @@ public class MailComponentConfigurer extends PropertyConfigurerSupport implement case "decodeFilename": getOrCreateConfiguration(target).setDecodeFilename(property(camelContext, boolean.class, value)); return true; case "delete": getOrCreateConfiguration(target).setDelete(property(camelContext, boolean.class, value)); return true; case "disconnect": getOrCreateConfiguration(target).setDisconnect(property(camelContext, boolean.class, value)); return true; + case "failonduplicatefileattachment": + case "failOnDuplicateFileAttachment": getOrCreateConfiguration(target).setFailOnDuplicateFileAttachment(property(camelContext, boolean.class, value)); return true; case "fetchsize": case "fetchSize": getOrCreateConfiguration(target).setFetchSize(property(camelContext, int.class, value)); return true; case "foldername": @@ -137,6 +139,8 @@ public class MailComponentConfigurer extends PropertyConfigurerSupport implement case "decodeFilename": return boolean.class; case "delete": return boolean.class; case "disconnect": return boolean.class; + case "failonduplicatefileattachment": + case "failOnDuplicateFileAttachment": return boolean.class; case "fetchsize": case "fetchSize": return int.class; case "foldername": @@ -217,6 +221,8 @@ public class MailComponentConfigurer extends PropertyConfigurerSupport implement case "decodeFilename": return getOrCreateConfiguration(target).isDecodeFilename(); case "delete": return getOrCreateConfiguration(target).isDelete(); case "disconnect": return getOrCreateConfiguration(target).isDisconnect(); + case "failonduplicatefileattachment": + case "failOnDuplicateFileAttachment": return getOrCreateConfiguration(target).isFailOnDuplicateFileAttachment(); case "fetchsize": case "fetchSize": return getOrCreateConfiguration(target).getFetchSize(); case "foldername": diff --git a/components/camel-mail/src/generated/java/org/apache/camel/component/mail/MailEndpointConfigurer.java b/components/camel-mail/src/generated/java/org/apache/camel/component/mail/MailEndpointConfigurer.java index b47422ecc24..eece4ac83c6 100644 --- a/components/camel-mail/src/generated/java/org/apache/camel/component/mail/MailEndpointConfigurer.java +++ b/components/camel-mail/src/generated/java/org/apache/camel/component/mail/MailEndpointConfigurer.java @@ -60,6 +60,8 @@ public class MailEndpointConfigurer extends PropertyConfigurerSupport implements case "exceptionHandler": target.setExceptionHandler(property(camelContext, org.apache.camel.spi.ExceptionHandler.class, value)); return true; case "exchangepattern": case "exchangePattern": target.setExchangePattern(property(camelContext, org.apache.camel.ExchangePattern.class, value)); return true; + case "failonduplicatefileattachment": + case "failOnDuplicateFileAttachment": target.getConfiguration().setFailOnDuplicateFileAttachment(property(camelContext, boolean.class, value)); return true; case "fetchsize": case "fetchSize": target.getConfiguration().setFetchSize(property(camelContext, int.class, value)); return true; case "foldername": @@ -182,6 +184,8 @@ public class MailEndpointConfigurer extends PropertyConfigurerSupport implements case "exceptionHandler": return org.apache.camel.spi.ExceptionHandler.class; case "exchangepattern": case "exchangePattern": return org.apache.camel.ExchangePattern.class; + case "failonduplicatefileattachment": + case "failOnDuplicateFileAttachment": return boolean.class; case "fetchsize": case "fetchSize": return int.class; case "foldername": @@ -305,6 +309,8 @@ public class MailEndpointConfigurer extends PropertyConfigurerSupport implements case "exceptionHandler": return target.getExceptionHandler(); case "exchangepattern": case "exchangePattern": return target.getExchangePattern(); + case "failonduplicatefileattachment": + case "failOnDuplicateFileAttachment": return target.getConfiguration().isFailOnDuplicateFileAttachment(); case "fetchsize": case "fetchSize": return target.getConfiguration().getFetchSize(); case "foldername": diff --git a/components/camel-mail/src/generated/java/org/apache/camel/component/mail/MailEndpointUriFactory.java b/components/camel-mail/src/generated/java/org/apache/camel/component/mail/MailEndpointUriFactory.java index 290084a9809..a19f3fa6010 100644 --- a/components/camel-mail/src/generated/java/org/apache/camel/component/mail/MailEndpointUriFactory.java +++ b/components/camel-mail/src/generated/java/org/apache/camel/component/mail/MailEndpointUriFactory.java @@ -22,7 +22,7 @@ public class MailEndpointUriFactory extends org.apache.camel.support.component.E private static final Set<String> SECRET_PROPERTY_NAMES; private static final Set<String> MULTI_VALUE_PREFIXES; static { - Set<String> props = new HashSet<>(68); + Set<String> props = new HashSet<>(69); props.add("additionalJavaMailProperties"); props.add("alternativeBodyHeader"); props.add("attachmentsContentTransferEncodingResolver"); @@ -46,6 +46,7 @@ public class MailEndpointUriFactory extends org.apache.camel.support.component.E props.add("disconnect"); props.add("exceptionHandler"); props.add("exchangePattern"); + props.add("failOnDuplicateFileAttachment"); props.add("fetchSize"); props.add("folderName"); props.add("from"); diff --git a/components/camel-mail/src/generated/resources/org/apache/camel/component/mail/imap.json b/components/camel-mail/src/generated/resources/org/apache/camel/component/mail/imap.json index 51acff65522..b81465232b8 100644 --- a/components/camel-mail/src/generated/resources/org/apache/camel/component/mail/imap.json +++ b/components/camel-mail/src/generated/resources/org/apache/camel/component/mail/imap.json @@ -36,6 +36,7 @@ "peek": { "kind": "property", "displayName": "Peek", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Will mark the javax.mail.Message as peeked before processing the mail message. This applies to IMAP [...] "skipFailedMessage": { "kind": "property", "displayName": "Skip Failed Message", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "If the mail consumer cannot retrieve a given mail message, then this o [...] "unseen": { "kind": "property", "displayName": "Unseen", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Whether to limit by unseen mails only." }, + "failOnDuplicateFileAttachment": { "kind": "property", "displayName": "Fail On Duplicate File Attachment", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Whether to fail processing the mail if the mail [...] "fetchSize": { "kind": "property", "displayName": "Fetch Size", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": -1, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Sets the maximum number of messages to consume during a poll. This can be [...] "folderName": { "kind": "property", "displayName": "Folder Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "INBOX", "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The folder to poll." }, "mapMailMessage": { "kind": "property", "displayName": "Map Mail Message", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Specifies whether Camel should map the received mail message to Camel body\/head [...] @@ -100,6 +101,7 @@ "bridgeErrorHandler": { "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "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 [...] "exceptionHandler": { "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the con [...] "exchangePattern": { "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut", "InOptionalOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." }, + "failOnDuplicateFileAttachment": { "kind": "parameter", "displayName": "Fail On Duplicate File Attachment", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Whether to fail processing the mail if the mai [...] "fetchSize": { "kind": "parameter", "displayName": "Fetch Size", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": -1, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Sets the maximum number of messages to consume during a poll. This can be [...] "folderName": { "kind": "parameter", "displayName": "Folder Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "INBOX", "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The folder to poll." }, "mailUidGenerator": { "kind": "parameter", "displayName": "Mail Uid Generator", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.mail.MailUidGenerator", "deprecated": false, "autowired": false, "secret": false, "description": "A pluggable MailUidGenerator that allows to use custom logic to generate UUID of the mail message." }, diff --git a/components/camel-mail/src/generated/resources/org/apache/camel/component/mail/imaps.json b/components/camel-mail/src/generated/resources/org/apache/camel/component/mail/imaps.json index cd871152d17..25c4119fc4b 100644 --- a/components/camel-mail/src/generated/resources/org/apache/camel/component/mail/imaps.json +++ b/components/camel-mail/src/generated/resources/org/apache/camel/component/mail/imaps.json @@ -36,6 +36,7 @@ "peek": { "kind": "property", "displayName": "Peek", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Will mark the javax.mail.Message as peeked before processing the mail message. This applies to IMAP [...] "skipFailedMessage": { "kind": "property", "displayName": "Skip Failed Message", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "If the mail consumer cannot retrieve a given mail message, then this o [...] "unseen": { "kind": "property", "displayName": "Unseen", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Whether to limit by unseen mails only." }, + "failOnDuplicateFileAttachment": { "kind": "property", "displayName": "Fail On Duplicate File Attachment", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Whether to fail processing the mail if the mail [...] "fetchSize": { "kind": "property", "displayName": "Fetch Size", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": -1, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Sets the maximum number of messages to consume during a poll. This can be [...] "folderName": { "kind": "property", "displayName": "Folder Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "INBOX", "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The folder to poll." }, "mapMailMessage": { "kind": "property", "displayName": "Map Mail Message", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Specifies whether Camel should map the received mail message to Camel body\/head [...] @@ -100,6 +101,7 @@ "bridgeErrorHandler": { "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "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 [...] "exceptionHandler": { "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the con [...] "exchangePattern": { "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut", "InOptionalOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." }, + "failOnDuplicateFileAttachment": { "kind": "parameter", "displayName": "Fail On Duplicate File Attachment", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Whether to fail processing the mail if the mai [...] "fetchSize": { "kind": "parameter", "displayName": "Fetch Size", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": -1, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Sets the maximum number of messages to consume during a poll. This can be [...] "folderName": { "kind": "parameter", "displayName": "Folder Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "INBOX", "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The folder to poll." }, "mailUidGenerator": { "kind": "parameter", "displayName": "Mail Uid Generator", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.mail.MailUidGenerator", "deprecated": false, "autowired": false, "secret": false, "description": "A pluggable MailUidGenerator that allows to use custom logic to generate UUID of the mail message." }, diff --git a/components/camel-mail/src/generated/resources/org/apache/camel/component/mail/pop3.json b/components/camel-mail/src/generated/resources/org/apache/camel/component/mail/pop3.json index b89e9bb3d9e..4713c9095ab 100644 --- a/components/camel-mail/src/generated/resources/org/apache/camel/component/mail/pop3.json +++ b/components/camel-mail/src/generated/resources/org/apache/camel/component/mail/pop3.json @@ -36,6 +36,7 @@ "peek": { "kind": "property", "displayName": "Peek", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Will mark the javax.mail.Message as peeked before processing the mail message. This applies to IMAP [...] "skipFailedMessage": { "kind": "property", "displayName": "Skip Failed Message", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "If the mail consumer cannot retrieve a given mail message, then this o [...] "unseen": { "kind": "property", "displayName": "Unseen", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Whether to limit by unseen mails only." }, + "failOnDuplicateFileAttachment": { "kind": "property", "displayName": "Fail On Duplicate File Attachment", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Whether to fail processing the mail if the mail [...] "fetchSize": { "kind": "property", "displayName": "Fetch Size", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": -1, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Sets the maximum number of messages to consume during a poll. This can be [...] "folderName": { "kind": "property", "displayName": "Folder Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "INBOX", "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The folder to poll." }, "mapMailMessage": { "kind": "property", "displayName": "Map Mail Message", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Specifies whether Camel should map the received mail message to Camel body\/head [...] @@ -100,6 +101,7 @@ "bridgeErrorHandler": { "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "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 [...] "exceptionHandler": { "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the con [...] "exchangePattern": { "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut", "InOptionalOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." }, + "failOnDuplicateFileAttachment": { "kind": "parameter", "displayName": "Fail On Duplicate File Attachment", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Whether to fail processing the mail if the mai [...] "fetchSize": { "kind": "parameter", "displayName": "Fetch Size", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": -1, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Sets the maximum number of messages to consume during a poll. This can be [...] "folderName": { "kind": "parameter", "displayName": "Folder Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "INBOX", "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The folder to poll." }, "mailUidGenerator": { "kind": "parameter", "displayName": "Mail Uid Generator", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.mail.MailUidGenerator", "deprecated": false, "autowired": false, "secret": false, "description": "A pluggable MailUidGenerator that allows to use custom logic to generate UUID of the mail message." }, diff --git a/components/camel-mail/src/generated/resources/org/apache/camel/component/mail/pop3s.json b/components/camel-mail/src/generated/resources/org/apache/camel/component/mail/pop3s.json index b6cdb0f759c..94b90a645b4 100644 --- a/components/camel-mail/src/generated/resources/org/apache/camel/component/mail/pop3s.json +++ b/components/camel-mail/src/generated/resources/org/apache/camel/component/mail/pop3s.json @@ -36,6 +36,7 @@ "peek": { "kind": "property", "displayName": "Peek", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Will mark the javax.mail.Message as peeked before processing the mail message. This applies to IMAP [...] "skipFailedMessage": { "kind": "property", "displayName": "Skip Failed Message", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "If the mail consumer cannot retrieve a given mail message, then this o [...] "unseen": { "kind": "property", "displayName": "Unseen", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Whether to limit by unseen mails only." }, + "failOnDuplicateFileAttachment": { "kind": "property", "displayName": "Fail On Duplicate File Attachment", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Whether to fail processing the mail if the mail [...] "fetchSize": { "kind": "property", "displayName": "Fetch Size", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": -1, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Sets the maximum number of messages to consume during a poll. This can be [...] "folderName": { "kind": "property", "displayName": "Folder Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "INBOX", "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The folder to poll." }, "mapMailMessage": { "kind": "property", "displayName": "Map Mail Message", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Specifies whether Camel should map the received mail message to Camel body\/head [...] @@ -100,6 +101,7 @@ "bridgeErrorHandler": { "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "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 [...] "exceptionHandler": { "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the con [...] "exchangePattern": { "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut", "InOptionalOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." }, + "failOnDuplicateFileAttachment": { "kind": "parameter", "displayName": "Fail On Duplicate File Attachment", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Whether to fail processing the mail if the mai [...] "fetchSize": { "kind": "parameter", "displayName": "Fetch Size", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": -1, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Sets the maximum number of messages to consume during a poll. This can be [...] "folderName": { "kind": "parameter", "displayName": "Folder Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "INBOX", "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The folder to poll." }, "mailUidGenerator": { "kind": "parameter", "displayName": "Mail Uid Generator", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.mail.MailUidGenerator", "deprecated": false, "autowired": false, "secret": false, "description": "A pluggable MailUidGenerator that allows to use custom logic to generate UUID of the mail message." }, diff --git a/components/camel-mail/src/generated/resources/org/apache/camel/component/mail/smtp.json b/components/camel-mail/src/generated/resources/org/apache/camel/component/mail/smtp.json index 28b5e913297..8463308c410 100644 --- a/components/camel-mail/src/generated/resources/org/apache/camel/component/mail/smtp.json +++ b/components/camel-mail/src/generated/resources/org/apache/camel/component/mail/smtp.json @@ -36,6 +36,7 @@ "peek": { "kind": "property", "displayName": "Peek", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Will mark the javax.mail.Message as peeked before processing the mail message. This applies to IMAP [...] "skipFailedMessage": { "kind": "property", "displayName": "Skip Failed Message", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "If the mail consumer cannot retrieve a given mail message, then this o [...] "unseen": { "kind": "property", "displayName": "Unseen", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Whether to limit by unseen mails only." }, + "failOnDuplicateFileAttachment": { "kind": "property", "displayName": "Fail On Duplicate File Attachment", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Whether to fail processing the mail if the mail [...] "fetchSize": { "kind": "property", "displayName": "Fetch Size", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": -1, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Sets the maximum number of messages to consume during a poll. This can be [...] "folderName": { "kind": "property", "displayName": "Folder Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "INBOX", "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The folder to poll." }, "mapMailMessage": { "kind": "property", "displayName": "Map Mail Message", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Specifies whether Camel should map the received mail message to Camel body\/head [...] @@ -100,6 +101,7 @@ "bridgeErrorHandler": { "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "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 [...] "exceptionHandler": { "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the con [...] "exchangePattern": { "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut", "InOptionalOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." }, + "failOnDuplicateFileAttachment": { "kind": "parameter", "displayName": "Fail On Duplicate File Attachment", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Whether to fail processing the mail if the mai [...] "fetchSize": { "kind": "parameter", "displayName": "Fetch Size", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": -1, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Sets the maximum number of messages to consume during a poll. This can be [...] "folderName": { "kind": "parameter", "displayName": "Folder Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "INBOX", "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The folder to poll." }, "mailUidGenerator": { "kind": "parameter", "displayName": "Mail Uid Generator", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.mail.MailUidGenerator", "deprecated": false, "autowired": false, "secret": false, "description": "A pluggable MailUidGenerator that allows to use custom logic to generate UUID of the mail message." }, diff --git a/components/camel-mail/src/generated/resources/org/apache/camel/component/mail/smtps.json b/components/camel-mail/src/generated/resources/org/apache/camel/component/mail/smtps.json index d0a5fe7818f..a52cc773d9b 100644 --- a/components/camel-mail/src/generated/resources/org/apache/camel/component/mail/smtps.json +++ b/components/camel-mail/src/generated/resources/org/apache/camel/component/mail/smtps.json @@ -36,6 +36,7 @@ "peek": { "kind": "property", "displayName": "Peek", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Will mark the javax.mail.Message as peeked before processing the mail message. This applies to IMAP [...] "skipFailedMessage": { "kind": "property", "displayName": "Skip Failed Message", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "If the mail consumer cannot retrieve a given mail message, then this o [...] "unseen": { "kind": "property", "displayName": "Unseen", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Whether to limit by unseen mails only." }, + "failOnDuplicateFileAttachment": { "kind": "property", "displayName": "Fail On Duplicate File Attachment", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Whether to fail processing the mail if the mail [...] "fetchSize": { "kind": "property", "displayName": "Fetch Size", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": -1, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Sets the maximum number of messages to consume during a poll. This can be [...] "folderName": { "kind": "property", "displayName": "Folder Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "INBOX", "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The folder to poll." }, "mapMailMessage": { "kind": "property", "displayName": "Map Mail Message", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Specifies whether Camel should map the received mail message to Camel body\/head [...] @@ -100,6 +101,7 @@ "bridgeErrorHandler": { "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "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 [...] "exceptionHandler": { "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the con [...] "exchangePattern": { "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut", "InOptionalOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." }, + "failOnDuplicateFileAttachment": { "kind": "parameter", "displayName": "Fail On Duplicate File Attachment", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Whether to fail processing the mail if the mai [...] "fetchSize": { "kind": "parameter", "displayName": "Fetch Size", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "defaultValue": -1, "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "Sets the maximum number of messages to consume during a poll. This can be [...] "folderName": { "kind": "parameter", "displayName": "Folder Name", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "INBOX", "configurationClass": "org.apache.camel.component.mail.MailConfiguration", "configurationField": "configuration", "description": "The folder to poll." }, "mailUidGenerator": { "kind": "parameter", "displayName": "Mail Uid Generator", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.mail.MailUidGenerator", "deprecated": false, "autowired": false, "secret": false, "description": "A pluggable MailUidGenerator that allows to use custom logic to generate UUID of the mail message." }, diff --git a/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailBinding.java b/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailBinding.java index becccec0985..5d26399ec35 100644 --- a/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailBinding.java +++ b/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailBinding.java @@ -72,6 +72,7 @@ public class MailBinding { private ContentTypeResolver contentTypeResolver; private boolean decodeFilename; private boolean mapMailMessage = true; + private boolean failOnDuplicateAttachment; public MailBinding() { headerFilterStrategy = new DefaultHeaderFilterStrategy(); @@ -80,15 +81,29 @@ public class MailBinding { @Deprecated public MailBinding(HeaderFilterStrategy headerFilterStrategy, ContentTypeResolver contentTypeResolver, boolean decodeFilename) { - this(headerFilterStrategy, contentTypeResolver, decodeFilename, true); + this(headerFilterStrategy, contentTypeResolver, decodeFilename, true, false); } public MailBinding(HeaderFilterStrategy headerFilterStrategy, ContentTypeResolver contentTypeResolver, boolean decodeFilename, boolean mapMailMessage) { + this(headerFilterStrategy, contentTypeResolver, decodeFilename, mapMailMessage, false); + } + + public MailBinding(HeaderFilterStrategy headerFilterStrategy, ContentTypeResolver contentTypeResolver, + boolean decodeFilename, boolean mapMailMessage, boolean failOnDuplicateAttachment) { this.headerFilterStrategy = headerFilterStrategy; this.contentTypeResolver = contentTypeResolver; this.decodeFilename = decodeFilename; this.mapMailMessage = mapMailMessage; + this.failOnDuplicateAttachment = failOnDuplicateAttachment; + } + + public boolean isFailOnDuplicateAttachment() { + return failOnDuplicateAttachment; + } + + public void setFailOnDuplicateAttachment(boolean failOnDuplicateAttachment) { + this.failOnDuplicateAttachment = failOnDuplicateAttachment; } public void populateMailMessage(MailEndpoint endpoint, MimeMessage mimeMessage, Exchange exchange) @@ -370,13 +385,28 @@ public class MailBinding { } map.put(fileName, camelAttachment); } else { - LOG.warn("Cannot extract duplicate file attachment: {}.", fileName); + handleDuplicateFileAttachment(mp, fileName); } } } } } + /** + * Strategy for handling extracting mail message that has duplicate file attachments + * + * @param mp the multipart entity + * @param duplicateFileName the duplicated file name + * @throws MessagingException is thrown, failing with an error + */ + protected void handleDuplicateFileAttachment(Multipart mp, String duplicateFileName) throws MessagingException { + if (failOnDuplicateAttachment) { + throw new MessagingException("Duplicate file attachment: " + duplicateFileName); + } else { + LOG.warn("Cannot extract duplicate file attachment: {}.", duplicateFileName); + } + } + private boolean validDisposition(String disposition, String fileName) { if (fileName == null || fileName.isEmpty()) { return false; 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 0ed8de6a505..328603d9297 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 @@ -138,6 +138,8 @@ public class MailConfiguration implements Cloneable { private Properties javaMailProperties; @UriParam(label = "advanced") private MailAuthenticator authenticator; + @UriParam(label = "consumer,advanced") + private boolean failOnDuplicateFileAttachment; public MailConfiguration() { } @@ -828,4 +830,17 @@ public class MailConfiguration implements Cloneable { public void setDecodeFilename(boolean decodeFilename) { this.decodeFilename = decodeFilename; } + + public boolean isFailOnDuplicateFileAttachment() { + return failOnDuplicateFileAttachment; + } + + /** + * Whether to fail processing the mail if the mail message contains attachments with duplicate file names. If set to + * false, then the duplicate attachment is skipped and a WARN is logged. If set to true then an exception is thrown + * failing to process the mail message. + */ + public void setFailOnDuplicateFileAttachment(boolean failOnDuplicateFileAttachment) { + this.failOnDuplicateFileAttachment = failOnDuplicateFileAttachment; + } } diff --git a/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailEndpoint.java b/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailEndpoint.java index 2396fc68212..4c8a186365b 100644 --- a/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailEndpoint.java +++ b/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailEndpoint.java @@ -140,7 +140,8 @@ public class MailEndpoint extends ScheduledPollEndpoint implements HeaderFilterS if (binding == null) { boolean decode = getConfiguration() != null && getConfiguration().isDecodeFilename(); boolean mapMailMessage = getConfiguration() != null && getConfiguration().isMapMailMessage(); - binding = new MailBinding(headerFilterStrategy, contentTypeResolver, decode, mapMailMessage); + boolean failDuplicate = getConfiguration() != null && getConfiguration().isFailOnDuplicateFileAttachment(); + binding = new MailBinding(headerFilterStrategy, contentTypeResolver, decode, mapMailMessage, failDuplicate); } return binding; } diff --git a/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailBindingAttachmentDuplicateFileNameTest.java b/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailBindingAttachmentDuplicateFileNameTest.java new file mode 100644 index 00000000000..0db6b55d98b --- /dev/null +++ b/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailBindingAttachmentDuplicateFileNameTest.java @@ -0,0 +1,98 @@ +/* + * 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 java.util.HashMap; +import java.util.Properties; + +import javax.mail.Message; +import javax.mail.MessagingException; +import javax.mail.Multipart; +import javax.mail.Session; +import javax.mail.internet.MimeBodyPart; +import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimeMultipart; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class MailBindingAttachmentDuplicateFileNameTest { + + private final MailBinding binding = new MailBinding(); + + @Test + public void shouldFailOnDuplicateFilenames() throws Exception { + binding.setFailOnDuplicateAttachment(true); + + final Session session = Session.getInstance(new Properties()); + final Message message = new MimeMessage(session); + + String filename = "file.txt"; + String filename2 = "file.txt"; + setAttachments(message, filename, filename2); + extractAttachmentsAndValidate(message, filename, filename2); + + filename = "file.txt"; + filename2 = "../file.txt"; + setAttachments(message, filename, filename2); + extractAttachmentsAndValidate(message, filename, filename2); + + filename = "file.txt"; + filename2 = "..\\file.txt"; + setAttachments(message, filename, filename2); + extractAttachmentsAndValidate(message, filename, filename2); + + filename = "file.txt"; + filename2 = "/absolute/file.txt"; + setAttachments(message, filename, filename2); + extractAttachmentsAndValidate(message, filename, filename2); + + filename = "file.txt"; + filename2 = "c:\\absolute\\file.txt"; + setAttachments(message, filename, filename2); + extractAttachmentsAndValidate(message, filename, filename2); + + filename = "..\\file.txt"; + filename2 = "c:\\absolute\\file.txt"; + setAttachments(message, filename, filename2); + extractAttachmentsAndValidate(message, filename, filename2); + } + + private void extractAttachmentsAndValidate(Message message, String filename, String filename2) throws Exception { + MessagingException thrown; + setAttachments(message, filename, filename2); + thrown = assertThrows(MessagingException.class, () -> binding.extractAttachmentsFromMail(message, new HashMap<>()), + "Duplicate attachment names should cause an exception"); + assertTrue(thrown.getMessage().contains("Duplicate file attachment")); + } + + private void setAttachments(Message message, String name1, String name2) throws Exception { + Multipart multipart = new MimeMultipart(); + MimeBodyPart part = new MimeBodyPart(); + part.attachFile(name1); + multipart.addBodyPart(part); + + part = new MimeBodyPart(); + part.attachFile(name2); + multipart.addBodyPart(part); + + message.setContent(multipart); + } + +}