From 9366d2cf5558723f694128d541729a38d884072f Mon Sep 17 00:00:00 2001 From: Dylan Piergies Date: Fri, 10 Jan 2025 15:44:32 +0000 Subject: [PATCH] CAMEL-21608: (aws2-ses) Support message tags Enhance to add support for message tags to the aws2-ses component. Tags are useful for providing user-defined metadata that will appear in email tracking events related to the sent email. --- .../camel/catalog/components/aws2-ses.json | 5 ++-- .../camel/component/aws2/ses/aws2-ses.json | 5 ++-- .../component/aws2/ses/Ses2Constants.java | 3 +++ .../component/aws2/ses/Ses2Producer.java | 19 ++++++++++++- .../component/aws2/ses/SesComponentTest.java | 27 +++++++++++++++++-- .../dsl/Ses2EndpointBuilderFactory.java | 14 ++++++++++ 6 files changed, 66 insertions(+), 7 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-ses.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-ses.json index dc369519d59e6..9777b29a8bc99 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-ses.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-ses.json @@ -60,8 +60,9 @@ "CamelAwsSesTo": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "List of comma separated destination email address.", "constantName": "org.apache.camel.component.aws2.ses.Ses2Constants#TO" }, "CamelAwsSesCc": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "List of comma separated destination carbon copy (cc) email address.", "constantName": "org.apache.camel.component.aws2.ses.Ses2Constants#CC" }, "CamelAwsSesBcc": { "index": 7, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "List of comma separated destination blind carbon copy (bcc) email address.", "constantName": "org.apache.camel.component.aws2.ses.Ses2Constants#BCC" }, - "CamelAwsSesHtmlEmail": { "index": 8, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The flag to show if email content is HTML.", "constantName": "org.apache.camel.component.aws2.ses.Ses2Constants#HTML_EMAIL" }, - "CamelAwsSesConfigurationSet": { "index": 9, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "TThe configuration set to send.", "constantName": "org.apache.camel.component.aws2.ses.Ses2Constants#CONFIGURATION_SET" } + "CamelAwsSesTags": { "index": 8, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Map", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "A collection of name\/value pairs to apply when sending the email. Tags are user-defined properties that are included in published email sending events.", "constantName": "org.apache.camel.component.aws2.ses.Ses2Constants#TAGS" }, + "CamelAwsSesHtmlEmail": { "index": 9, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The flag to show if email content is HTML.", "constantName": "org.apache.camel.component.aws2.ses.Ses2Constants#HTML_EMAIL" }, + "CamelAwsSesConfigurationSet": { "index": 10, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "TThe configuration set to send.", "constantName": "org.apache.camel.component.aws2.ses.Ses2Constants#CONFIGURATION_SET" } }, "properties": { "from": { "index": 0, "kind": "path", "displayName": "From", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.ses.Ses2Configuration", "configurationField": "configuration", "description": "The sender's email address." }, diff --git a/components/camel-aws/camel-aws2-ses/src/generated/resources/META-INF/org/apache/camel/component/aws2/ses/aws2-ses.json b/components/camel-aws/camel-aws2-ses/src/generated/resources/META-INF/org/apache/camel/component/aws2/ses/aws2-ses.json index dc369519d59e6..9777b29a8bc99 100644 --- a/components/camel-aws/camel-aws2-ses/src/generated/resources/META-INF/org/apache/camel/component/aws2/ses/aws2-ses.json +++ b/components/camel-aws/camel-aws2-ses/src/generated/resources/META-INF/org/apache/camel/component/aws2/ses/aws2-ses.json @@ -60,8 +60,9 @@ "CamelAwsSesTo": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "List of comma separated destination email address.", "constantName": "org.apache.camel.component.aws2.ses.Ses2Constants#TO" }, "CamelAwsSesCc": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "List of comma separated destination carbon copy (cc) email address.", "constantName": "org.apache.camel.component.aws2.ses.Ses2Constants#CC" }, "CamelAwsSesBcc": { "index": 7, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "List of comma separated destination blind carbon copy (bcc) email address.", "constantName": "org.apache.camel.component.aws2.ses.Ses2Constants#BCC" }, - "CamelAwsSesHtmlEmail": { "index": 8, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The flag to show if email content is HTML.", "constantName": "org.apache.camel.component.aws2.ses.Ses2Constants#HTML_EMAIL" }, - "CamelAwsSesConfigurationSet": { "index": 9, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "TThe configuration set to send.", "constantName": "org.apache.camel.component.aws2.ses.Ses2Constants#CONFIGURATION_SET" } + "CamelAwsSesTags": { "index": 8, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Map", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "A collection of name\/value pairs to apply when sending the email. Tags are user-defined properties that are included in published email sending events.", "constantName": "org.apache.camel.component.aws2.ses.Ses2Constants#TAGS" }, + "CamelAwsSesHtmlEmail": { "index": 9, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The flag to show if email content is HTML.", "constantName": "org.apache.camel.component.aws2.ses.Ses2Constants#HTML_EMAIL" }, + "CamelAwsSesConfigurationSet": { "index": 10, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "TThe configuration set to send.", "constantName": "org.apache.camel.component.aws2.ses.Ses2Constants#CONFIGURATION_SET" } }, "properties": { "from": { "index": 0, "kind": "path", "displayName": "From", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.ses.Ses2Configuration", "configurationField": "configuration", "description": "The sender's email address." }, diff --git a/components/camel-aws/camel-aws2-ses/src/main/java/org/apache/camel/component/aws2/ses/Ses2Constants.java b/components/camel-aws/camel-aws2-ses/src/main/java/org/apache/camel/component/aws2/ses/Ses2Constants.java index 43b333cc88f87..5709e358539b1 100644 --- a/components/camel-aws/camel-aws2-ses/src/main/java/org/apache/camel/component/aws2/ses/Ses2Constants.java +++ b/components/camel-aws/camel-aws2-ses/src/main/java/org/apache/camel/component/aws2/ses/Ses2Constants.java @@ -40,6 +40,9 @@ public interface Ses2Constants { String CC = "CamelAwsSesCc"; @Metadata(description = "List of comma separated destination blind carbon copy (bcc) email address.", javaType = "String") String BCC = "CamelAwsSesBcc"; + @Metadata(description = "A collection of name/value pairs to apply when sending the email. Tags are user-defined properties that are included in published email sending events.", + javaType = "Map") + String TAGS = "CamelAwsSesTags"; @Metadata(description = "The flag to show if email content is HTML.", javaType = "Boolean") String HTML_EMAIL = "CamelAwsSesHtmlEmail"; @Metadata(description = "TThe configuration set to send.", javaType = "String") diff --git a/components/camel-aws/camel-aws2-ses/src/main/java/org/apache/camel/component/aws2/ses/Ses2Producer.java b/components/camel-aws/camel-aws2-ses/src/main/java/org/apache/camel/component/aws2/ses/Ses2Producer.java index 0fb3aa0119661..e43d0e3430d40 100644 --- a/components/camel-aws/camel-aws2-ses/src/main/java/org/apache/camel/component/aws2/ses/Ses2Producer.java +++ b/components/camel-aws/camel-aws2-ses/src/main/java/org/apache/camel/component/aws2/ses/Ses2Producer.java @@ -22,6 +22,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.stream.Stream; import org.apache.camel.Endpoint; @@ -39,6 +40,7 @@ import software.amazon.awssdk.services.ses.model.Body; import software.amazon.awssdk.services.ses.model.Content; import software.amazon.awssdk.services.ses.model.Destination; +import software.amazon.awssdk.services.ses.model.MessageTag; import software.amazon.awssdk.services.ses.model.SendEmailRequest; import software.amazon.awssdk.services.ses.model.SendEmailResponse; import software.amazon.awssdk.services.ses.model.SendRawEmailRequest; @@ -86,6 +88,7 @@ private SendEmailRequest createMailRequest(Exchange exchange) { request.returnPath(determineReturnPath(exchange)); request.replyToAddresses(determineReplyToAddresses(exchange)); request.message(createMessage(exchange)); + request.tags(determineTags(exchange)); request.configurationSetName(determineConfigurationSet(exchange)); return request.build(); } @@ -95,6 +98,7 @@ private SendRawEmailRequest createRawMailRequest(Exchange exchange) throws Excep request.source(determineFrom(exchange)); request.destinations(determineRawTo(exchange)); request.rawMessage(createRawMessage(exchange)); + request.tags(determineTags(exchange)); request.configurationSetName(determineConfigurationSet(exchange)); return request.build(); } @@ -129,7 +133,6 @@ private software.amazon.awssdk.services.ses.model.RawMessage createRawMessage(Ex return message.build(); } - @SuppressWarnings("unchecked") private Collection determineReplyToAddresses(Exchange exchange) { String replyToAddresses = exchange.getIn().getHeader(Ses2Constants.REPLY_TO_ADDRESSES, String.class); if (replyToAddresses == null) { @@ -217,6 +220,20 @@ private String determineSubject(Exchange exchange) { return subject; } + @SuppressWarnings("unchecked") + private List determineTags(Exchange exchange) { + Map tagMap = exchange.getIn().getHeader(Ses2Constants.TAGS, Map.class); + if (tagMap == null || tagMap.isEmpty()) { + return null; + } + return tagMap.entrySet().stream() + .map(entry -> MessageTag.builder() + .name(entry.getKey()) + .value(entry.getValue()) + .build()) + .toList(); + } + private String determineConfigurationSet(Exchange exchange) { String configuration = exchange.getIn().getHeader(Ses2Constants.CONFIGURATION_SET, String.class); if (configuration == null) { diff --git a/components/camel-aws/camel-aws2-ses/src/test/java/org/apache/camel/component/aws2/ses/SesComponentTest.java b/components/camel-aws/camel-aws2-ses/src/test/java/org/apache/camel/component/aws2/ses/SesComponentTest.java index edb1515d93e82..936963872e9f5 100644 --- a/components/camel-aws/camel-aws2-ses/src/test/java/org/apache/camel/component/aws2/ses/SesComponentTest.java +++ b/components/camel-aws/camel-aws2-ses/src/test/java/org/apache/camel/component/aws2/ses/SesComponentTest.java @@ -16,7 +16,9 @@ */ package org.apache.camel.component.aws2.ses; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.apache.camel.BindToRegistry; import org.apache.camel.Exchange; @@ -24,10 +26,10 @@ import org.apache.camel.builder.RouteBuilder; import org.apache.camel.test.junit5.CamelTestSupport; import org.junit.jupiter.api.Test; +import software.amazon.awssdk.services.ses.model.MessageTag; import software.amazon.awssdk.services.ses.model.SendEmailRequest; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.*; public class SesComponentTest extends CamelTestSupport { @@ -55,6 +57,8 @@ public void process(Exchange exchange) { assertTrue(sendEmailRequest.replyToAddresses().contains("replyTo1@example.com")); assertTrue(sendEmailRequest.replyToAddresses().contains("replyTo2@example.com")); assertEquals("Subject", getSubject(sendEmailRequest)); + assertFalse(sendEmailRequest.hasTags()); + assertEquals(0, sendEmailRequest.tags().size()); assertEquals("This is my message text.", getBody(sendEmailRequest)); } @@ -81,6 +85,7 @@ public void process(Exchange exchange) { exchange.getIn().setHeader(Ses2Constants.REPLY_TO_ADDRESSES, "anotherReplyTo1@example.com, anotherReplyTo2@example.com"); exchange.getIn().setHeader(Ses2Constants.SUBJECT, "anotherSubject"); + exchange.getIn().setHeader(Ses2Constants.TAGS, Map.of("tagName", "tagValue")); } }); @@ -97,6 +102,24 @@ public void process(Exchange exchange) { assertTrue(sendEmailRequest.replyToAddresses().contains("anotherReplyTo2@example.com")); assertEquals("anotherSubject", getSubject(sendEmailRequest)); assertEquals("This is my message text.", getBody(sendEmailRequest)); + assertTrue(sendEmailRequest.hasTags()); + assertEquals(List.of(MessageTag.builder().name("tagName").value("tagValue").build()), sendEmailRequest.tags()); + } + + @Test + public void sendMessageWithEmptyMessageTagsHeader() { + Exchange exchange = template.send("direct:start", new Processor() { + public void process(Exchange exchange) { + exchange.getIn().setBody("This is my message text."); + exchange.getIn().setHeader(Ses2Constants.TAGS, new HashMap()); + } + }); + + assertEquals("1", exchange.getIn().getHeader(Ses2Constants.MESSAGE_ID)); + + SendEmailRequest sendEmailRequest = sesClient.getSendEmailRequest(); + assertFalse(sendEmailRequest.hasTags()); + assertEquals(0, sendEmailRequest.tags().size()); } @Override diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/Ses2EndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/Ses2EndpointBuilderFactory.java index 0d57740c129ec..1f6433d73f78e 100644 --- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/Ses2EndpointBuilderFactory.java +++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/Ses2EndpointBuilderFactory.java @@ -732,6 +732,20 @@ public String awsSesCc() { public String awsSesBcc() { return "CamelAwsSesBcc"; } + /** + * A collection of name/value pairs to apply when sending the email. + * Tags are user-defined properties that are included in published email + * sending events. + * + * The option is a: {@code Map} type. + * + * Group: producer + * + * @return the name of the header {@code AwsSesTags}. + */ + public String awsSesTags() { + return "CamelAwsSesTags"; + } /** * The flag to show if email content is HTML. *