Self-hosted email infrastructure

One endpoint between
your apps and email.

egate is a focused application-to-application email gateway backed by SQLite and Resend. Sign in to register apps, issue a secret connection key for each app, 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

Apps you control

Register each calling app to get its own key. Revoke an app without rotating your Resend API key.

03

Simple operations

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

Quickstart

Send an email

First register an app in the admin dashboard and copy its key. Then send a JSON request to egate with the 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": "[email protected]",
    "to": "[email protected]",
    "subject": "Hello from egate",
    "text_body": "Your transactional email is ready."
  }'

HTTP API

POST /v1/email

Submits a message to Resend. 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 Resend 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

Resend 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:     "[email protected]",
  To:       "[email protected]",
  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

Registered apps, 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.