From 765bb2f09e20fb7b9e500618a57bdf87cad5da86 Mon Sep 17 00:00:00 2001 From: Christoph Deppisch Date: Mon, 6 Dec 2021 16:47:56 +0100 Subject: [PATCH] Add mail sink Kamelet --- .github/workflows/test.yaml | 9 +- .gitignore | 2 + .../ROOT/assets/images/kamelets/mail-sink.svg | 68 ++++++++ docs/modules/ROOT/nav.adoc | 1 + docs/modules/ROOT/pages/mail-sink.adoc | 158 ++++++++++++++++++ kamelets/mail-sink.kamelet.yaml | 118 +++++++++++++ .../resources/kamelets/mail-sink.kamelet.yaml | 118 +++++++++++++ .../bindings/camel-k/mail-sink-binding.yaml | 20 +++ .../bindings/core/mail-sink-binding.yaml | 14 ++ test/mail-sink/mail-server.groovy | 6 + test/mail-sink/mail-sink.feature | 46 +++++ test/mail-sink/timer-to-mail.yaml | 24 +++ test/mail-sink/yaks-config.yaml | 47 ++++++ 13 files changed, 627 insertions(+), 4 deletions(-) create mode 100644 docs/modules/ROOT/assets/images/kamelets/mail-sink.svg create mode 100644 docs/modules/ROOT/pages/mail-sink.adoc create mode 100644 kamelets/mail-sink.kamelet.yaml create mode 100644 library/camel-kamelets/src/main/resources/kamelets/mail-sink.kamelet.yaml create mode 100644 templates/bindings/camel-k/mail-sink-binding.yaml create mode 100644 templates/bindings/core/mail-sink-binding.yaml create mode 100644 test/mail-sink/mail-server.groovy create mode 100644 test/mail-sink/mail-sink.feature create mode 100644 test/mail-sink/timer-to-mail.yaml create mode 100644 test/mail-sink/yaks-config.yaml diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 77d9d38f2..5d7b7ba0b 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -42,7 +42,8 @@ concurrency: env: CAMEL_K_VERSION: 1.5.0 - YAKS_VERSION: 0.4.0 + YAKS_VERSION: 0.6.0 + YAKS_IMAGE_NAME: "docker.io/citrusframework/yaks" jobs: test: @@ -62,7 +63,7 @@ jobs: rm -r _kamel - name: Get YAKS CLI run: | - curl --fail -L --silent https://github.com/citrusframework/yaks/releases/download/v${YAKS_VERSION}/yaks-${YAKS_VERSION}-linux-64bit.tar.gz -o yaks.tar.gz + curl --fail -L --silent https://github.com/citrusframework/yaks/releases/download/${YAKS_VERSION}/yaks-${YAKS_VERSION}-linux-64bit.tar.gz -o yaks.tar.gz mkdir -p _yaks tar -zxf yaks.tar.gz --directory ./_yaks sudo mv ./_yaks/yaks /usr/local/bin/ @@ -85,10 +86,10 @@ jobs: export KAMEL_INSTALL_REGISTRY_INSECURE=true echo "Configuring Yaks" - yaks install + yaks install --operator-image $YAKS_IMAGE_NAME:$YAKS_VERSION echo "Running tests" - yaks test ./test + yaks run ./test - uses: actions/upload-artifact@v2 if: failure() with: diff --git a/.gitignore b/.gitignore index 1d9193513..40ff173ec 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,5 @@ components/camel-cxf/activemq-data .flattened-pom.xml .java-version node_modules/ + +_output diff --git a/docs/modules/ROOT/assets/images/kamelets/mail-sink.svg b/docs/modules/ROOT/assets/images/kamelets/mail-sink.svg new file mode 100644 index 000000000..c7eee96fd --- /dev/null +++ b/docs/modules/ROOT/assets/images/kamelets/mail-sink.svg @@ -0,0 +1,68 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index c47dc770e..8a7437993 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -89,6 +89,7 @@ * xref:ROOT:kubernetes-pods-source.adoc[image:kamelets/kubernetes-pods-source.svg[] Kubernetes Pods Source] * xref:ROOT:log-sink.adoc[image:kamelets/log-sink.svg[] Log Sink] * xref:ROOT:mail-imap-source.adoc[image:kamelets/mail-imap-source.svg[] Mail IMAP Source] +* xref:ROOT:mail-sink.adoc[image:kamelets/mail-sink.svg[] Mail Sink] * xref:ROOT:mariadb-sink.adoc[image:kamelets/mariadb-sink.svg[] MariaDB Sink] * xref:ROOT:mariadb-source.adoc[image:kamelets/mariadb-source.svg[] MariaDB Source] * xref:ROOT:mask-field-action.adoc[image:kamelets/mask-field-action.svg[] Mask Fields Action] diff --git a/docs/modules/ROOT/pages/mail-sink.adoc b/docs/modules/ROOT/pages/mail-sink.adoc new file mode 100644 index 000000000..401f59030 --- /dev/null +++ b/docs/modules/ROOT/pages/mail-sink.adoc @@ -0,0 +1,158 @@ +// THIS FILE IS AUTOMATICALLY GENERATED: DO NOT EDIT + += image:kamelets/mail-sink.svg[] Mail Sink + +*Provided by: "Apache Software Foundation"* + +*Support Level for this Kamelet is: "Preview"* + +Send mails to given SMTP server. + +== Configuration Options + +The following table summarizes the configuration options available for the `mail-sink` Kamelet: +[width="100%",cols="2,^2,3,^2,^2,^3",options="header"] +|=== +| Property| Name| Description| Type| Default| Example +| *connectionHost {empty}* *| Host| The mail server host| string| | `"smtp.gmail.com"` +| *password {empty}* *| Password| The password to access the mail box| string| | +| *username {empty}* *| Username| The username to access the mail box| string| | +| connectionPort| Port| The mail server port| string| `25`| +| from| From| The `from` field of the outgoing mail| string| | +| protocol| Protocol| The mail protocol to use| string| `"smtp"`| +| subject| Subject| The mail subject of the outgoing mail| string| | +| to| To| The `to` field of the outgoing mail| string| | +|=== + +NOTE: Fields marked with an asterisk ({empty}*) are mandatory. + + +== Dependencies + +At runtime, the `mail-sink` Kamelet relies upon the presence of the following dependencies: + +- camel:core +- camel:mail +- camel:kamelet + +== Usage + +This section describes how you can use the `mail-sink`. + +=== Knative Sink + +You can use the `mail-sink` Kamelet as a Knative sink by binding it to a Knative object. + +.mail-sink-binding.yaml +[source,yaml] +---- +apiVersion: camel.apache.org/v1alpha1 +kind: KameletBinding +metadata: + name: mail-sink-binding +spec: + source: + ref: + kind: Channel + apiVersion: messaging.knative.dev/v1 + name: mychannel + sink: + ref: + kind: Kamelet + apiVersion: camel.apache.org/v1alpha1 + name: mail-sink + properties: + connectionHost: "smtp.gmail.com" + password: "The Password" + username: "The Username" + +---- + +==== *Prerequisite* + +You have xref:{camel-k-version}@camel-k::installation/installation.adoc[Camel K installed] on the cluster. + +==== *Procedure for using the cluster CLI* + +. Save the `mail-sink-binding.yaml` file to your local drive, and then edit it as needed for your configuration. + +. Run the sink by using the following command: ++ +[source,shell] +---- +kubectl apply -f mail-sink-binding.yaml +---- + +==== *Procedure for using the Kamel CLI* + +Configure and run the sink by using the following command: + +[source,shell] +---- +kamel bind channel:mychannel mail-sink -p "sink.connectionHost=smtp.gmail.com" -p "sink.password=The Password" -p "sink.username=The Username" +---- + +This command creates the KameletBinding in the current namespace on the cluster. + +=== Kafka Sink + +You can use the `mail-sink` Kamelet as a Kafka sink by binding it to a Kafka topic. + +.mail-sink-binding.yaml +[source,yaml] +---- +apiVersion: camel.apache.org/v1alpha1 +kind: KameletBinding +metadata: + name: mail-sink-binding +spec: + source: + ref: + kind: KafkaTopic + apiVersion: kafka.strimzi.io/v1beta1 + name: my-topic + sink: + ref: + kind: Kamelet + apiVersion: camel.apache.org/v1alpha1 + name: mail-sink + properties: + connectionHost: "smtp.gmail.com" + password: "The Password" + username: "The Username" + +---- + +==== *Prerequisites* + +* You've installed https://strimzi.io/[Strimzi]. +* You've created a topic named `my-topic` in the current namespace. +* You have xref:{camel-k-version}@camel-k::installation/installation.adoc[Camel K installed] on the cluster. + +==== *Procedure for using the cluster CLI* + +. Save the `mail-sink-binding.yaml` file to your local drive, and then edit it as needed for your configuration. + +. Run the sink by using the following command: ++ +[source,shell] +---- +kubectl apply -f mail-sink-binding.yaml +---- + +==== *Procedure for using the Kamel CLI* + +Configure and run the sink by using the following command: + +[source,shell] +---- +kamel bind kafka.strimzi.io/v1beta1:KafkaTopic:my-topic mail-sink -p "sink.connectionHost=smtp.gmail.com" -p "sink.password=The Password" -p "sink.username=The Username" +---- + +This command creates the KameletBinding in the current namespace on the cluster. + +== Kamelet source file + +https://github.com/apache/camel-kamelets/blob/main/kamelets/mail-sink.kamelet.yaml + +// THIS FILE IS AUTOMATICALLY GENERATED: DO NOT EDIT diff --git a/kamelets/mail-sink.kamelet.yaml b/kamelets/mail-sink.kamelet.yaml new file mode 100644 index 000000000..da5f126e7 --- /dev/null +++ b/kamelets/mail-sink.kamelet.yaml @@ -0,0 +1,118 @@ +# --------------------------------------------------------------------------- +# 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. +# --------------------------------------------------------------------------- +apiVersion: camel.apache.org/v1alpha1 +kind: Kamelet +metadata: + name: mail-sink + annotations: + camel.apache.org/kamelet.support.level: "Preview" + camel.apache.org/catalog.version: "main-SNAPSHOT" + camel.apache.org/kamelet.icon: "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM6c29kaXBvZGk9Imh0dHA6Ly9zb2RpcG9kaS5zb3VyY2Vmb3JnZS5uZXQvRFREL3NvZGlwb2RpLTAuZHRkIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIKICAgdmlld0JveD0iMCAwIDE2LjIwMDAwMSAxMi4yIgogICB2ZXJzaW9uPSIxLjEiCiAgIGlkPSJzdmc1IgogICBzb2RpcG9kaTpkb2NuYW1lPSJCcmVlemVpY29ucy1wbGFjZXMtMTYtZm9sZGVyLW1haWwuc3ZnIgogICB3aWR0aD0iMTYuMjAwMDAxIgogICBoZWlnaHQ9IjEyLjIiCiAgIGlua3NjYXBlOnZlcnNpb249IjEuMC4yIChlODZjODcwODc5LCAyMDIxLTAxLTE1KSI+CiAgPG1ldGFkYXRhCiAgICAgaWQ9Im1ldGFkYXRhOSI+CiAgICA8cmRmOlJERj4KICAgICAgPGNjOldvcmsKICAgICAgICAgcmRmOmFib3V0PSIiPgogICAgICAgIDxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PgogICAgICAgIDxkYzp0eXBlCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vcHVybC5vcmcvZGMvZGNtaXR5cGUvU3RpbGxJbWFnZSIgLz4KICAgICAgICA8ZGM6dGl0bGU+PC9kYzp0aXRsZT4KICAgICAgPC9jYzpXb3JrPgogICAgPC9yZGY6UkRGPgogIDwvbWV0YWRhdGE+CiAgPHNvZGlwb2RpOm5hbWVkdmlldwogICAgIHBhZ2Vjb2xvcj0iI2ZmZmZmZiIKICAgICBib3JkZXJjb2xvcj0iIzY2NjY2NiIKICAgICBib3JkZXJvcGFjaXR5PSIxIgogICAgIG9iamVjdHRvbGVyYW5jZT0iMTAiCiAgICAgZ3JpZHRvbGVyYW5jZT0iMTAiCiAgICAgZ3VpZGV0b2xlcmFuY2U9IjEwIgogICAgIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwIgogICAgIGlua3NjYXBlOnBhZ2VzaGFkb3c9IjIiCiAgICAgaW5rc2NhcGU6d2luZG93LXdpZHRoPSIxOTIwIgogICAgIGlua3NjYXBlOndpbmRvdy1oZWlnaHQ9IjEwMTYiCiAgICAgaWQ9Im5hbWVkdmlldzciCiAgICAgc2hvd2dyaWQ9ImZhbHNlIgogICAgIGZpdC1tYXJnaW4tdG9wPSIwLjEiCiAgICAgZml0LW1hcmdpbi1yaWdodD0iMC4xIgogICAgIGZpdC1tYXJnaW4tbGVmdD0iMC4xIgogICAgIGZpdC1tYXJnaW4tYm90dG9tPSIwLjEiCiAgICAgaW5rc2NhcGU6em9vbT0iNTMuNSIKICAgICBpbmtzY2FwZTpjeD0iOC4xIgogICAgIGlua3NjYXBlOmN5PSIzLjEwOTM0NTgiCiAgICAgaW5rc2NhcGU6d2luZG93LXg9IjAiCiAgICAgaW5rc2NhcGU6d2luZG93LXk9IjI3IgogICAgIGlua3NjYXBlOndpbmRvdy1tYXhpbWl6ZWQ9IjEiCiAgICAgaW5rc2NhcGU6Y3VycmVudC1sYXllcj0ic3ZnNSIgLz4KICA8ZGVmcwogICAgIGlkPSJkZWZzMzA1MSI+CiAgICA8c3R5bGUKICAgICAgIHR5cGU9InRleHQvY3NzIgogICAgICAgaWQ9ImN1cnJlbnQtY29sb3Itc2NoZW1lIj4KICAgICAgLkNvbG9yU2NoZW1lLVRleHQgewogICAgICAgIGNvbG9yOiM0ZDRkNGQ7CiAgICAgIH0KICAgICAgPC9zdHlsZT4KICA8L2RlZnM+CiAgPHBhdGgKICAgICBzdHlsZT0iZmlsbDpjdXJyZW50Q29sb3I7ZmlsbC1vcGFjaXR5OjE7c3Ryb2tlOm5vbmUiCiAgICAgZD0ibSAwLjEsMC4xIHYgMTIgaCAxNiB2IC0xMiB6IG0gMS40MTQwNjI1LDEgSCAxNC42ODU5MzggTCA4LjEsNy42ODU5Mzc1IFogTSAxLjEsMi4xIGwgNCw0IC00LDQgeiBtIDE0LDAgdiA4IGwgLTQsLTQgeiBNIDUuODA3MDMxMiw2LjgwNzAzMTIgOC4xLDkuMSAxMC4zOTI5NjksNi44MDcwMzEyIDE0LjY4NTkzOCwxMS4xIEggMS41MTQwNjI1IFoiCiAgICAgaWQ9InJlY3Q0MTQ0IgogICAgIGNsYXNzPSJDb2xvclNjaGVtZS1UZXh0IiAvPgo8L3N2Zz4K" + camel.apache.org/provider: "Apache Software Foundation" + camel.apache.org/kamelet.group: "Mail" + labels: + camel.apache.org/kamelet.type: "sink" +spec: + definition: + title: "Mail Sink" + description: "Send mails to given SMTP server." + required: + - connectionHost + - username + - password + type: object + properties: + protocol: + description: The mail protocol to use + default: smtp + title: Protocol + type: string + connectionHost: + description: The mail server host + example: smtp.gmail.com + title: Host + type: string + connectionPort: + description: The mail server port + title: Port + default: 25 + type: string + username: + title: Username + description: The username to access the mail box + type: string + x-descriptors: + - urn:camel:group:credentials + password: + title: Password + description: The password to access the mail box + type: string + format: password + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:password + - urn:camel:group:credentials + from: + description: The `from` field of the outgoing mail + title: From + type: string + to: + description: The `to` field of the outgoing mail + title: To + type: string + subject: + description: The mail subject of the outgoing mail + title: Subject + type: string + dependencies: + - "camel:core" + - "camel:mail" + - "camel:kamelet" + flow: + from: + uri: "kamelet:source" + steps: + - choice: + when: + - simple: "${header[ce-subject]}" + steps: + - set-header: + name: Subject + simple: "${header[ce-subject]}" + - choice: + when: + - simple: "${header[ce-from]}" + steps: + - set-header: + name: From + simple: "${header[ce-from]}" + - choice: + when: + - simple: "${header[ce-to]}" + steps: + - set-header: + name: To + simple: "${header[ce-to]}" + - choice: + when: + - simple: "${header[ce-cc]}" + steps: + - set-header: + name: Cc + simple: "${header[ce-cc]}" + - remove-headers: + pattern: "ce-*" + - to: '{{protocol}}://{{connectionHost}}:{{connectionPort}}?subject={{subject}}&from={{from}}&to={{to}}&username={{username}}&password={{password}}' diff --git a/library/camel-kamelets/src/main/resources/kamelets/mail-sink.kamelet.yaml b/library/camel-kamelets/src/main/resources/kamelets/mail-sink.kamelet.yaml new file mode 100644 index 000000000..da5f126e7 --- /dev/null +++ b/library/camel-kamelets/src/main/resources/kamelets/mail-sink.kamelet.yaml @@ -0,0 +1,118 @@ +# --------------------------------------------------------------------------- +# 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. +# --------------------------------------------------------------------------- +apiVersion: camel.apache.org/v1alpha1 +kind: Kamelet +metadata: + name: mail-sink + annotations: + camel.apache.org/kamelet.support.level: "Preview" + camel.apache.org/catalog.version: "main-SNAPSHOT" + camel.apache.org/kamelet.icon: "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM6c29kaXBvZGk9Imh0dHA6Ly9zb2RpcG9kaS5zb3VyY2Vmb3JnZS5uZXQvRFREL3NvZGlwb2RpLTAuZHRkIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIKICAgdmlld0JveD0iMCAwIDE2LjIwMDAwMSAxMi4yIgogICB2ZXJzaW9uPSIxLjEiCiAgIGlkPSJzdmc1IgogICBzb2RpcG9kaTpkb2NuYW1lPSJCcmVlemVpY29ucy1wbGFjZXMtMTYtZm9sZGVyLW1haWwuc3ZnIgogICB3aWR0aD0iMTYuMjAwMDAxIgogICBoZWlnaHQ9IjEyLjIiCiAgIGlua3NjYXBlOnZlcnNpb249IjEuMC4yIChlODZjODcwODc5LCAyMDIxLTAxLTE1KSI+CiAgPG1ldGFkYXRhCiAgICAgaWQ9Im1ldGFkYXRhOSI+CiAgICA8cmRmOlJERj4KICAgICAgPGNjOldvcmsKICAgICAgICAgcmRmOmFib3V0PSIiPgogICAgICAgIDxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PgogICAgICAgIDxkYzp0eXBlCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vcHVybC5vcmcvZGMvZGNtaXR5cGUvU3RpbGxJbWFnZSIgLz4KICAgICAgICA8ZGM6dGl0bGU+PC9kYzp0aXRsZT4KICAgICAgPC9jYzpXb3JrPgogICAgPC9yZGY6UkRGPgogIDwvbWV0YWRhdGE+CiAgPHNvZGlwb2RpOm5hbWVkdmlldwogICAgIHBhZ2Vjb2xvcj0iI2ZmZmZmZiIKICAgICBib3JkZXJjb2xvcj0iIzY2NjY2NiIKICAgICBib3JkZXJvcGFjaXR5PSIxIgogICAgIG9iamVjdHRvbGVyYW5jZT0iMTAiCiAgICAgZ3JpZHRvbGVyYW5jZT0iMTAiCiAgICAgZ3VpZGV0b2xlcmFuY2U9IjEwIgogICAgIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwIgogICAgIGlua3NjYXBlOnBhZ2VzaGFkb3c9IjIiCiAgICAgaW5rc2NhcGU6d2luZG93LXdpZHRoPSIxOTIwIgogICAgIGlua3NjYXBlOndpbmRvdy1oZWlnaHQ9IjEwMTYiCiAgICAgaWQ9Im5hbWVkdmlldzciCiAgICAgc2hvd2dyaWQ9ImZhbHNlIgogICAgIGZpdC1tYXJnaW4tdG9wPSIwLjEiCiAgICAgZml0LW1hcmdpbi1yaWdodD0iMC4xIgogICAgIGZpdC1tYXJnaW4tbGVmdD0iMC4xIgogICAgIGZpdC1tYXJnaW4tYm90dG9tPSIwLjEiCiAgICAgaW5rc2NhcGU6em9vbT0iNTMuNSIKICAgICBpbmtzY2FwZTpjeD0iOC4xIgogICAgIGlua3NjYXBlOmN5PSIzLjEwOTM0NTgiCiAgICAgaW5rc2NhcGU6d2luZG93LXg9IjAiCiAgICAgaW5rc2NhcGU6d2luZG93LXk9IjI3IgogICAgIGlua3NjYXBlOndpbmRvdy1tYXhpbWl6ZWQ9IjEiCiAgICAgaW5rc2NhcGU6Y3VycmVudC1sYXllcj0ic3ZnNSIgLz4KICA8ZGVmcwogICAgIGlkPSJkZWZzMzA1MSI+CiAgICA8c3R5bGUKICAgICAgIHR5cGU9InRleHQvY3NzIgogICAgICAgaWQ9ImN1cnJlbnQtY29sb3Itc2NoZW1lIj4KICAgICAgLkNvbG9yU2NoZW1lLVRleHQgewogICAgICAgIGNvbG9yOiM0ZDRkNGQ7CiAgICAgIH0KICAgICAgPC9zdHlsZT4KICA8L2RlZnM+CiAgPHBhdGgKICAgICBzdHlsZT0iZmlsbDpjdXJyZW50Q29sb3I7ZmlsbC1vcGFjaXR5OjE7c3Ryb2tlOm5vbmUiCiAgICAgZD0ibSAwLjEsMC4xIHYgMTIgaCAxNiB2IC0xMiB6IG0gMS40MTQwNjI1LDEgSCAxNC42ODU5MzggTCA4LjEsNy42ODU5Mzc1IFogTSAxLjEsMi4xIGwgNCw0IC00LDQgeiBtIDE0LDAgdiA4IGwgLTQsLTQgeiBNIDUuODA3MDMxMiw2LjgwNzAzMTIgOC4xLDkuMSAxMC4zOTI5NjksNi44MDcwMzEyIDE0LjY4NTkzOCwxMS4xIEggMS41MTQwNjI1IFoiCiAgICAgaWQ9InJlY3Q0MTQ0IgogICAgIGNsYXNzPSJDb2xvclNjaGVtZS1UZXh0IiAvPgo8L3N2Zz4K" + camel.apache.org/provider: "Apache Software Foundation" + camel.apache.org/kamelet.group: "Mail" + labels: + camel.apache.org/kamelet.type: "sink" +spec: + definition: + title: "Mail Sink" + description: "Send mails to given SMTP server." + required: + - connectionHost + - username + - password + type: object + properties: + protocol: + description: The mail protocol to use + default: smtp + title: Protocol + type: string + connectionHost: + description: The mail server host + example: smtp.gmail.com + title: Host + type: string + connectionPort: + description: The mail server port + title: Port + default: 25 + type: string + username: + title: Username + description: The username to access the mail box + type: string + x-descriptors: + - urn:camel:group:credentials + password: + title: Password + description: The password to access the mail box + type: string + format: password + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:password + - urn:camel:group:credentials + from: + description: The `from` field of the outgoing mail + title: From + type: string + to: + description: The `to` field of the outgoing mail + title: To + type: string + subject: + description: The mail subject of the outgoing mail + title: Subject + type: string + dependencies: + - "camel:core" + - "camel:mail" + - "camel:kamelet" + flow: + from: + uri: "kamelet:source" + steps: + - choice: + when: + - simple: "${header[ce-subject]}" + steps: + - set-header: + name: Subject + simple: "${header[ce-subject]}" + - choice: + when: + - simple: "${header[ce-from]}" + steps: + - set-header: + name: From + simple: "${header[ce-from]}" + - choice: + when: + - simple: "${header[ce-to]}" + steps: + - set-header: + name: To + simple: "${header[ce-to]}" + - choice: + when: + - simple: "${header[ce-cc]}" + steps: + - set-header: + name: Cc + simple: "${header[ce-cc]}" + - remove-headers: + pattern: "ce-*" + - to: '{{protocol}}://{{connectionHost}}:{{connectionPort}}?subject={{subject}}&from={{from}}&to={{to}}&username={{username}}&password={{password}}' diff --git a/templates/bindings/camel-k/mail-sink-binding.yaml b/templates/bindings/camel-k/mail-sink-binding.yaml new file mode 100644 index 000000000..99c9d0b2e --- /dev/null +++ b/templates/bindings/camel-k/mail-sink-binding.yaml @@ -0,0 +1,20 @@ +apiVersion: camel.apache.org/v1alpha1 +kind: KameletBinding +metadata: + name: mail-sink-binding +spec: + source: + ref: + kind: KafkaTopic + apiVersion: kafka.strimzi.io/v1beta1 + name: my-topic + sink: + ref: + kind: Kamelet + apiVersion: camel.apache.org/v1alpha1 + name: mail-sink + properties: + connectionHost: "smtp.gmail.com" + password: "The Password" + username: "The Username" + \ No newline at end of file diff --git a/templates/bindings/core/mail-sink-binding.yaml b/templates/bindings/core/mail-sink-binding.yaml new file mode 100644 index 000000000..31bd4126f --- /dev/null +++ b/templates/bindings/core/mail-sink-binding.yaml @@ -0,0 +1,14 @@ +- route: + from: + uri: "kamelet:timer-source" + parameters: + period: 1000 + message: "Hello Camel JBang" + steps: + - to: + uri: "kamelet:mail-sink" + parameters: + connectionHost: "smtp.gmail.com" + password: "The Password" + username: "The Username" + \ No newline at end of file diff --git a/test/mail-sink/mail-server.groovy b/test/mail-sink/mail-server.groovy new file mode 100644 index 000000000..d1d2c4f0e --- /dev/null +++ b/test/mail-sink/mail-server.groovy @@ -0,0 +1,6 @@ +System.properties['citrus.mail.marshaller.type'] = "JSON" + +mail() + .server('mail-server') + .port(22222) + .autoStart(true) diff --git a/test/mail-sink/mail-sink.feature b/test/mail-sink/mail-sink.feature new file mode 100644 index 000000000..489246a26 --- /dev/null +++ b/test/mail-sink/mail-sink.feature @@ -0,0 +1,46 @@ +Feature: Mail Sink + + Background: + Given Camel-K resource polling configuration + | maxAttempts | 200 | + | delayBetweenAttempts | 2000 | + Given variables + | host | mail-server | + | username | test | + | password | secret | + | from | user@demo.yaks | + | to | announcements@demo.yaks | + | subject | Kamelet workshop | + | message | Camel K rocks | + + Scenario: Create mail server + Given load endpoint mail-server.groovy + Given create Kubernetes service mail-server with port mapping 25:22222 + + Scenario: Create Camel-K resources + Given Kamelet mail-sink is available + Given Kamelet timer-source is available + Given load KameletBinding timer-to-mail.yaml + And Camel-K integration timer-to-mail should be running + + Scenario: Verify mail message sent + Then endpoint mail-server should receive body + """ + { + "from": "${from}", + "to": "${to}", + "cc": "", + "bcc": "", + "replyTo": "@ignore@", + "subject": "${subject}", + "body": { + "contentType": "text/plain", + "content": "${message}", + "attachments": null + } + } + """ + + Scenario: Remove Camel-K resources + Given delete KameletBinding timer-to-mail + And delete Kubernetes service mail-server diff --git a/test/mail-sink/timer-to-mail.yaml b/test/mail-sink/timer-to-mail.yaml new file mode 100644 index 000000000..feaa24feb --- /dev/null +++ b/test/mail-sink/timer-to-mail.yaml @@ -0,0 +1,24 @@ +apiVersion: camel.apache.org/v1alpha1 +kind: KameletBinding +metadata: + name: timer-to-mail +spec: + source: + ref: + kind: Kamelet + apiVersion: camel.apache.org/v1alpha1 + name: timer-source + properties: + message: "${message}" + sink: + ref: + apiVersion: camel.apache.org/v1alpha1 + kind: Kamelet + name: mail-sink + properties: + connectionHost: "${host}" + username: "${username}" + password: "${password}" + from: "${from}" + to: "${to}" + subject: "${subject}" diff --git a/test/mail-sink/yaks-config.yaml b/test/mail-sink/yaks-config.yaml new file mode 100644 index 000000000..f1be932a0 --- /dev/null +++ b/test/mail-sink/yaks-config.yaml @@ -0,0 +1,47 @@ +# --------------------------------------------------------------------------- +# 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. +# --------------------------------------------------------------------------- + +config: + runtime: + env: + - name: YAKS_CAMELK_AUTO_REMOVE_RESOURCES + value: false + - name: YAKS_KUBERNETES_AUTO_REMOVE_RESOURCES + value: false + settings: + dependencies: + - groupId: com.consol.citrus + artifactId: citrus-mail + version: "@citrus.version@" + resources: + - mail-server.groovy + - timer-to-mail.yaml +pre: +- name: installation + run: | + # Install required Kamelets (these steps may be done globally in future versions) + + kamel install -n $YAKS_NAMESPACE -w + kubectl delete kamelet -n $YAKS_NAMESPACE --all + kubectl apply -f ../../kamelets/mail-sink.kamelet.yaml -n $YAKS_NAMESPACE + kubectl apply -f ../../kamelets/timer-source.kamelet.yaml -n $YAKS_NAMESPACE +post: +- name: dump + run: | + kamel dump -n $YAKS_NAMESPACE $(basename `pwd`)-dump.log + mkdir -p /tmp/dumps + cp *-dump.log /tmp/dumps