SkillAgentSearch skills...

Kannon

✉️ Cloud-Native massive mail sender for Kubernetes!

Install / Use

/learn @kannon-email/Kannon
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Kannon 💥

CI

Kannon Logo

A Cloud Native SMTP mail sender for Kubernetes and modern infrastructure.

[!NOTE] Due to limitations of AWS, GCP, etc. on port 25, this project will not work on cloud providers that block port 25.


Table of Contents


Features

  • Cloud-native, scalable SMTP mail sending
  • gRPC API for sending HTML and templated emails
  • DKIM and SPF support for deliverability
  • Attachments support (JSONB in DB)
  • Custom fields for emails (JSONB in DB)
  • Statistics and analytics (DB + gRPC API)
  • Template management (CRUD via API)
  • Kubernetes-ready deployment
  • Postgres-backed persistence

Planned:

  • Multi-node sending
  • Advanced analytics dashboard

Architecture

Kannon is composed of several microservices and workers:

  • API: gRPC server for mail, template, and domain management
  • SMTP: Handles SMTP protocol and relays mail
  • Sender: Sends emails from the queue
  • Dispatcher: Manages the sending pool and delivery
  • Verifier: Validates emails before sending
  • Bounce: Handles bounces
  • Stats: Collects and stores delivery statistics

All components can be enabled/disabled via CLI flags or config.

See ARCHITECTURE.md for a full breakdown of modules, NATS streams, topics, consumers, and message flows.

flowchart TD
    subgraph Core
        API["gRPC API"]
        SMTP["SMTP Server"]
        Sender["Sender"]
        Dispatcher["Dispatcher"]
        Verifier["Verifier"]
        Bounce["Bounce"]
        Stats["Stats"]
    end
    DB[(PostgreSQL)]
    NATS[(NATS)]
    API <--> DB
    Dispatcher <--> DB
    Sender <--> DB
    Verifier <--> DB
    Stats <--> DB
    Bounce <--> DB
    API <--> NATS
    Sender <--> NATS
    Dispatcher <--> NATS
    SMTP <--> NATS
    Stats <--> NATS
    Verifier <--> NATS
    Bounce <--> NATS

Quickstart

Prerequisites

  • Go 1.25.5+
  • Docker (optional, for containerized deployment)
  • PostgreSQL database
  • NATS server (optional - embedded mode available in standalone command)

Standalone Mode (Recommended for Development/Testing)

Run all Kannon components in a single process with embedded NATS (only PostgreSQL required):

git clone https://github.com/kannon-email/kannon.git
cd kannon
go build -o kannon .
./kannon standalone --config ./config.yaml

This mode:

  • Runs all components (API, SMTP, Sender, Dispatcher, Verifier, Stats, Bounce)
  • Embeds NATS server (no external NATS required)
  • Ideal for development, testing, or single-server deployments
  • Still requires a PostgreSQL database

Local Run (Manual Component Selection)

git clone https://github.com/kannon-email/kannon.git
cd kannon
go build -o kannon .
./kannon --run-api --run-smtp --run-sender --run-dispatcher --config ./config.yaml

Note: This mode requires an external NATS server configured in your config file.

Docker Compose

See examples/docker-compose/ for ready-to-use files.

docker-compose -f examples/docker-compose/docker-compose.yaml up
  • Edit examples/docker-compose/kannon.yaml to configure your environment.

Makefile Targets

  • make test — Run all tests
  • make generate — Generate DB and proto code
  • make lint — Run linters

Configuration

Kannon can be configured via YAML file, environment variables, or CLI flags. Precedence: CLI > Env > YAML.

Main config options:

| Key / Env Var | Type | Default | Description | | ----------------------------------------------- | -------- | -------------- | -------------------------------------- | | database_url / K_DATABASE_URL | string | (required) | PostgreSQL connection string | | nats_url / K_NATS_URL | string | (required) | NATS server URL for internal messaging | | debug / K_DEBUG | bool | false | Enable debug logging | | api.port / K_API_PORT | int | 50051 | gRPC API port | | sender.hostname / K_SENDER_HOSTNAME | string | (required) | Hostname for outgoing mail | | sender.max_jobs / K_SENDER_MAX_JOBS | int | 10 | Max parallel sending jobs | | sender.demo_sender / K_SENDER_DEMO_SENDER | bool | false | Enable demo sender mode for testing | | smtp.address / K_SMTP_ADDRESS | string | :25 | SMTP server listen address | | smtp.domain / K_SMTP_DOMAIN | string | localhost | SMTP server domain | | smtp.read_timeout / K_SMTP_READ_TIMEOUT | duration | 10s | SMTP read timeout | | smtp.write_timeout / K_SMTP_WRITE_TIMEOUT | duration | 10s | SMTP write timeout | | smtp.max_payload / K_SMTP_MAX_PAYLOAD | size | 1024kb | Max SMTP message size | | smtp.max_recipients / K_SMTP_MAX_RECIPIENTS | int | 50 | Max recipients per SMTP message | | run-api / K_RUN_API | bool | false | Enable API server | | run-smtp / K_RUN_SMTP | bool | false | Enable SMTP server | | run-sender / K_RUN_SENDER | bool | false | Enable sender worker | | run-dispatcher / K_RUN_DISPATCHER | bool | false | Enable dispatcher worker | | run-verifier / K_RUN_VERIFIER | bool | false | Enable verifier worker | | run-bounce / K_RUN_BOUNCE | bool | false | Enable bounce worker | | run-stats / K_RUN_STATS | bool | false | Enable stats worker | | config | string | ~/.kannon.yaml | Path to config file |

Database Schema

Kannon requires a PostgreSQL database. Main tables:

  • domains: Registered sender domains, DKIM keys
  • api_keys: API keys for authentication (multiple keys per domain, expirable, revocable)
  • messages: Outgoing messages, subject, sender, template, attachments, custom headers
  • sending_pool_emails: Email queue, status, scheduling, custom fields
  • templates: Email templates, type, metadata
  • stats: Delivery and open/click statistics
  • stats_keys: Public/private keys for stats security

See db/migrations/ for full schema and migrations.

API Overview

Kannon exposes a gRPC API for sending mail, managing domains/templates, and retrieving stats.

Services & Methods

  • Mailer API (proto)
    • SendHTML: Send a raw HTML email
    • SendTemplate: Send an email using a stored template
  • Admin API (proto)
    • Domains: GetDomains, GetDomain, CreateDomain
    • Templates: CreateTemplate, UpdateTemplate, DeleteTemplate, GetTemplate, GetTemplates
    • API Keys: CreateAPIKey, ListAPIKeys, GetAPIKey, DeactivateAPIKey
  • Stats API (proto)
    • GetStats, GetStatsAggregated

Authentication

All gRPC APIs use Basic Auth with your domain and API key:

token = base64(<your domain>:<your api key>)

Pass this in the Authorization metadata for gRPC calls:

{
  "Authorization": "Basic <your token>"
}

Example: SendHTML Request

{
  "sender": {
    "email": "no-reply@yourdomain.com",
    "alias": "Your Name"
  },
  "recipients": ["user@example.com"],
  "subject": "Test",
  "html": "<h1>Hello</h1><p>This is a test.</p>",
  "attachments": [
    { "filename": "file.txt", "content": "base64-encoded-content" }
  ],
  "fields": { "custom": "value" },
  "headers": {
    "to": ["visible-recipient@example.com"],
    "cc": ["cc@example.com"]
  }
}

Headers

The optional headers field allows overriding the To and adding a Cc header on sent emails. The SMTP envelope recipient (actual delivery target) remains the pool recipient, but the visible mail headers will use the values from headers:

  • to: Overrides the To header displayed in the email client
  • cc: Adds a Cc header to the email

This is useful for scenarios where you want the email to appear addressed to a group or alias while delivering to individual recipients.

See the proto files for all fields and options.

Deployment

Kubernetes

  • See k8s/deployment.yaml for a production-ready manifest.
  • Configure your environment via a mounted YAML file or environment variables.

Docker Compose

Domain & DNS Setup

To send mail, you must register a sender domain and configure DNS:

  1. Register a domain via the Admin API

Related Skills

View on GitHub
GitHub Stars76
CategoryDevelopment
Updated2d ago
Forks14

Languages

Go

Security Score

100/100

Audited on Apr 5, 2026

No findings