# rizoma-mail

Standalone mail server extracted from the Rizoma WebPanel codebase.
One static binary: MX (`:25`), submission (`:587`), IMAP (`:993`),
background outbound delivery with DKIM signing, SQLite store, Maildir.

## Status: working v1 foundation (locally verified)

End-to-end smoke tested: domain/account CLI, authenticated submission,
MX receipt, IMAP auth/read, external enqueue → DKIM-signed delivery
attempt → deferral, full `go test ./...` green.

## Quick start

```bash
go build -o maild ./cmd/maild
export RIZOMA_MAIL_DB=/var/lib/rizoma-mail/mail.db
export RIZOMA_MAIL_MAILDIR=/var/mail/rizoma
export RIZOMA_MAIL_HOSTNAME=mx.example.com   # must match PTR + HELO
export RIZOMA_MAIL_TLS_CERT=/path/mx.crt
export RIZOMA_MAIL_TLS_KEY=/path/mx.key

./maild domain add example.com
./maild dkim show example.com    # paste this TXT into DNS first
RIZOMA_MAIL_ACCOUNT_PASS='...' ./maild account add user@example.com
./maild serve
./maild queue stats
```

## Ownership rule

The daemon runs as the `maild` user. Mailbox directories created by the
CLI as root are unreadable to it — after `account add`, or whenever mail
landed as another user:

```bash
chown -R maild:maild /var/mail/rizoma /var/lib/rizoma-mail
```

(Or run the CLI as the service user: `sudo -u maild maild account add …`.)

## Configuration (env)

| Var | Default | Notes |
|---|---|---|
| `RIZOMA_MAIL_BIND` | `0.0.0.0` | set to mesh IP for mesh-only operation |
| `RIZOMA_MAIL_MX_PORT` / `SMTP_PORT` / `IMAP_PORT` | `25/587/993` | |
| `RIZOMA_MAIL_DB` | `/var/lib/rizoma-mail/mail.db` | SQLite (WAL) |
| `RIZOMA_MAIL_MAILDIR` | `/var/mail/rizoma` | |
| `RIZOMA_MAIL_HOSTNAME` | `mx.local` | **must be set**: EHLO + cert CN + PTR target |
| `RIZOMA_MAIL_TLS_CERT/KEY` | empty (plaintext + warn) | required for AUTH (no plaintext auth) |
| `RIZOMA_MAIL_MX_REQUIRE_TLS` | `false` | opportunistic by default |
| `RIZOMA_MAIL_DKIM_SELECTOR` | `mail` | used when auto-creating keys |
| `RIZOMA_MAIL_SMARTHOST[_USER/_PASS]` | empty (direct MX) | relay when port-25 egress is blocked |
| `RIZOMA_MAIL_DNS_*` | system resolver | split-horizon mesh/public DNS |

## DNS needed per domain

```
@   MX   10 <hostname>
@   TXT  "v=spf1 mx -all"
<sel>._domainkey  TXT  (from: maild dkim show <domain>)
_dmarc  TXT  "v=DMARC1; p=quarantine; rua=mailto:postmaster@<domain>"
PTR <ip> -> <hostname>   (via VPS provider)
```

## Gaps

See [docs/GAPS.md](docs/GAPS.md) — what v1 lacks vs a full public mail
server (spam filtering, sieve, DMARC enforcement, etc.).
