Documentation
Getting started: Inbound mail
This walkthrough shows how to start Everlock with inbound SMTP enabled, add a
simple rules.toml, send a hello-world inbound mail, and verify that the
message landed in the versioned mail store.
What “vhost” means for mail
Mail does not use HTTP-style vhosts.
The equivalent pieces are:
- the recipient domain in the mail address, such as
alice@example.com - the MX record for that domain, which points at the machine running Everlock
So when you want Everlock to receive mail for example.com, you point the MX
record for example.com at your Everlock host.
1. Start Everlock with SMTP
For the first pass, use explicit CLI flags:
everlock serve \
--frontend-ssh \
--backend-admin-ssh \
--frontend-smtp \
--frontend-smtp-listen 0.0.0.0:2525 \
--backend-mail-smtp \
--admin-user admin \
--admin-password change-me
Expected startup shape:
[INFO everlock] starting backend-mail-smtp
[INFO everlock_backend_mail_smtp::module] backend-mail-smtp registered (store: everlock-mail, delivery path: domain/mailbox/YYYY/MM/DD/*.eml)
[INFO everlock] starting frontend-smtp
[INFO everlock_frontend_smtp::module] frontend-smtp: using backend-mail-smtp
[INFO everlock_frontend_smtp::module] frontend-smtp: binding listener on 0.0.0.0:2525
[INFO everlock_frontend_smtp::module] SMTP server listening on 0.0.0.0:2525
2. Optionally add rules.toml
This step is optional. SMTP can start without a rules.toml, and in that case
Everlock stores mail by default into the recipient mailbox under the inbox
folder.
When you define rules, Everlock evaluates them by ascending priority.
Lower numbers run first. If priority is omitted, it defaults to 10.
Recipient acceptance also has a bootstrap behavior:
- if no local mail domains are configured yet, inbound SMTP accepts syntactically valid recipients
- once you create the first mail domain with
/mail domains create <domain>, inbound accepts only configured local domains
This bootstrap mode is a setup convenience, not a general outbound relay.
Add a rules file when you want behavior other than the default, such as:
- rejecting specific messages
- forwarding messages
- storing into a different mailbox
- storing into a different folder
Create data/everlock-mail/rules.toml:
[[rule]]
id = "rule-local-example"
name = "store all example.com mail"
priority = 10
receiver = "*@example.com"
type = "store"
folder = "inbox"
Commit it into the versioned store:
git -C ./data/everlock-mail add rules.toml
git -C ./data/everlock-mail commit -m "add initial mail rules"
Expected result:
[main abc1234] add initial mail rules
1 file changed, 7 insertions(+)
create mode 100644 rules.toml
If you skip this step entirely, the current backend default is:
- no matching rule
- store the message in the recipient mailbox
- use
inboxas the folder
3. Point DNS at the Everlock host
For real inbound delivery, publish:
AorAAAAformail.example.comMXforexample.compointing tomail.example.com
Example DNS intent:
mail.example.com. A 203.0.113.24
example.com. MX 10 mail.example.com.
For a local test, you can skip public DNS and just connect directly to the
listener on 127.0.0.1:2525.
4. Send a hello-world mail from the CLI
The easiest CLI test is swaks:
swaks \
--server 127.0.0.1:2525 \
--from sender@example.net \
--to alice@example.com \
--header "Subject: Hello world" \
--body "Hello from Everlock SMTP"
Expected output shape:
=== Trying 127.0.0.1:2525...
<~ 220
~> EHLO
<~ 250
~> MAIL FROM:<sender@example.net>
<~ 250
~> RCPT TO:<alice@example.com>
<~ 250
~> DATA
<~ 354
~> .
<~ 250 2.0.0 Accepted
If you do not have swaks, you have two simple alternatives:
Plain SMTP without TLS:
printf 'EHLO localhost\r\nMAIL FROM:<sender@example.net>\r\nRCPT TO:<alice@example.com>\r\nDATA\r\nSubject: Hello world\r\nFrom: sender@example.net\r\nTo: alice@example.com\r\n\r\nHello from Everlock SMTP\r\n.\r\nQUIT\r\n' \
| nc 127.0.0.1 2525
SMTP with STARTTLS:
openssl s_client -starttls smtp -crlf -connect 127.0.0.1:2525 <<'EOF'
EHLO localhost
MAIL FROM:<sender@example.net>
RCPT TO:<alice@example.com>
DATA
Subject: Hello world
From: sender@example.net
To: alice@example.com
Hello from Everlock SMTP
.
QUIT
EOF
Expected final acceptance line:
250 2.0.0 Accepted
Do not use plain openssl s_client -connect ...:25 for SMTP. That attempts
implicit TLS immediately. Everlock speaks SMTP first and upgrades with
STARTTLS on the same listener.
5. Send a test mail from a desktop mail client
Everlock supports inbound SMTP and a separate authenticated submission listener. For local testing against the inbound listener, use:
- server:
127.0.0.1 - port:
2525 - connection security:
NoneorSTARTTLS - authentication:
None - from address:
sender@example.net - recipient:
alice@example.com
That is enough for a hello-world test from a real mail client.
6. Check the stored message
Inspect the latest mail-store commit:
git -C ./data/everlock-mail log --stat -1
Expected shape:
commit <sha>
Author: ...
receive mail for alice@example.com
example.com/alice/2026/05/21/<timestamp>-<id>.eml | ...
example.com/alice/2026/05/21/<timestamp>-<id>.toml | ...
List the stored paths:
git -C ./data/everlock-mail ls-tree -r --name-only HEAD | grep 'example.com/alice/'
Expected shape:
example.com/alice/2026/05/21/20260521T101530Z-7f3c2b1a.eml
example.com/alice/2026/05/21/20260521T101530Z-7f3c2b1a.toml
Inspect the sidecar:
git -C ./data/everlock-mail show HEAD:example.com/alice/2026/05/21/<timestamp>-<id>.toml
Expected fields include:
recipient_address = "alice@example.com"
folder = "inbox"
subject = "Hello world"
forwarded = false
source_ip = "127.0.0.1"
STARTTLS note
frontend-smtp manages its own certificate material under
config/frontend-smtp/fullchain.pem and config/frontend-smtp/privkey.pem.
If no certificate exists yet, it generates a self-signed STARTTLS certificate
automatically.
For local testing, that self-signed certificate includes loopback names such as
localhost, 127.0.0.1, and ::1, plus the configured SMTP listen host when
it is a specific hostname or IP address. For public SMTP hostnames, replace the
generated certificate files with operator-provided ones for the hostname your
clients actually connect to.
When certificate material exists, EHLO advertises STARTTLS automatically.