Small surface area
One authenticated email endpoint, one health check, and no unnecessary runtime dependencies.
Self-hosted email infrastructure
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.
One authenticated email endpoint, one health check, and no unnecessary runtime dependencies.
Register each calling app to get its own key. Revoke an app without rotating your Resend API key.
A single Go binary, a SQLite database, and a Docker workflow with persistent local storage.
Quickstart
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.
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
Submits a message to Resend. egate passes the provider response body and HTTP status through unchanged.
AuthorizationrequiredBearer eg_YOUR_KEY
Content-Typerequiredapplication/json
fromstring · requiredSender address accepted by your Resend account.
tostring · requiredRecipient address.
subjectstring · requiredMessage subject.
text_bodystringPlain-text body. At least one of text_body or html_body is required.
html_bodystringHTML message body.
reply_tostring · optionalAddress used for recipient replies.
2xxResend accepted the request. The exact provider status and JSON response are returned.
400The JSON is invalid or a required field is missing.
401The bearer token is missing, invalid, or revoked.
502The email provider could not be reached.
Go SDK
Install the module, construct a client with your deployment URL and API key, then send a typed message.
go get github.com/englandsystems/egateclient, 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
egate is designed to sit behind a TLS reverse proxy. Persist its SQLite data directory and keep credentials outside the image.
GET /healthzReturns {"ok":true} with status 200 when the process can serve traffic.
Request sizeEmail request bodies are limited to 1 MiB.
TimeoutsProvider requests time out after 15 seconds.
PersistenceRegistered apps, keys, sessions, and security records live in the configured SQLite database.
Transport securityTerminate TLS at a reverse proxy and restrict direct access to the application port in production.