generated from cds-snc/project-template
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
15fed37
commit 1529e3c
Showing
21 changed files
with
1,231 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// For format details, see https://aka.ms/devcontainer.json. For config options, see the | ||
// README at: https://github.com/devcontainers/templates/tree/main/src/go | ||
{ | ||
"name": "Go", | ||
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile | ||
"image": "mcr.microsoft.com/devcontainers/go:1-1.21-bullseye", | ||
"containerEnv": { | ||
"SHELL": "/bin/zsh" | ||
}, | ||
"features": { | ||
"ghcr.io/devcontainers/features/docker-in-docker:2": {}, | ||
"ghcr.io/rocker-org/devcontainer-features/apt-packages:1": { | ||
"packages": "telnet" | ||
} | ||
}, | ||
"extensions": [ | ||
"redhat.vscode-yaml", | ||
"github.copilot" | ||
], | ||
"remoteUser": "vscode" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
name: CI Latest Release | ||
on: | ||
pull_request: | ||
branches: | ||
- main | ||
|
||
jobs: | ||
ci-latest-release: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 | ||
|
||
- name: Build a new release based on the code | ||
run: make release-test | ||
|
||
- name: Diff binaries | ||
run: diff -u ./release/latest/smtp-proxy-for-notify ./release/latest/smtp-proxy-for-notify-test || exit 1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
FROM alpine:3.6 as alpine | ||
|
||
RUN apk add -U --no-cache ca-certificates | ||
|
||
FROM scratch | ||
|
||
ARG SMTP_TLS_CERT_FILE | ||
ARG SMTP_TLS_KEY_FILE | ||
ARG SMTP_TLS_CERT_FILE_DESTINATION_DIR=/etc/ssl/certs/ | ||
ARG SMTP_TLS_KEY_FILE_DESTINATION_DIR=/etc/ssl/private/ | ||
|
||
# Copy the CA certs from the alpine image | ||
COPY --from=alpine /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ | ||
|
||
# Copy the TLS cert and key files if they are defined. | ||
# Copying the LICENSE just allows for an optional copy of the certs if they are not defined. | ||
COPY LICENSE ${SMTP_TLS_CERT_FILE}* ${SMTP_TLS_CERT_FILE_DESTINATION_DIR} | ||
COPY LICENSE ${SMTP_TLS_KEY_FILE}* ${SMTP_TLS_KEY_FILE_DESTINATION_DIR} | ||
|
||
# Copy the binary | ||
COPY ./release/latest/smtp-proxy-for-notify /smtp-proxy-for-notify | ||
|
||
# Run the binary | ||
ENTRYPOINT ["/smtp-proxy-for-notify"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
FROM golang:1.21.5-alpine as build | ||
|
||
WORKDIR /app | ||
|
||
COPY go.mod ./ | ||
COPY go.sum ./ | ||
RUN go mod download | ||
|
||
COPY *.go ./ | ||
|
||
RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -o /smtp-proxy-for-notify |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
.EXPORT_ALL_VARIABLES: | ||
NOTIFY_HOSTNAME=https://api.staging.notification.cdssandbox.xyz | ||
NOTIFY_APIKEY=gcntfy-test-00000000-0000-4000-8000-000000000000-00000000-0000-4000-8000-0000000000000 | ||
NOTIFY_TEMPLATE_ID=00000000-0000-4000-8000-000000000000 | ||
|
||
SMTP_USE_TLS=true | ||
SMTP_TLS_CERT_FILE=./example_certs/server.crt | ||
SMTP_TLS_KEY_FILE=./example_certs/server.key | ||
SMTP_HOSTNAME=localhost | ||
SMTP_PORT=1025 | ||
SMTP_USERNAME=username | ||
SMTP_PASSWORD=longpasswordgo | ||
|
||
TEST_SENDER=author@localhost | ||
TEST_RECIPIENT[email protected] | ||
|
||
.PHONY: dev generate-keys release release-test script-test-python test | ||
|
||
dev: | ||
@echo "Starting dev server..." | ||
@go run . | ||
|
||
generate-keys: | ||
@cd example_certs && \ | ||
rm -f server.key server.crt && \ | ||
echo "Generating keys..." && \ | ||
openssl genrsa -out server.key 2048 && \ | ||
openssl req -new -x509 -sha256 -key server.key -out server.crt -days 3650 -subj /CN=localhost/O=smtp-proxy-for-notify/C=CA | ||
|
||
release: | ||
@mkdir -p release/latest | ||
@docker build -t smtp-proxy-for-notify-build -f Dockerfile.build . | ||
@docker create -ti --name smtp-proxy-for-notify-build smtp-proxy-for-notify-build bash | ||
@docker cp smtp-proxy-for-notify-build:/smtp-proxy-for-notify release/latest/smtp-proxy-for-notify | ||
@docker rm -f smtp-proxy-for-notify-build | ||
|
||
release-test: | ||
@mkdir -p release/latest | ||
@docker build -t smtp-proxy-for-notify-build -f Dockerfile.build . | ||
@docker create -ti --name smtp-proxy-for-notify-build smtp-proxy-for-notify-build bash | ||
@docker cp smtp-proxy-for-notify-build:/smtp-proxy-for-notify release/latest/smtp-proxy-for-notify-test | ||
@docker rm -f smtp-proxy-for-notify-build | ||
|
||
script-test-python: | ||
@python3 ./bin/test_send.py | ||
|
||
test: | ||
@go test -cover ./... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,70 @@ | ||
# Generic Project Template | ||
# SMTP Proxy for Notify | ||
|
||
This repository provides some base files for setting up a repository at | ||
CDS. Plan is to create more project template for specific technologies: | ||
This is a simple SMTP proxy for Notify that bridges the gap between the SMTP protocol and the Notify API. The proxy listens for SMTP connections and converts the SMTP message into a Notify API call. The Notify API then sends the message to the recipient. Attachments are supported. | ||
|
||
- project-template-terraform | ||
- project-template-python | ||
- project-template-nodejs | ||
## Usage | ||
|
||
Note that default community health files are maintained at https://github.com/cds-snc/.github | ||
### Requirements | ||
|
||
- A Notify account | ||
- A Notify API key | ||
- A Notify template ID | ||
|
||
Your template must have a `subject` and `body` field. For example, the template should look something like this: | ||
|
||
![An image showing a Notify template](https://github.com/cds-snc/smtp-proxy-for-notify/assets/867334/a868d28b-f4fb-4069-95ed-6fb11bbf5aae) | ||
|
||
### Environment variables | ||
|
||
| Variable | Description | Required | Default | | ||
| --- | --- | --- | --- | | ||
| NOTIFY_APIKEY | Your Notify API key | Yes | | | ||
| NOTIFY_HOSTNAME | The hostname of the Notify API | No | https://api.notification.canada.ca | | ||
| NOTIFY_TEMPLATE_ID | Your Notify template ID | Yes | | | ||
| SMTP_TLS_CERT_FILE | Path to your TLS certificate file | No | | | ||
| SMTP_TLS_KEY_FILE | Path to your TLS key file | No | | | ||
| SMTP_USE_TLS | Whether to use TLS or not | No | false | | ||
| SMTP_HOSTNAME | The hostname to listen on | No | localhost | | ||
| SMTP_PORT | The port to listen on | No | 1025 | | ||
| SMTP_USERNAME | The username to use for authentication | Yes | | ||
| SMTP_PASSWORD | The password to use for authentication | Yes | | ||
|
||
### Running | ||
|
||
#### Locally | ||
|
||
You can run the proxy locally using the following command as long as you have all the environment variables set: | ||
|
||
```bash | ||
./release/latest/smtp-proxy-for-notify | ||
``` | ||
|
||
#### Docker | ||
|
||
The proxy can also be run using Docker. You can build the image using the Dockerfile in this repository. However, you should provide your own TLS certificate and key files. You can do this by building the image with the `SMTP_TLS_CERT_FILE` and `SMTP_TLS_KEY_FILE` build arguments. For example: | ||
|
||
```bash | ||
docker build --build-arg SMTP_TLS_CERT_FILE="example_certs/server.crt" --build-arg=SMTP_TLS_KEY_FILE="example_certs/server.key" -t smtp . | ||
``` | ||
|
||
The alternative is to mount the certificate and key files into the container at runtime. | ||
|
||
To run the container, you can use the following command assuming you built it with the Dockerfile in this repository: | ||
|
||
```bash | ||
docker run \ | ||
-e NOTIFY_APIKEY=gcntfy-test-00000000-0000-4000-8000-000000000000-00000000-0000-4000-8000-0000000000000 \ | ||
-e NOTIFY_TEMPLATE_ID=00000000-0000-4000-8000-0000000000008 \ | ||
-e SMTP_TLS_CERT_FILE=/etc/ssl/certs/server.crt \ | ||
-e SMTP_TLS_KEY_FILE=/etc/ssl/private/server.key \ | ||
-e SMTP_USE_TLS=true \ | ||
-e SMTP_HOSTNAME=0.0.0.0 \ | ||
-e SMTP_USERNAME=username \ | ||
-e SMTP_PASSWORD=longpasswordgo \ | ||
-p 1025:1025 \ | ||
smtp | ||
``` | ||
|
||
# License | ||
|
||
MIT License |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# Send an email to a local smtp server using the smtplib module | ||
import os | ||
import random | ||
import smtplib | ||
import ssl | ||
import string | ||
import email.utils | ||
from email.mime.text import MIMEText | ||
from email.message import EmailMessage | ||
|
||
# Generate random string for the attachment | ||
def randomword(length): | ||
letters = string.ascii_lowercase | ||
return ''.join(random.choice(letters) for i in range(length)) | ||
|
||
email = EmailMessage() | ||
email['subject'] = "Simple test message" | ||
email.set_content("This is the body of the message.") | ||
|
||
attachment_size_in_kb = 1000 | ||
|
||
#for i in range(5): | ||
# email.add_attachment( | ||
# randomword(attachment_size_in_kb * 1024).encode('utf-8'), | ||
# filename="attachment-{}.txt".format(i), | ||
# maintype="application", | ||
# subtype="txt" | ||
# ) | ||
|
||
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) | ||
server = smtplib.SMTP_SSL("0.0.0.0", 1025) | ||
server.ehlo() # send the extended hello to our server | ||
server.set_debuglevel(True) # show communication with the server | ||
try: | ||
server.login(os.environ["SMTP_USERNAME"], os.environ["SMTP_PASSWORD"]) | ||
server.sendmail(os.environ["TEST_SENDER"], [os.environ["TEST_RECIPIENT"]], email.as_string()) | ||
finally: | ||
server.quit() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
package main | ||
|
||
import ( | ||
"errors" | ||
"regexp" | ||
|
||
"github.com/spf13/viper" | ||
) | ||
|
||
type Config struct { | ||
// Notify settings | ||
Notify struct { | ||
ApiKey string | ||
Hostname string | ||
TemplateId string | ||
} | ||
|
||
// SMTP settings | ||
Smtp struct { | ||
// Hostname to listen on | ||
Hostname string | ||
Port int | ||
|
||
// Username and password for authentication | ||
Username string | ||
Password string | ||
|
||
// Start TLS | ||
UseTLS bool | ||
TlsCertFile string | ||
TlsKeyFile string | ||
} | ||
} | ||
|
||
func initConfig() (*Config, error) { | ||
viper.AutomaticEnv() | ||
|
||
var configuration Config | ||
var err error | ||
|
||
// Set default values | ||
viper.SetDefault("LogLevel", "info") | ||
viper.SetDefault("Notify_ApiKey", "") | ||
viper.SetDefault("Notify_Hostname", "https://api.notification.canada.ca") | ||
viper.SetDefault("Notify_Template_Id", "") | ||
viper.SetDefault("Smtp_Hostname", "localhost") | ||
viper.SetDefault("Smtp_Port", 1025) | ||
viper.SetDefault("Smtp_Username", "") | ||
viper.SetDefault("Smtp_Password", "") | ||
viper.SetDefault("Smtp_Use_tls", false) | ||
viper.SetDefault("Smtp_tls_cert_file", "") | ||
viper.SetDefault("Smtp_tls_key_file", "") | ||
|
||
configuration.Notify.ApiKey = viper.GetString("Notify_ApiKey") | ||
configuration.Notify.Hostname = viper.GetString("Notify_Hostname") | ||
configuration.Notify.TemplateId = viper.GetString("Notify_Template_Id") | ||
configuration.Smtp.Hostname = viper.GetString("Smtp_Hostname") | ||
configuration.Smtp.Port = viper.GetInt("Smtp_Port") | ||
configuration.Smtp.Username = viper.GetString("Smtp_Username") | ||
configuration.Smtp.Password = viper.GetString("Smtp_Password") | ||
configuration.Smtp.UseTLS = viper.GetBool("Smtp_Use_TLS") | ||
configuration.Smtp.TlsCertFile = viper.GetString("Smtp_tls_cert_file") | ||
configuration.Smtp.TlsKeyFile = viper.GetString("Smtp_tls_key_file") | ||
|
||
// Validate username is no less than three characters | ||
if len(configuration.Smtp.Username) < 3 { | ||
err := errors.New("username must be at least three characters") | ||
return &configuration, err | ||
} | ||
|
||
// Validate password is no less than fourteen characters | ||
if len(configuration.Smtp.Password) < 14 { | ||
err := errors.New("password must be at least fourteen characters") | ||
return &configuration, err | ||
} | ||
|
||
// Validate API key starts with gcntfy and is not less than 81 characters | ||
if len(configuration.Notify.ApiKey) < 81 || configuration.Notify.ApiKey[:6] != "gcntfy" { | ||
err := errors.New("API key must start with gcntfy and be at least 81 characters") | ||
return &configuration, err | ||
} | ||
|
||
// Validate Notify Template ID matches a UUIDv4 using regex | ||
r, _ := regexp.Compile(`^[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-4[0-9a-fA-F]{3}\-[89abAB][0-9a-fA-F]{3}\-[0-9a-fA-F]{12}$`) | ||
if !r.MatchString(configuration.Notify.TemplateId) { | ||
err := errors.New("notify Template ID must be a UUIDv4") | ||
return &configuration, err | ||
} | ||
|
||
// If TLS is enabled, validate the certificate and key file paths | ||
if configuration.Smtp.UseTLS { | ||
if configuration.Smtp.TlsCertFile == "" { | ||
err := errors.New("TLS certificate file path must be specified") | ||
return &configuration, err | ||
} | ||
if configuration.Smtp.TlsKeyFile == "" { | ||
err := errors.New("TLS key file path must be specified") | ||
return &configuration, err | ||
} | ||
} | ||
|
||
return &configuration, err | ||
} |
Oops, something went wrong.