Skip to content
ariefsnPublic

About

Surat is a lightweight email notification service with support for MJML (email templates), Handlebars (variable injection), and built-in Swagger API docs. It is packaged as a Docker image for easy deployment with SMTP integration.

Topics

Resources

Stars

4 stars

Watchers

0 watching

Forks

Repository files navigation

📧 Surat – Mini Email Notification Service

Surat is a lightweight email notification service with support for MJML (email templates), Handlebars (variable injection), and built-in Swagger API docs.
It is packaged as a Docker image for easy deployment with SMTP integration.


✨ Features

  • 📩 Send emails via any SMTP provider
  • 🎨 Templating with MJML + Handlebars
  • 🛠️ Auto-generated Swagger docs (/api)
  • 🐳 Docker image ready to use
  • 🔑 Easy configuration via environment variables
  • 🔒 Optional API key authentication
  • 📎 Attachments (plain text or base64), including inline images

🚀 Quick Start

Pull image

docker pull ariefsn/surat:latest

Run container

docker run -d \
  -p 3000:3000 \
  -e PORT=3000 \
  -e SMTP_HOST=smtp.example.com \
  -e SMTP_PORT=587 \
  -e SMTP_USER=myuser \
  -e SMTP_PASSWORD=mypassword \
  -e SMTP_SECURE=false \
  -e DEFAULT_SENDER_EMAIL=no-reply@example.com \
  -e DEFAULT_SENDER_NAME="Surat" \
  -e SMTP_POOL=true \
  -e SMTP_MAX_CONNECTIONS=10 \
  -e SMTP_MAX_MESSAGES=100 \
  -e BODY_LIMIT=10mb \
  -e API_KEY=change-me \
  --name surat \
  ariefsn/surat:latest

Docker Compose

version: "3.8"

services:
  surat:
    image: ariefsn/surat:latest
    container_name: surat
    restart: unless-stopped
    ports:
      - "3000:3000"
    environment:
      PORT: 3000
      SMTP_HOST: smtp.example.com
      SMTP_PORT: 587
      SMTP_USER: myuser
      SMTP_PASSWORD: mypassword
      SMTP_SECURE: "false"
      SMTP_POOL: "true"
      SMTP_MAX_CONNECTIONS: "10"
      SMTP_MAX_MESSAGES: "100"
      DEFAULT_SENDER_EMAIL: no-reply@example.com
      DEFAULT_SENDER_NAME: "Surat"
      BODY_LIMIT: "10mb"
      API_KEY: change-me

⚙️ Environment Variables

Variable Required Default Description
PORT ✅ 3000 Port the app listens on
SMTP_HOST ✅ – SMTP server host
SMTP_PORT ✅ – SMTP server port
SMTP_USER ✅ – SMTP username
SMTP_PASSWORD ✅ – SMTP password
SMTP_SECURE ❌ false Enable TLS/SSL (true / false)
SMTP_POOL ❌ true Enable connection pooling (true / false)
SMTP_MAX_CONNECTIONS ❌ 10 Max SMTP connections per pool
SMTP_MAX_MESSAGES ❌ 100 Max messages per connection
DEFAULT_SENDER_EMAIL ✅ – Default sender email address
DEFAULT_SENDER_NAME ✅ – Default sender display name
BODY_LIMIT ❌ 10mb Body limit for requests
API_KEY ❌ – When set, /email and /mjml require a matching X-API-Key header. Leave empty to disable auth

💡 You can store them in a .env file and run with:

docker compose --env-file .env up -d

Example .env:

PORT=3000
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USER=myuser
SMTP_PASSWORD=mypassword
SMTP_SECURE=false
DEFAULT_SENDER_EMAIL=no-reply@example.com
DEFAULT_SENDER_NAME=Surat
BODY_LIMIT=10mb
API_KEY=change-me

📖 API Documentation

Swagger UI is available at:
👉 http://localhost:3000/api

Endpoints:

  • GET / → Health check
  • POST /email → Send an email
  • POST /mjml → Convert MJML to HTML

🔒 Authentication

Authentication is off by default. Set API_KEY to turn it on. Requests to POST /email and POST /mjml must then send the same value in the X-API-Key header, or they get 401 Unauthorized. GET / (health check) and the Swagger UI (/api) stay public.

curl -X POST http://localhost:3000/email \
  -H "Content-Type: application/json" \
  -H "X-API-Key: change-me" \
  -d @payload.json

In Swagger UI, click Authorize and enter the key.


📎 Attachments

POST /email accepts an attachments array. Each item has these fields:

Field Required Description
filename ✅ File name shown to the recipient
content ✅ File content, as plain text or encoded (see encoding)
encoding ❌ Encoding of content, e.g. base64. Omit it to send content as plain text
type ❌ MIME type, e.g. application/pdf, image/png. Guessed from filename when omitted
disposition ❌ attachment (default) or inline
contentId ❌ Content ID for inline images, referenced in the body as cid:<contentId>

Surat never guesses the encoding. Binary files such as PDFs and images must be sent base64-encoded with "encoding": "base64", otherwise the recipient gets the base64 text instead of the file.

{
  "attachments": [
    {
      "filename": "invoice.pdf",
      "content": "JVBERi0xLjQK...",
      "encoding": "base64",
      "type": "application/pdf"
    },
    {
      "filename": "note.txt",
      "content": "Hello from Surat"
    },
    {
      "filename": "logo.png",
      "content": "iVBORw0KGgo...",
      "encoding": "base64",
      "type": "image/png",
      "disposition": "inline",
      "contentId": "logo"
    }
  ]
}

The inline image above is shown in the body with <img src="cid:logo">.

Attachment size counts toward BODY_LIMIT. Base64 makes a file about 33% larger.


🧩 Handlebars Helpers

The service provides several custom Handlebars helpers out of the box, so you can use them directly inside your email templates:

Helper Example (Template) Result
add {{add 2 3}} 5
gt {{gt 5 3}} true
gte {{gte 5 5}} true
lt {{lt 2 5}} true
lte {{lte 2 2}} true
eq {{eq "a" "a"}} true
ne {{ne "a" "b"}} true
or {{or true false}} true
and {{and true false}} false
not {{not true}} false
contains {{contains "hello world" "wor"}} true
startWith {{startWith "hello" "he"}} true
endWith {{endWith "hello" "lo"}} true
replace {{replace "foo bar" "bar" "baz"}} foo baz
json {{json myObject}} {"key":"value"}

👉 Example MJML + Handlebars usage:

<mj-text>
  Hello {{name}},  
  You have {{add unreadCount 1}} unread messages.
</mj-text>

🛠 Tech Stack


📜 License

This project is licensed under the MIT License.

About

Surat is a lightweight email notification service with support for MJML (email templates), Handlebars (variable injection), and built-in Swagger API docs. It is packaged as a Docker image for easy deployment with SMTP integration.

Topics

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages