Skip to content

Commit

Permalink
Merge pull request #1 from eexit/aws-lambda
Browse files Browse the repository at this point in the history
AWS Lambda support via Serverless
  • Loading branch information
eexit authored Jan 7, 2021
2 parents 18f679c + ceac6bc commit 1af6d79
Show file tree
Hide file tree
Showing 13 changed files with 499 additions and 27 deletions.
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.env*
.git*
http2smtp
40 changes: 33 additions & 7 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,11 @@ jobs:
name: Unit tests + coverage
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Go 1.x
uses: actions/setup-go@v2
with:
go-version: ^1.15
- name: Check out code into the Go module directory
uses: actions/checkout@v2
- name: Get dependencies
run: go get -v -t -d ./...
- name: Build
Expand All @@ -34,19 +33,19 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: golangci-lint
- name: Lint the codebase
uses: golangci/golangci-lint-action@v2
with:
version: v1.34
publish:
if: contains(github.ref, 'refs/tags/')
name: Docker publish
runs-on: ubuntu-latest
if: contains(github.ref, 'refs/tags/')
needs: [ tests, lint ]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- uses: docker/setup-qemu-action@v1
- uses: docker/setup-buildx-action@v1
- name: Login to DockerHub
uses: docker/login-action@v1
with:
Expand All @@ -58,6 +57,7 @@ jobs:
- name: Build and push
uses: docker/build-push-action@v2
with:
platforms: linux/amd64
build-args: version=${{ steps.tagref.outputs.tag }}+${{ github.sha }}
tags: '${{ github.repository }}:${{ steps.tagref.outputs.tag }},${{ github.repository }}:latest'
push: true
Expand All @@ -67,3 +67,29 @@ jobs:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
repository: ${{ github.repository }}
release-bin:
name: Release binaries
if: contains(github.ref, 'refs/tags/')
needs: [ tests, lint ]
runs-on: ubuntu-latest
env:
CGO_ENABLED: 0
strategy:
matrix:
target: [http2smtp, http2smtp-lambda]
steps:
- uses: actions/checkout@v2
- name: Retrieve tag
id: tagref
run: echo ::set-output name=tag::${GITHUB_REF#refs/*/}
- uses: wangyoucao577/[email protected]
with:
github_token: ${{ secrets.GH_TOKEN }}
goos: linux
goarch: amd64
goversion: '1.15'
project_path: cmd/${{ matrix.target }}
binary_name: ${{ matrix.target }}
extra_files: LICENSE README.md
release_tag: ${{ steps.tagref.outputs.tag }}
ldflags: -X github.com/eexit/http2smtp/internal/api.Version=${{ steps.tagref.outputs.tag }}+${{ github.sha }}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
.env
coverage.txt
http2smtp
.serverless
7 changes: 4 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
FROM golang:1-alpine AS builder
RUN apk --update add ca-certificates
FROM golang:1 AS builder
RUN update-ca-certificates
ARG version
ARG goos=linux
ARG goarch=amd64
LABEL version=${version}
WORKDIR /go/src/github.com/eexit/http2smtp
COPY . .
# Inject the build version: https://blog.alexellis.io/inject-build-time-vars-golang/
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \
RUN CGO_ENABLED=0 GOOS=${goos} GOARCH=${goarch} go build \
-ldflags "-X github.com/eexit/http2smtp/internal/api.Version=${version}" \
-o /http2smtp \
./cmd/http2smtp
Expand Down
29 changes: 15 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,41 @@
# 📩 HTTP to SMTP

[![version](https://img.shields.io/github/v/tag/eexit/http2smtp?label=version&logo=github&sort=semver)](https://github.com/eexit/http2smtp/releases) [![docker pull](https://img.shields.io/docker/pulls/eexit/http2smtp)](https://hub.docker.com/repository/docker/eexit/http2smtp) [![ci](https://github.com/eexit/http2smtp/workflows/build/badge.svg)](https://github.com/eexit/http2smtp/actions) [![codecov](https://codecov.io/gh/eexit/http2smtp/branch/master/graph/badge.svg?token=XH18EYLDLZ)](https://codecov.io/gh/eexit/http2smtp) [![license](https://img.shields.io/github/license/eexit/http2smtp)](https://github.com/eexit/http2smtp/blob/master/LICENSE)
[![ci](https://github.com/eexit/http2smtp/workflows/build/badge.svg)](https://github.com/eexit/http2smtp/actions) [![codecov](https://codecov.io/gh/eexit/http2smtp/branch/master/graph/badge.svg?token=XH18EYLDLZ)](https://codecov.io/gh/eexit/http2smtp) [![version](https://img.shields.io/github/v/tag/eexit/http2smtp?label=version&logo=github&sort=semver)](https://github.com/eexit/http2smtp/releases) [![license](https://img.shields.io/github/license/eexit/http2smtp)](https://github.com/eexit/http2smtp/blob/master/LICENSE)

An API that forwards HTTP-backed vendor mailer calls to SMTP.

Plug a [MailHog](https://github.com/mailhog/MailHog) or [MailCatcher](https://mailcatcher.me/) to API email sending vendors such as [SparkPost](https://www.sparkpost.com/), [Mailgun](https://www.mailgun.com/) or [SendGrid](https://sendgrid.com/) for testing purposes.

#### Features

- :white_check_mark: 100% code coverage
- :whale: Light Docker image available
- :zap: AWS Lambda Function 3-commands deployment

## Usage

See [examples](examples).

:zap: ProTip: for tracing purposes, this app kinda supports [W3C Trace Context recommendation](https://www.w3.org/TR/trace-context/). Configure the env var `TRACEPARENT_HEADER` and inject any trace into this header value. All log entries will be contextualized with the given value.

### Docker image
### Docker image [![docker pull](https://img.shields.io/docker/pulls/eexit/http2smtp)](https://hub.docker.com/repository/docker/eexit/http2smtp) [![size](https://img.shields.io/docker/image-size/eexit/http2smtp?sort=semver)](https://hub.docker.com/repository/docker/eexit/http2smtp)

1. Checkout this repo or only copy the `.env.dist` and `docker-compose.yml` files
1. Rename `.env.dist` into `.env`
1. Optional: update the values accordingly
1. Pull images and run `docker-compose up http2smtp`

## Vendor endpoints

### [SparkPost](https://developers.sparkpost.com/api/)
### AWS Lambda Function ![aws-lambda-ready](https://img.shields.io/badge/aws-lambda--ready-orange?logo=amazon-aws&style=flat)

#### Inline transmission
:zap: This project is also shipped for an AWS Lambda Function-ready. Check out the [README](cmd/http2smtp-lambda).

API documentation: https://developers.sparkpost.com/api/transmissions/#transmissions-post-send-inline-content
## Vendors

_:warning: Not supported yet._

#### RFC 822 transmission

API documentation: https://developers.sparkpost.com/api/transmissions/#transmissions-post-send-rfc822-content
### [SparkPost](https://developers.sparkpost.com/api/)

POST /sparkpost/api/v1/transmissions

SparkPost supports either [inline](https://developers.sparkpost.com/api/transmissions/#transmissions-post-send-inline-content) or [RFC 822 transmissions](https://developers.sparkpost.com/api/transmissions/#transmissions-post-send-rfc822-content). For now, only the latter one is supported.

Basic validation is enforced, only the recipients list email and the RFC 822 content are used and mandatory.

## License
Expand All @@ -43,4 +44,4 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file

## Contributors

![contributors](https://contrib.rocks/image?repo=eexit/http2smtp)
[![contributors](https://contrib.rocks/image?repo=eexit/http2smtp)](https://github.com/eexit/http2smtp/graphs/contributors)
24 changes: 24 additions & 0 deletions cmd/http2smtp-lambda/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
URL=https://api.github.com/repos/eexit/http2smtp/releases/latest

.DEFAULT: usage

usage:
@echo '+-------------------------------------------------------------------+'
@echo '| Make Usage |'
@echo '+-------------------------------------------------------------------+'
@grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "|- \033[33m%-15s\033[0m -> %s\n", $$1, $$2}'

install-sls: ## Installs serverless (via NPM)
npm install -g serverless --ignore-scripts --loglevel error

config: ## Prints the resolved stack config
sls print --verbose

download: ## Gets the latest version of the binary
curl -sL $(URL) | jq -r '.assets[].browser_download_url' | grep lambda | grep -v md5 | xargs wget -qO- | tar xvz http2smtp-lambda

deploy: ## Deploys the stack
sls deploy --verbose

remove: ## Removes the stack
sls remove --verbose
33 changes: 33 additions & 0 deletions cmd/http2smtp-lambda/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# :zap: http2smtp for AWS Lambda

Deploy in 3 commands (assuming you already have a SMTP server deployed).

## Usage

```
$ make
+-------------------------------------------------------------------+
| Make Usage |
+-------------------------------------------------------------------+
|- config -> Prints the resolved stack config
|- deploy -> Deploys the stack
|- download -> Gets the latest version of the binary
|- install-sls -> Installs serverless (via NPM)
|- remove -> Removes the stack
```

## Deploying

- Install [serverless](https://www.serverless.com/) [yourself](https://www.serverless.com/framework/docs/getting-started/) or run `make install-sls`
- Edit the `serverless.yml` file with the [wished configuration](https://www.serverless.com/framework/docs/providers/aws/guide/serverless.yml/)
- Run `make download && make deploy`

### Deploying a specific version

If you wish to download a specific version of http2smtp, you can prefix the download URL as env var prior calling `make download`:

```bash
$ URL=https://api.github.com/repos/eexit/http2smtp/releases/tags/v1.2.3 make download
```

Then deploy using `make deploy`.
Binary file added cmd/http2smtp-lambda/http2smtp-lambda
Binary file not shown.
47 changes: 47 additions & 0 deletions cmd/http2smtp-lambda/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package main

import (
"math/rand"
"os"
"time"

"github.com/aws/aws-lambda-go/lambda"
"github.com/awslabs/aws-lambda-go-api-proxy/httpadapter"
"github.com/eexit/http2smtp/internal/api"
"github.com/eexit/http2smtp/internal/converter"
"github.com/eexit/http2smtp/internal/env"
"github.com/eexit/http2smtp/internal/smtp"
"github.com/kelseyhightower/envconfig"
"github.com/rs/zerolog"
)

func main() {
rand.Seed(time.Now().UTC().UnixNano())

var e env.Bag
envconfig.MustProcess("", &e)

level, err := zerolog.ParseLevel(e.LogLevel)
if err != nil {
panic(err)
}

logger := zerolog.New(os.Stdout).
Level(level).
With().
Timestamp().
Str("version", api.Version).
Logger()

smtpClient := smtp.New(e.SMTPAddr, logger)

converterProvider := converter.NewProvider(
converter.NewRFC5322(),
converter.NewSparkPost(),
)

app := api.New(e, logger, smtpClient, converterProvider)
adapter := httpadapter.New(app.Wrap(app.Mux()))

lambda.StartHandler(lambda.NewHandler(adapter.ProxyWithContext))
}
25 changes: 25 additions & 0 deletions cmd/http2smtp-lambda/serverless.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
service: http2smtp-lambda
frameworkVersion: '2'
useDotenv: true

provider:
name: aws
runtime: go1.x

package:
exclude:
- ./**
include:
- http2smtp-lambda

functions:
proxy:
handler: http2smtp-lambda
memorySize: 128
environment:
SMTP_ADDR: 'smtp:25'
LOG_LEVEL: debug
events:
- http:
path: '{proxy+}'
method: any
File renamed without changes.
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ module github.com/eexit/http2smtp
go 1.15

require (
github.com/aws/aws-lambda-go v1.22.0
github.com/awslabs/aws-lambda-go-api-proxy v0.9.0
github.com/go-playground/validator/v10 v10.4.1
github.com/gorilla/mux v1.8.0
github.com/justinas/alice v1.2.0
github.com/kelseyhightower/envconfig v1.4.0
github.com/rs/zerolog v1.20.0
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f // indirect
)
Loading

0 comments on commit 1af6d79

Please sign in to comment.