Skip to content

vugarfamiloglu/corvus

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🦅 Corvus

A self-hosted mail server written from scratch in Go. SMTP (inbound MTA + authenticated submission), IMAP4rev1, POP3, an outbound delivery queue with DKIM signing and DSN bounces, SPF/DMARC checking, greylisting and a built-in web admin panel + webmail — all in a single static binary with the mail protocols implemented by hand on top of the Go standard library.

Corvus is built as a learning-grade, portfolio reference implementation: every wire protocol (RFC 5321, 3501, 1939) and authentication mechanism (DKIM RFC 6376, SPF RFC 7208, DMARC RFC 7489) is implemented in this repository — no third-party mail libraries.

Go 1.26 License Apache 2.0 Single binary CGO disabled From scratch


Features

Area What's implemented
SMTP inbound (MTA) RFC 5321 state machine, ESMTP (STARTTLS, SIZE, 8BITMIME, SMTPUTF8, PIPELINING, ENHANCEDSTATUSCODES), open-relay prevention (mail accepted only for local domains), greylisting, SPF check, DKIM verify, DMARC policy, spam scoring → INBOX / Junk
SMTP submission Ports 587 (STARTTLS) & 465 (implicit TLS), AUTH PLAIN/LOGIN over TLS only, DKIM-signs outbound, queues external recipients
Outbound delivery Persistent queue, MX lookup, from-scratch SMTP client, opportunistic STARTTLS, exponential-backoff retry, DSN bounces
IMAP4rev1 LOGIN/AUTHENTICATE, LIST, SELECT/EXAMINE, STATUS, CREATE/DELETE/RENAME, APPEND, FETCH (FLAGS, ENVELOPE, BODY[…], BODYSTRUCTURE, UID), STORE, SEARCH, COPY, EXPUNGE, CLOSE, IDLE, UID variants
POP3 RFC 1939: USER/PASS, STAT, LIST, UIDL, RETR, TOP, DELE, RSET, STLS
Auth & crypto argon2id password hashing, DKIM RSA-2048 sign/verify (relaxed/relaxed canonicalization), AES-256-GCM vault for DKIM private keys
TLS STARTTLS + implicit TLS on every protocol; auto-generated self-signed cert (or bring your own)
Web Admin panel (domains, mailboxes, aliases, queue, DKIM/DNS wizard, live log monitor) + minimal webmail (read, compose, send)
Storage SQLite (pure-Go, no CGO) for metadata + Maildir-style tree on disk for bodies

🛠 Tech Stack

Language Storage Web Protocols Email Auth Crypto Deploy

Layer Technology
Language Go 1.26 — standard library (net, crypto/tls, crypto/rand)
Storage SQLite (pure-Go modernc.org/sqlite, WAL) + Maildir on disk
Email auth DKIM RSA-2048 (RFC 6376), SPF (RFC 7208), DMARC (RFC 7489) — from scratch
Crypto argon2id (passwords), AES-256-GCM (DKIM key vault)
Protocols SMTP (RFC 5321) · IMAP4rev1 (RFC 3501) · POP3 (RFC 1939)
Web html/template + embed — no build step
Deploy Docker · systemd · single static binary

Only two direct module dependencies (golang.org/x/crypto for argon2, modernc.org/sqlite for pure-Go storage); every mail protocol and DKIM/SPF/ DMARC check is hand-written on the standard library.


Quickstart

Requires Go 1.26+. No CGO, no external services.

git clone https://github.com/vugarfamiloglu/corvus
cd corvus

# build the single binary
CGO_ENABLED=0 go build -o corvus ./cmd/corvus

# create the demo domain (corvus.local) + accounts and a welcome message
./corvus seed

# run all listeners
./corvus serve

Then open the web panel at http://localhost:8025 and sign in:

Account Password Role
postmaster@corvus.local Corvus2026! admin (full panel + webmail)
alice@corvus.local Corvus2026! user (webmail)
bob@corvus.local Corvus2026! user (webmail)

Default ports (development)

Ports default to unprivileged values so Corvus runs without root. Map them to the standard ports in production via the COR_* env vars.

Service Dev Standard
SMTP inbound 2525 25
Submission (STARTTLS) 5870 587
Submission (implicit TLS) 4650 465
IMAP (STARTTLS) 1430 143
IMAP (implicit TLS) 9930 993
POP3 (STLS) 1100 110
POP3 (implicit TLS) 9950 995
Web / webmail 8025 8025

Trying the protocols

Submit a message (authenticated) with swaks:

swaks --server localhost:5870 --auth LOGIN \
  --auth-user alice@corvus.local --auth-password 'Corvus2026!' \
  --from alice@corvus.local --to bob@corvus.local \
  --header "Subject: Hello from Corvus" --body "It works."

Read it over POP3:

openssl s_client -connect localhost:9950 -quiet
USER bob@corvus.local
PASS Corvus2026!
STAT
RETR 1
QUIT

Connect a real IMAP client (Thunderbird, K-9, Apple Mail): IMAP host localhost, port 9930, SSL/TLS, allow the self-signed certificate; SMTP host localhost, port 5870, STARTTLS. You can read, flag, search, move and send mail end-to-end.

The web log monitor (/logs) streams every SMTP/IMAP/POP3/delivery event live so you can watch the protocols at work.


Configuration

All settings come from COR_* environment variables (see .env.example):

COR_HOSTNAME=mail.example.com
COR_SMTP_ADDR=:25
COR_SUBMISSION_ADDR=:587
COR_IMAP_TLS_ADDR=:993
COR_TLS_CERT=/etc/corvus/fullchain.pem
COR_TLS_KEY=/etc/corvus/privkey.pem
COR_ADMIN_EMAIL=postmaster@example.com
COR_ADMIN_PASSWORD=change-me

CLI

corvus serve                      # run all listeners + delivery worker
corvus seed                       # create demo domain + accounts
corvus dkim-gen <domain>          # print the DKIM DNS record for a domain
corvus passwd <address> <pass>    # set a mailbox password
corvus version

Going to production (DNS)

Corvus's admin panel generates the exact records to publish. For example.com with mail host mail.example.com:

mail.example.com.         A     <server-ip>
example.com.              MX 10 mail.example.com.
example.com.              TXT   "v=spf1 mx -all"
cv1._domainkey.example.com. TXT "v=DKIM1; k=rsa; p=<generated>"
_dmarc.example.com.       TXT   "v=DMARC1; p=quarantine; rua=mailto:postmaster@example.com"

Plus a PTR / reverse-DNS record for the server IP (set at your VPS provider). Real-world deliverability additionally needs: a static IP with outbound port 25 open, a clean (non-blacklisted) IP, and IP warming — see the caveats below.

⚠️ Reality check. Most ISPs and cloud providers block outbound port 25, and a brand-new IP/domain will land in spam until it builds reputation. This repository is a from-scratch reference implementation for learning and portfolio use; running it as your primary production MX requires a dedicated static IP with PTR control and reputation warming.


Project layout

cmd/corvus/         entrypoint + subcommands (serve/seed/dkim-gen/passwd)
internal/
  config/           COR_* configuration
  logx/             structured logging + in-memory ring buffer (web log monitor)
  store/            SQLite metadata + Maildir storage + AES vault + DKIM keys
  auth/             argon2id hashing + SASL PLAIN/LOGIN
  mailmsg/          RFC 5322 header parsing + IMAP ENVELOPE + Received headers
  dkim/             DKIM RSA-SHA256 sign/verify (relaxed/relaxed)
  spf/              SPF policy evaluator
  dmarc/            DMARC alignment + policy
  spam/             signal-based spam scoring + greylisting
  tlsx/             TLS config + self-signed certificate generation
  smtp/             SMTP server (inbound MTA + submission)
  delivery/         outbound queue worker + SMTP client + DSN bounces
  imap/             IMAP4rev1 server
  pop3/             POP3 server
  web/              admin panel + webmail (html/template, embedded, no build)

Scope & roadmap

Implemented: the full vertical slice above. Some advanced features are deliberately out of scope for this reference build and noted here for honesty: Sieve filtering, ARC, MTA-STS/DANE enforcement, IMAP CONDSTORE/QRESYNC, JMAP, a trained Bayesian classifier, and HA/clustering. Spam scoring uses authentication signals + heuristics rather than a learned model.


Testing

go test ./...

Unit tests cover DKIM sign/verify round-trips, argon2 hashing, SASL decoding, the store lifecycle (domains, mailboxes, delivery, recipient resolution, greylisting), IMAP sequence-set/item parsing, SPF CIDR matching, message parsing and delivery backoff.


Screenshots

001 002 003

License

Apache License 2.0 — see LICENSE.

About

A self-hosted mail server written from scratch in Go — SMTP, IMAP, POP3, DKIM/SPF/DMARC, outbound queue, admin panel and webmail in a single binary.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors