Self-hosted email infrastructure

One endpoint between
your apps and email.

egate is a focused application-to-application email gateway backed by SQLite and Postmark. Centralize provider credentials, issue revocable API keys, and send transactional email over a small HTTP API.

01

Small surface area

One authenticated email endpoint, one health check, and no unnecessary runtime dependencies.

02

Keys you control

Create separate keys for each application and revoke access without rotating your Postmark server token.

03

Simple operations

A single Go binary, a SQLite database, and a Docker workflow with persistent local storage.

Quickstart

Send an email

Send a JSON request to your egate host with an API key in the bearer authorization header.

Shell
curl https://egate.example.com/v1/email \
  -H 'Authorization: Bearer eg_YOUR_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "from": "sender@example.com",
    "to": "recipient@example.com",
    "subject": "Hello from egate",
    "text_body": "Your transactional email is ready."
  }'

HTTP API

POST /v1/email

Submits a message to Postmark. egate passes the provider response body and HTTP status through unchanged.

Headers

Authorizationrequired

Bearer eg_YOUR_KEY

Content-Typerequired

application/json

JSON body

fromstring · required

Sender address accepted by your Postmark account.

tostring · required

Recipient address.

subjectstring · required

Message subject.

text_bodystring

Plain-text body. At least one of text_body or html_body is required.

html_bodystring

HTML message body.

reply_tostring · optional

Address used for recipient replies.

Responses

2xx

Postmark accepted the request. The exact provider status and JSON response are returned.

400

The JSON is invalid or a required field is missing.

401

The bearer token is missing, invalid, or revoked.

502

The email provider could not be reached.

Go SDK

Use egate from Go

Install the module, construct a client with your deployment URL and API key, then send a typed message.

Install
go get github.com/englandsystems/egate
Go
client, err := sdk.NewClient(
  "https://egate.example.com",
  os.Getenv("EGATE_API_KEY"),
)
if err != nil {
  log.Fatal(err)
}

response, err := client.SendEmail(ctx, sdk.Email{
  From:     "sender@example.com",
  To:       "recipient@example.com",
  Subject:  "Hello from egate",
  TextBody: "Your transactional email is ready.",
})

Operations

Run it reliably

egate is designed to sit behind a TLS reverse proxy. Persist its SQLite data directory and keep credentials outside the image.

Health check

GET /healthz

Returns {"ok":true} with status 200 when the process can serve traffic.

Limits and behavior

Request size

Email request bodies are limited to 1 MiB.

Timeouts

Provider requests time out after 15 seconds.

Persistence

API keys, sessions, and security records live in the configured SQLite database.

Transport security

Terminate TLS at a reverse proxy and restrict direct access to the application port in production.