From 12e8730d0075882a0e412cb411b163e7e92defa8 Mon Sep 17 00:00:00 2001 From: Jorge Tudela Date: Fri, 9 Oct 2020 13:06:05 +0200 Subject: [PATCH] Adds SMTP relay server (maildev) --- charts/maildev/.helmignore | 23 ++++ charts/maildev/Chart.yaml | 9 ++ charts/maildev/README.md | 95 +++++++++++++++ charts/maildev/templates/NOTES.txt | 1 + charts/maildev/templates/_helpers.tpl | 63 ++++++++++ .../templates/cm-auto-relay-rules.yaml | 6 + charts/maildev/templates/deployment.yaml | 114 ++++++++++++++++++ charts/maildev/templates/route-smtp.yaml | 18 +++ charts/maildev/templates/route-web.yaml | 16 +++ charts/maildev/templates/service-smtp.yaml | 17 +++ charts/maildev/templates/service-web.yaml | 17 +++ charts/maildev/templates/serviceaccount.yaml | 12 ++ charts/maildev/values.yaml | 102 ++++++++++++++++ 13 files changed, 493 insertions(+) create mode 100644 charts/maildev/.helmignore create mode 100644 charts/maildev/Chart.yaml create mode 100644 charts/maildev/README.md create mode 100644 charts/maildev/templates/NOTES.txt create mode 100644 charts/maildev/templates/_helpers.tpl create mode 100644 charts/maildev/templates/cm-auto-relay-rules.yaml create mode 100644 charts/maildev/templates/deployment.yaml create mode 100644 charts/maildev/templates/route-smtp.yaml create mode 100644 charts/maildev/templates/route-web.yaml create mode 100644 charts/maildev/templates/service-smtp.yaml create mode 100644 charts/maildev/templates/service-web.yaml create mode 100644 charts/maildev/templates/serviceaccount.yaml create mode 100644 charts/maildev/values.yaml diff --git a/charts/maildev/.helmignore b/charts/maildev/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/charts/maildev/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/charts/maildev/Chart.yaml b/charts/maildev/Chart.yaml new file mode 100644 index 00000000..00da1016 --- /dev/null +++ b/charts/maildev/Chart.yaml @@ -0,0 +1,9 @@ +apiVersion: v2 +appVersion: v1.1.0 +description: A Helm chart for deploying maildev SMTP server. +name: maildev +type: application +version: 0.1.0 +home: https://github.com/redhat-cop/helm-charts +maintainers: +- name: jtudelag diff --git a/charts/maildev/README.md b/charts/maildev/README.md new file mode 100644 index 00000000..3188cb0b --- /dev/null +++ b/charts/maildev/README.md @@ -0,0 +1,95 @@ +# SMTP relay service +This helm-chart installs [Maildev](https://github.com/maildev/maildev). + +Its mainly usage is to provide with a SMTP relay service inside OpenShift, +so other apps can rely on it to send mails externally. + +Inside the Namespace where it is deployed, an SMTP service is available: `smtp:25`. + +Maildev also provides a Web interface, it can be disabled/enabled at discretion. +By default it exposed at a route. + +Also note that mails do not persist after reboot. Everytime Maildev starts, it starts from scratch, +even if the `/tmp/maildev` folder, where Maildev stores mails, is persisted. + +And I haven't found any way to configure Maildev so it reload previous mails after a reboot.... + +# Sources code +Maildev source code can be here: https://github.com/maildev/maildev + +# Known issue with Env Vars + +Github issue: https://github.com/maildev/maildev/issues/315 + +So, not every option can be configured using env vars, so, a few options are hardcoded in the deployment: +`["--verbose", "--outgoing-secure", "--auto-relay"]` + +## Configuration + +Table with the most relevants parameters for MailDev. +Not listing here the more general paramaters such as tolerations, nodeSelectors, etc. + +| Parameter | Description | Default | +|------------------------------:|:--------------------------------------------------------------------------------------------------|:--------------------------------------------| +| **outgoing_relay.host** | SMTP Relay host, `MAILDEV_OUTGOING_HOST`. | `` | +| **outgoing_relay.port** | SMTP Relay port, `MAILDEV_OUTGOING_PORT`. | `` | +| **outgoing_relay.user** | SMTP Relay user, `MAILDEV_OUTGOING_USER`. | `` | +| **outgoing_relay.pass** | SMTP Relay password, `MAILDEV_OUTGOING_PASS`. | `` | +| **outgoing_relay.secure** | Use SMTP SSL for outgoing emails, `MAILDEV_OUTGOING_SECURE`. | `true`. Hardcoded in the deployment due to a bug. | +| **ports.smtp** | Port where the SMTP service is listenning. (Irrelevant for OCP/K8S), `MAILDEV_SMTP_PORT`. | `1025` | +| **ports.web** | Port where the Web interface service is listenning. (Irrelevant for OCP/K8S), `MAILDEV_WEB_PORT`. | `1080` | +| **web.disable** | Disable Web interface. `MAILDEV_DISABLE_WEB`. | `False` | +| **web.user** | Web interface user, `MAILDEV_WEB_USER`. | `admin` | +| **web.pass** | Web interface password, `MAILDEV_WEB_PASS`. | `` | +| **https.enabled** | Switch from http to https protocol, `MAILDEV_HTTPS`. | `False` | +| **https.key** | The file path to the ssl private key, `MAILDEV_HTTPS_KEY`. | | +| **https.cert** | The file path to the ssl cert file, `MAILDEV_HTTPS_CERT`. | | +| **incoming.user** | SMTP user for incoming emails, `MAILDEV_INCOMING_USER`. | | +| **incoming.pass** | SMTP password for incoming emails, `MAILDEV_INCOMING_PASS`. | | + +# Test it + +rsh into the pod. +```bash +oc rsh $(oc get pod -l "app.kubernetes.io/instance=maildev" -o name) +``` + +Create summy mail.txt file. +```bash +cat <> mail.txt +From: Test Maildev +To: Jorge Tudela +Subject: Test mail from maildev +Date: Fri, 17 Nov 2020 11:26:16 + +Dear Joe, +Welcome to this example email. What a lovely day. +Cheers!! +EOF +``` + +Send the mail with curl: +```bash +curl smtp://smtp:25 --mail-from test@maildev.com --mail-rcpt jtudelag@redhat.com --upload-file ./mail.txt +``` + +Check the logs and see if the mail has been delivered. +```bash +oc logs $(oc get pod -l "app.kubernetes.io/instance=maildev" -o name) +Temporary directory created at /tmp/maildev +Temporary directory created at /tmp/maildev/1 +MailDev outgoing SMTP Server smtp.gmail.com:465 (user:rht-labs-noreply@redhat.com, pass:####, secure:yes) +Auto-Relay mode on +MailDev webapp running at http://0.0.0.0:1080 +MailDev SMTP Server running at 0.0.0.0:1025 +Saving email: Test mail from maildev, id: 3ZhYnk5q +MailDev outgoing SMTP Server smtp.gmail.com:465 (user:rht-labs-noreply@redhat.com, pass:####, secure:yes) +Mail Delivered: Test mail from maildev +``` + +Alternatively you can check the webconsole. +```bash +oc get route web-maildev -o=jsonpath='{.spec.host}' +``` + +Check your mail inbox ;) \ No newline at end of file diff --git a/charts/maildev/templates/NOTES.txt b/charts/maildev/templates/NOTES.txt new file mode 100644 index 00000000..39e26336 --- /dev/null +++ b/charts/maildev/templates/NOTES.txt @@ -0,0 +1 @@ +# Sources code here: https://github.com/maildev/maildev \ No newline at end of file diff --git a/charts/maildev/templates/_helpers.tpl b/charts/maildev/templates/_helpers.tpl new file mode 100644 index 00000000..c3039c63 --- /dev/null +++ b/charts/maildev/templates/_helpers.tpl @@ -0,0 +1,63 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "maildev.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "maildev.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "maildev.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "maildev.labels" -}} +helm.sh/chart: {{ include "maildev.chart" . }} +{{ include "maildev.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "maildev.selectorLabels" -}} +app.kubernetes.io/name: {{ include "maildev.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "maildev.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "maildev.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/charts/maildev/templates/cm-auto-relay-rules.yaml b/charts/maildev/templates/cm-auto-relay-rules.yaml new file mode 100644 index 00000000..4348e65d --- /dev/null +++ b/charts/maildev/templates/cm-auto-relay-rules.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +data: + auto-relay-rules.json: "[\n\t{ \"allow\": \"*\" }\n]\n" +kind: ConfigMap +metadata: + name: maildev-relay-rules diff --git a/charts/maildev/templates/deployment.yaml b/charts/maildev/templates/deployment.yaml new file mode 100644 index 00000000..928ea60e --- /dev/null +++ b/charts/maildev/templates/deployment.yaml @@ -0,0 +1,114 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "maildev.fullname" . }} + labels: + {{- include "maildev.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "maildev.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "maildev.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "maildev.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + command: ["/opt/app-root/src/bin/maildev"] + args: ["--verbose", "--outgoing-secure", "--auto-relay"] + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: smtp-port + containerPort: {{ .Values.ports.smtp }} + protocol: TCP + - name: web-port + containerPort: {{ .Values.ports.web }} + protocol: TCP + env: + - name: MAILDEV_DISABLE_WEB + value: "{{ .Values.web.disable }}" + {{- if or .Values.web.user .Values.web.pass}} + - name: MAILDEV_WEB_USER + value: "{{ .Values.web.user }}" + - name: MAILDEV_WEB_PASS + value: "{{ .Values.web.pass }}" + {{- end }} + - name: MAILDEV_SMTP_PORT + value: "{{ .Values.ports.smtp }}" + - name: MAILDEV_WEB_PORT + value: "{{ .Values.ports.web }}" + - name: MAILDEV_HTTPS + value: "{{ .Values.https.enabled }}" + {{- if .Values.https.key }} + - name: MAILDEV_HTTPS_KEY + value: "{{ .Values.https.key }}" + {{- end }} + {{- if .Values.https.cert }} + - name: MAILDEV_HTTPS_CERT + value: "{{ .Values.https.cert }}" + {{- end }} + - name: MAILDEV_OUTGOING_HOST + value: "{{ .Values.outgoing_relay.host }}" + - name: MAILDEV_OUTGOING_PORT + value: "{{ .Values.outgoing_relay.port }}" + - name: MAILDEV_OUTGOING_USER + value: "{{ .Values.outgoing_relay.user }}" + - name: MAILDEV_OUTGOING_PASS + value: "{{ .Values.outgoing_relay.pass }}" + - name: MAILDEV_OUTGOING_SECURE + value: "{{ .Values.outgoing_relay.secure }}" + {{- if .Values.incoming }} + - name: MAILDEV_INCOMING_USER + value: "{{ .Values.incoming.user }}" + - name: MAILDEV_INCOMING_PASS + value: "{{ .Values.incoming.pass }}" + {{- end }} + livenessProbe: + httpGet: + path: /healthz + port: {{ .Values.ports.web }} + readinessProbe: + httpGet: + path: /healthz + port: {{ .Values.ports.web }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumeMounts: + - name: auto-relay-rules + mountPath: /etc/maildev + subpath: auto-relay-rules.json + volumes: + - name: auto-relay-rules + configMap: + name: maildev-relay-rules + items: + - key: auto-relay-rules.json + path: auto-relay-rules.json + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/charts/maildev/templates/route-smtp.yaml b/charts/maildev/templates/route-smtp.yaml new file mode 100644 index 00000000..5e948969 --- /dev/null +++ b/charts/maildev/templates/route-smtp.yaml @@ -0,0 +1,18 @@ +{{- if .Values.ports.smtp }} +apiVersion: route.openshift.io/v1 +kind: Route +metadata: + name: "smtp" + labels: + {{- include "maildev.labels" . | nindent 4 }} +spec: + port: + targetPort: {{ .Values.ports.smtp }} + to: + kind: Service + name: smtp + weight: 100 + tls: + termination: passthrough + wildcardPolicy: None +{{- end }} \ No newline at end of file diff --git a/charts/maildev/templates/route-web.yaml b/charts/maildev/templates/route-web.yaml new file mode 100644 index 00000000..78fbbae5 --- /dev/null +++ b/charts/maildev/templates/route-web.yaml @@ -0,0 +1,16 @@ +{{- if .Values.ports.web }} +apiVersion: route.openshift.io/v1 +kind: Route +metadata: + name: "web-{{ include "maildev.fullname" . }}" + labels: + {{- include "maildev.labels" . | nindent 4 }} +spec: + port: + targetPort: {{ .Values.ports.web }} + to: + kind: Service + name: web-{{ include "maildev.fullname" . }} + weight: 100 + wildcardPolicy: None +{{- end }} \ No newline at end of file diff --git a/charts/maildev/templates/service-smtp.yaml b/charts/maildev/templates/service-smtp.yaml new file mode 100644 index 00000000..0c3106b6 --- /dev/null +++ b/charts/maildev/templates/service-smtp.yaml @@ -0,0 +1,17 @@ +{{- if .Values.ports.smtp }} +apiVersion: v1 +kind: Service +metadata: + name: smtp + labels: + {{- include "maildev.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - name: smtp-{{ .Values.ports.smtp }}-tcp + port: 25 + protocol: TCP + targetPort: {{ .Values.ports.smtp }} + selector: + {{- include "maildev.selectorLabels" . | nindent 4 }} +{{- end }} \ No newline at end of file diff --git a/charts/maildev/templates/service-web.yaml b/charts/maildev/templates/service-web.yaml new file mode 100644 index 00000000..daa28c7d --- /dev/null +++ b/charts/maildev/templates/service-web.yaml @@ -0,0 +1,17 @@ +{{- if .Values.ports.web }} +apiVersion: v1 +kind: Service +metadata: + name: "web-{{ include "maildev.fullname" . }}" + labels: + {{- include "maildev.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - name: web-{{ .Values.ports.smtp }}-tcp + port: {{ .Values.ports.web }} + protocol: TCP + targetPort: {{ .Values.ports.web }} + selector: + {{- include "maildev.selectorLabels" . | nindent 4 }} +{{- end }} \ No newline at end of file diff --git a/charts/maildev/templates/serviceaccount.yaml b/charts/maildev/templates/serviceaccount.yaml new file mode 100644 index 00000000..07a28f1d --- /dev/null +++ b/charts/maildev/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "maildev.serviceAccountName" . }} + labels: + {{- include "maildev.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/charts/maildev/values.yaml b/charts/maildev/values.yaml new file mode 100644 index 00000000..60104e6b --- /dev/null +++ b/charts/maildev/values.yaml @@ -0,0 +1,102 @@ +--- +appName: &name maildev + +# Default values for maildev. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: docker.io/maildev/maildev + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: v1.1.0 + +outgoing_relay: + # MAILDEV_OUTGOING_HOST + host: smtp.gmail.com + # MAILDEV_OUTGOING_PORT + port: 465 + # MAILDEV_OUTGOING_USER + user: 'XXX' + # MAILDEV_OUTGOING_PASS + pass: 'YYY' + # MAILDEV_OUTGOING_SECURE + secure: true + +incoming: + # MAILDEV_INCOMING_USER + # user: + # MAILDEV_INCOMING_PASS + # pass: + +ports: + # MAILDEV_SMTP_PORT + smtp: 1025 + # MAILDEV_WEB_PORT + web: 1080 + +# MAILDEV_HTTPS +https: + enabled: false + # MAILDEV_HTTPS_KEY + # key: + # MAILDEV_HTTPS_KEY + # cert: + +# Web interface +web: + # MAILDEV_DISABLE_WEB + disable: false + # MAILDEV_WEB_USER + user: admin + # MAILDEV_WEB_PASS + pass: admin + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +nodeSelector: {} + +tolerations: [] + +affinity: {}