go-smtp

An ESMTP client and server library for Go, implementing RFC 5321 plus AUTH, LMTP, and modern mail extensions.

Library
Go
vv0.25.0
2,048stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
66/100Good
Development Activity52
Maintenance40
Community72
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
78/100Good
Architecture82
Code Quality85
Innovation78
Learning Curve65

go-smtp is a Go library that implements the Simple Mail Transfer Protocol end to end: an ESMTP client for sending mail and a full ESMTP/LMTP server implementation for receiving it. It exists because the Go standard library’s net/smtp is frozen and client-only, so any project that needs a real SMTP server, or client features beyond the basics, has to look elsewhere.

On the server side, consumers implement a small Backend/Session interface pair to plug in their own mail storage or routing logic, while go-smtp handles the protocol state machine, line parsing, error codes, and optional extensions (STARTTLS, AUTH via SASL, DSN, CHUNKING/BINARYMIME, SMTPUTF8, and more). The client mirrors this with a Dial/Client API for connecting, authenticating, and streaming a message body without buffering it entirely in memory.

It is maintained by emersion, the author of several widely used Go mail and IMAP libraries, and is used as the SMTP layer inside real mail servers and mail-handling tools rather than as a toy example implementation.

What You Get

  • An ESMTP client (Client, Dial, DialTLS, DialStartTLS) for connecting, authenticating via SASL, and streaming message bodies to a remote server
  • A pluggable ESMTP server (Server, Backend, Session) where you implement mail handling and go-smtp handles the RFC 5321 command loop
  • LMTP (RFC 2033) support via the same server, for per-recipient delivery status reporting through the optional LMTPSession/StatusCollector interfaces
  • Extension support for AUTH, STARTTLS, PIPELINING, 8BITMIME, BINARYMIME/CHUNKING, DSN, SMTPUTF8, DELIVERBY, MT-PRIORITY, and RRVS, each toggled independently on Server
  • Structured SMTP error values (SMTPError with numeric code, enhanced code, and message) instead of opaque strings, usable from both client and server code

Common Use Cases

  • Building a custom mail server or mail-relay component that needs full control over how incoming messages are accepted, validated, and stored
  • Implementing LMTP delivery between a mail transfer agent and a local delivery agent, with per-recipient status reporting
  • Adding outbound SMTP submission with SASL authentication to a Go application, beyond what the frozen net/smtp package supports
  • Prototyping or testing SMTP-speaking services locally, including the bundled smtp-debug-server command for inspecting raw client traffic

Under The Hood

Architecture go-smtp separates cleanly into a server half and a client half that share only low-level plumbing (net/textproto, SASL, error types). On the server side, Server owns the listener accept loop and per-connection bookkeeping (server.go), handing each connection to a Conn (conn.go) that runs the RFC 5321 command state machine: it wraps the raw connection in a line-limited reader, parses commands via parse.go, and dispatches them to a library-supplied Backend/Session implementation (backend.go). Extension behavior (LMTP status collection, BDAT chunking via an io.Pipe, dot-stuffed DATA streaming through a custom dataReader in data.go) is layered on top of this core loop rather than baked into it, so a minimal backend only needs to implement Reset/Logout/Mail/Rcpt/Data, while optional interfaces (LMTPSession, AuthSession) add capability without forcing every implementer to support it. The client (client.go) is a largely independent RFC 5321 implementation reusing the same textproto and SMTPError types, decoupled from the server’s Conn/Backend machinery.

Tech Stack The library has a single external dependency, github.com/emersion/go-sasl, for SASL authentication mechanisms; everything else is Go standard library (net, crypto/tls, net/textproto, bufio, encoding/base64). go.mod targets Go 1.13, favoring broad compatibility over newer language features. There is no web framework, database, or build tooling beyond go build/go test; CI runs on sourcehut (.build.yml) rather than GitHub Actions, executing race-detector builds and tests with coverage reporting plus a gofmt formatting check. A small cmd/smtp-debug-server binary ships alongside the library for manual protocol inspection.

Code Quality Testing is extensive relative to the library’s size: client_test.go and server_test.go are each larger than the production code they cover, with additional dedicated coverage for LMTP (lmtp_server_test.go) and command parsing (parse_test.go), plus runnable Example* functions that double as documentation. CI runs the full suite with the race detector and tracks coverage, and enforces gofmt formatting on every build. Errors are consistently typed via SMTPError (numeric code, RFC 2034 enhanced code, message) rather than ad hoc strings, used uniformly across client and server. There is no separate linter configuration beyond gofmt, and the test suite relies on the standard library’s testing package without an assertion framework, which is idiomatic for Go but means less structured failure output than table-driven frameworks with custom matchers.

API Design The Backend/Session split is the core design decision: it lets applications own mail storage and routing while go-smtp owns protocol correctness, and optional interfaces (AuthSession for AUTH, LMTPSession for per-recipient LMTP status) are additive so simple backends stay simple. The extension surface is unusually broad for a Go SMTP library — most alternatives cover only basic ESMTP, while go-smtp also implements LMTP, DELIVERBY, MT-PRIORITY, and RRVS, extensions rarely found outside MTA-grade software. Combined with the frozen, client-only state of the standard library’s net/smtp, this makes go-smtp one of the few Go options for building a real SMTP server rather than only a client.

Used by 8 apps in this directory

Go
75%
AGPL 3.0

Coder

Devops · Developer Tools · Code Editors

14,463

Self-hosted cloud development environments and AI coding agents — defined in Terraform, connected via WireGuard, automatically shut down when idle.

View details
93
Repo Health
90
Technical
65
Dependency
Built with
Go75%
TypeScript23%
Updated 2 days ago
Go
45%
Apache 2.0

e2a

AI Agents · Automation

189

Give your AI agents a real, authenticated email address — with SPF/DKIM-verified inbound, HMAC-signed delivery, WebSocket fan-out, and human-in-the-loop approval built in.

View details
78
Repo Health
80
Technical
71
Dependency
Built with
Go45%
TypeScript27%
Python14%
Updated 4 days ago
Go
84%
MIT

Hatchet

AI Development · Developer Tools · Automation

7,938

A Postgres-backed orchestration engine for background tasks, AI agents, and durable workflows that replaces Redis queues and multi-datastore durable execution platforms with a single self-hostable service.

View details
88
Repo Health
83
Technical
67
Dependency
Built with
Go84%
PLpgSQL11%
Updated 3 days ago
PHP
63%
AGPL 3.0

Hyvor Relay

Devops · AI Development · Monitoring

891

Self-hosted, open-source email API that automates DNS, manages SMTP delivery, and provides deep observability — replacing SES, Mailgun, and SendGrid with infrastructure you fully own.

View details
68
Repo Health
79
Technical
70
Dependency
Built with
PHP63%
Svelte23%
Go12%
Updated 3 days ago
Go
75%
Other

Notifuse

Marketing

2,198

Open-source, self-hosted alternative to Mailchimp, Brevo, and Klaviyo — send newsletters and transactional emails without per-email pricing or vendor lock-in.

View details
82
Repo Health
80
Technical
66
Dependency
Built with
Go75%
TypeScript23%
Updated 4 days ago
Go
73%
Apache 2.0

ntfy

Developer Tools · Marketing

34,222

Send push notifications to your phone or desktop from any script or service using a single HTTP PUT or POST—no sign-up required.

View details
89
Repo Health
89
Technical
75
Dependency
Built with
Go73%
JavaScript26%
Updated 1 weeks ago
TypeScript
50%
Other

SigNoz

Monitoring · Analytics

32,100

Self-host your entire observability stack — logs, metrics, traces, and LLM monitoring — in one OpenTelemetry-native platform, without the Datadog bill.

View details
92
Repo Health
83
Technical
67
Dependency
Built with
TypeScript50%
Go38%
Updated 2 days ago
Go
78%
MIT

Wakapi

Developer Tools · Analytics

4,432

Self-hosted WakaTime-compatible coding statistics backend that gives developers full control over their coding activity data.

View details
90
Repo Health
77
Technical
72
Dependency
Built with
Go78%
HTML12%
Updated 3 days ago

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search