Fixed logging, clippy suggestions and organized configuration directives.
This commit is contained in:
53
resources/config/common.toml
Normal file
53
resources/config/common.toml
Normal file
@@ -0,0 +1,53 @@
|
||||
[server]
|
||||
hostname = "__HOST__"
|
||||
max-connections = 8192
|
||||
|
||||
[server.run-as]
|
||||
user = "__RUN_AS_USER__"
|
||||
group = "__RUN_AS_GROUP__"
|
||||
|
||||
[server.tls]
|
||||
enable = true
|
||||
implicit = false
|
||||
timeout = "1m"
|
||||
certificate = "default"
|
||||
#sni = [{subject = "", certificate = ""}]
|
||||
#protocols = ["TLSv1.2", TLSv1.3"]
|
||||
#ciphers = []
|
||||
ignore-client-order = true
|
||||
|
||||
[server.socket]
|
||||
reuse-addr = true
|
||||
#reuse-port = true
|
||||
backlog = 1024
|
||||
#ttl = 3600
|
||||
#send-buffer-size = 65535
|
||||
#recv-buffer-size = 65535
|
||||
#linger = 1
|
||||
#tos = 1
|
||||
|
||||
[global]
|
||||
shared-map = {shard = 32, capacity = 10}
|
||||
#thread-pool = 8
|
||||
|
||||
#[global.tracing]
|
||||
#method = "stdout"
|
||||
#level = "trace"
|
||||
|
||||
#[global.tracing]
|
||||
#method = "open-telemetry"
|
||||
#transport = "http"
|
||||
#endpoint = "https://127.0.0.1/otel"
|
||||
#headers = ["Authorization: <place_auth_here>"]
|
||||
#level = "debug"
|
||||
|
||||
[global.tracing]
|
||||
method = "log"
|
||||
path = "__PATH__/logs"
|
||||
prefix = "smtp.log"
|
||||
rotate = "daily"
|
||||
level = "info"
|
||||
|
||||
[certificate."default"]
|
||||
cert = "file://__PATH__/etc/certs/tls.crt"
|
||||
private-key = "file://__PATH__/etc/private/tls.key"
|
||||
139
resources/config/directory.toml
Normal file
139
resources/config/directory.toml
Normal file
@@ -0,0 +1,139 @@
|
||||
[directory."sql"]
|
||||
type = "sql"
|
||||
address = "sqlite::memory:"
|
||||
|
||||
[directory."sql".options]
|
||||
catch-all = true
|
||||
subaddressing = true
|
||||
|
||||
[directory."sql".pool]
|
||||
max-connections = 10
|
||||
|
||||
[directory."sql".query]
|
||||
name = "SELECT name, type, secret, description, quota FROM accounts WHERE name = ? AND active = true"
|
||||
members = "SELECT member_of FROM group_members WHERE name = ?"
|
||||
recipients = "SELECT name FROM emails WHERE address = ?"
|
||||
emails = "SELECT address FROM emails WHERE name = ? AND type != 'list' ORDER BY type DESC, address ASC"
|
||||
verify = "SELECT address FROM emails WHERE address LIKE '%' || ? || '%' AND type = 'primary' ORDER BY address LIMIT 5"
|
||||
expand = "SELECT p.address FROM emails AS p JOIN emails AS l ON p.name = l.name WHERE p.type = 'primary' AND l.address = ? AND l.type = 'list' ORDER BY p.address LIMIT 50"
|
||||
domains = "SELECT 1 FROM emails WHERE address LIKE '%@' || ? LIMIT 1"
|
||||
|
||||
[directory."sql".columns]
|
||||
name = "name"
|
||||
description = "description"
|
||||
secret = "secret"
|
||||
email = "address"
|
||||
quota = "quota"
|
||||
type = "type"
|
||||
|
||||
[directory."ldap"]
|
||||
type = "ldap"
|
||||
address = "ldap://localhost:3893"
|
||||
base-dn = "dc=example,dc=org"
|
||||
|
||||
[directory."ldap".bind]
|
||||
dn = "cn=serviceuser,ou=svcaccts,dc=example,dc=org"
|
||||
secret = "mysecret"
|
||||
|
||||
[directory."ldap".options]
|
||||
catch-all = true
|
||||
subaddressing = true
|
||||
|
||||
[directory."ldap".filter]
|
||||
name = "(&(|(objectClass=posixAccount)(objectClass=posixGroup))(uid=?))"
|
||||
email = "(&(|(objectClass=posixAccount)(objectClass=posixGroup))(|(mail=?)(mailAlias=?)))"
|
||||
verify = "(&(|(objectClass=posixAccount)(objectClass=posixGroup))(|(mail=*?*)(mailAlias=*?*)))"
|
||||
expand = "(&(|(objectClass=posixAccount)(objectClass=posixGroup))(sn=?))"
|
||||
domains = "(&(|(objectClass=posixAccount)(objectClass=posixGroup))(|(mail=*@?)(mailAlias=*@?)))"
|
||||
|
||||
[directory."ldap".object-classes]
|
||||
user = "posixAccount"
|
||||
group = "posixGroup"
|
||||
|
||||
[directory."ldap".attributes]
|
||||
name = "uid"
|
||||
description = ["principalName", "description"]
|
||||
secret = "userPassword"
|
||||
groups = ["memberOf", "otherGroups"]
|
||||
email = "mail"
|
||||
email-alias = "mailAlias"
|
||||
quota = "diskQuota"
|
||||
|
||||
[directory."imap"]
|
||||
type = "imap"
|
||||
address = "127.0.0.1"
|
||||
port = 9198
|
||||
|
||||
[directory."imap".pool]
|
||||
max-connections = 5
|
||||
|
||||
[directory."imap".tls]
|
||||
implicit = true
|
||||
allow-invalid-certs = true
|
||||
|
||||
[directory."imap".lookup]
|
||||
domains = ["example.org"]
|
||||
|
||||
[directory."smtp"]
|
||||
type = "lmtp"
|
||||
address = "127.0.0.1"
|
||||
port = 9199
|
||||
|
||||
[directory."smtp".limits]
|
||||
auth-errors = 3
|
||||
rcpt = 5
|
||||
|
||||
[directory."smtp".pool]
|
||||
max-connections = 5
|
||||
|
||||
[directory."smtp".tls]
|
||||
implicit = true
|
||||
allow-invalid-certs = true
|
||||
|
||||
[directory."smtp".cache]
|
||||
entries = 500
|
||||
ttl = {positive = '10s', negative = '5s'}
|
||||
|
||||
[directory."smtp".lookup]
|
||||
domains = ["example.org"]
|
||||
|
||||
[directory."memory"]
|
||||
type = "memory"
|
||||
|
||||
[directory."memory".options]
|
||||
catch-all = true
|
||||
subaddressing = true
|
||||
|
||||
[[directory."memory".users]]
|
||||
name = "admin"
|
||||
description = "Superuser"
|
||||
secret = "changeme"
|
||||
email = ["admin@example.org"]
|
||||
member-of = ["superusers"]
|
||||
|
||||
[[directory."memory".users]]
|
||||
name = "jane"
|
||||
description = "Jane Doe"
|
||||
secret = "abcde"
|
||||
email = ["jane@example.org", "jane.doe@example.org"]
|
||||
email-list = ["info@example.org"]
|
||||
member-of = ["sales", "support"]
|
||||
|
||||
[[directory."memory".users]]
|
||||
name = "bill"
|
||||
description = "Bill Foobar"
|
||||
secret = "$2y$05$bvIG6Nmid91Mu9RcmmWZfO5HJIMCT8riNW0hEp8f6/FuA2/mHZFpe"
|
||||
quota = 500000
|
||||
email = "bill@example.org"
|
||||
email-list = ["info@example.org"]
|
||||
|
||||
[[directory."memory".groups]]
|
||||
name = "sales"
|
||||
description = "Sales Team"
|
||||
|
||||
[[directory."memory".groups]]
|
||||
name = "support"
|
||||
description = "Support Team"
|
||||
|
||||
[directory."memory".lookup]
|
||||
domains = ["example.org"]
|
||||
33
resources/config/imap.toml
Normal file
33
resources/config/imap.toml
Normal file
@@ -0,0 +1,33 @@
|
||||
[server.listener."imap"]
|
||||
bind = ["0.0.0.0:143"]
|
||||
protocol = "imap"
|
||||
|
||||
[server.listener."imaptls"]
|
||||
bind = ["0.0.0.0:9993"]
|
||||
protocol = "imap"
|
||||
tls.implicit = true
|
||||
|
||||
[server.listener."sieve"]
|
||||
bind = ["0.0.0.0:4190"]
|
||||
protocol = "managesieve"
|
||||
tls.implicit = true
|
||||
|
||||
[imap.request]
|
||||
max-size = 52428800
|
||||
|
||||
[imap.auth]
|
||||
max-failures = 3
|
||||
allow-plain-text = false
|
||||
|
||||
[imap.folders.name]
|
||||
shared = "Shared Folders"
|
||||
all = "All Mail"
|
||||
|
||||
[imap.timeout]
|
||||
authenticated = "30m"
|
||||
anonymous = "1m"
|
||||
idle = "30m"
|
||||
|
||||
[imap.rate-limit]
|
||||
requests = "2000/1m"
|
||||
concurrent = 4
|
||||
154
resources/config/jmap.toml
Normal file
154
resources/config/jmap.toml
Normal file
@@ -0,0 +1,154 @@
|
||||
[server.listener."jmap"]
|
||||
bind = ["0.0.0.0:__BIND_PORT__"]
|
||||
url = "https://127.0.0.1:__BIND_PORT__"
|
||||
protocol = "jmap"
|
||||
|
||||
[store.db]
|
||||
path = "__PATH__/db"
|
||||
|
||||
[store.blob]
|
||||
type = "local"
|
||||
|
||||
[store.blob.local]
|
||||
path = "__PATH__/blobs"
|
||||
|
||||
[store.blob.s3]
|
||||
bucket = "stalwart"
|
||||
region = "eu-central-1"
|
||||
access-key = "minioadmin"
|
||||
secret-key = "minioadmin"
|
||||
#endpoint = ""
|
||||
#security-token = ""
|
||||
#profile = ""
|
||||
timeout = "30s"
|
||||
|
||||
[jmap]
|
||||
directory = "sql"
|
||||
|
||||
[jmap.session.cache]
|
||||
ttl = "1h"
|
||||
size = 100
|
||||
|
||||
[jmap.protocol.get]
|
||||
max-objects = 500
|
||||
|
||||
[jmap.protocol.set]
|
||||
max-objects = 500
|
||||
|
||||
[jmap.protocol.request]
|
||||
max-concurrent = 4
|
||||
max-size = 10000000
|
||||
max-calls = 16
|
||||
|
||||
[jmap.protocol.query]
|
||||
max-results = 5000
|
||||
|
||||
[jmap.protocol.upload]
|
||||
max-size = 50000000
|
||||
max-concurrent = 4
|
||||
ttl = "1h"
|
||||
|
||||
[jmap.protocol.upload.quota]
|
||||
files = 1000
|
||||
size = 50000000
|
||||
|
||||
[jmap.protocol.changes]
|
||||
max-results = 5000
|
||||
|
||||
[jmap.rate-limit]
|
||||
account = "1000/1m"
|
||||
authentication = "10/1m"
|
||||
anonymous = "100/1m"
|
||||
|
||||
[jmap.rate-limit.cache]
|
||||
size = 1024
|
||||
|
||||
[jmap.mailbox]
|
||||
max-depth = 10
|
||||
max-name-length = 255
|
||||
|
||||
[jmap.email]
|
||||
max-attachment-size = 50000000
|
||||
max-size = 75000000
|
||||
|
||||
[jmap.email.parse]
|
||||
max-items = 10
|
||||
|
||||
[jmap.sieve]
|
||||
disable-capabilities = []
|
||||
notification-uris = ["mailto"]
|
||||
protected-headers = ["Original-Subject", "Original-From", "Received", "Auto-Submitted"]
|
||||
|
||||
[jmap.sieve.limits]
|
||||
name-length = 512
|
||||
max-scripts = 256
|
||||
script-size = 102400
|
||||
string-length = 4096
|
||||
variable-name-length = 32
|
||||
variable-size = 4096
|
||||
nested-blocks = 15
|
||||
nested-tests = 15
|
||||
nested-foreverypart = 3
|
||||
match-variables = 30
|
||||
local-variables = 128
|
||||
header-size = 1024
|
||||
includes = 3
|
||||
nested-includes = 3
|
||||
cpu = 5000
|
||||
redirects = 1
|
||||
received-headers = 10
|
||||
outgoing-messages = 3
|
||||
|
||||
[jmap.sieve.vacation]
|
||||
default-subject = "Automated reply"
|
||||
subject-prefix = "Auto: "
|
||||
|
||||
[jmap.sieve.default-expiry]
|
||||
vacation = "30d"
|
||||
duplicate = "7d"
|
||||
|
||||
[jmap.event-source]
|
||||
throttle = "1s"
|
||||
|
||||
[jmap.web-sockets]
|
||||
throttle = "1s"
|
||||
timeout = "10m"
|
||||
heartbeat = "1m"
|
||||
|
||||
[jmap.push]
|
||||
max-total = 100
|
||||
throttle = "1ms"
|
||||
|
||||
[jmap.push.attempts]
|
||||
interval = "1m"
|
||||
max = 3
|
||||
|
||||
[jmap.push.retry]
|
||||
interval = "1s"
|
||||
|
||||
[jmap.push.timeout]
|
||||
request = "10s"
|
||||
verify = "1s"
|
||||
|
||||
[jmap.fts]
|
||||
default-language = "en"
|
||||
|
||||
[oauth]
|
||||
key = "__OAUTH_KEY__"
|
||||
|
||||
[oauth.auth]
|
||||
max-attempts = 3
|
||||
|
||||
[oauth.expiry]
|
||||
user-code = "30m"
|
||||
token = "1h"
|
||||
refresh-token = "30d"
|
||||
refresh-token-renew = "4d"
|
||||
|
||||
[oauth.cache]
|
||||
size = 128
|
||||
|
||||
[jmap.purge.schedule]
|
||||
db = "0 3 *"
|
||||
blobs = "30 3 *"
|
||||
sessions = "15 * *"
|
||||
@@ -1,72 +1,21 @@
|
||||
[server]
|
||||
hostname = "__HOST__"
|
||||
#greeting = "Stalwart SMTP at your service"
|
||||
protocol = "smtp"
|
||||
|
||||
[server.run-as]
|
||||
user = "stalwart-smtp"
|
||||
group = "stalwart-smtp"
|
||||
|
||||
[server.listener."smtp"]
|
||||
bind = ["0.0.0.0:25"]
|
||||
max-connections = 8192
|
||||
greeting = "Stalwart SMTP at your service"
|
||||
protocol = "smtp"
|
||||
|
||||
[server.listener."submission"]
|
||||
bind = ["0.0.0.0:587"]
|
||||
max-connections = 8192
|
||||
protocol = "smtp"
|
||||
|
||||
[server.listener."submissions"]
|
||||
bind = ["0.0.0.0:465"]
|
||||
max-connections = 8192
|
||||
protocol = "smtp"
|
||||
tls.implicit = true
|
||||
|
||||
|
||||
[server.listener."management"]
|
||||
bind = ["127.0.0.1:8686"]
|
||||
protocol = "http"
|
||||
|
||||
[server.tls]
|
||||
enable = true
|
||||
implicit = false
|
||||
timeout = "1m"
|
||||
certificate = "default"
|
||||
#sni = [{subject = "", certificate = ""}]
|
||||
#protocols = ["TLSv1.2", TLSv1.3"]
|
||||
#ciphers = []
|
||||
ignore-client-order = true
|
||||
|
||||
[server.socket]
|
||||
reuse-addr = true
|
||||
#reuse-port = true
|
||||
backlog = 1024
|
||||
#ttl = 3600
|
||||
#send-buffer-size = 65535
|
||||
#recv-buffer-size = 65535
|
||||
#linger = 1
|
||||
#tos = 1
|
||||
|
||||
[global]
|
||||
shared-map = {shard = 32, capacity = 10}
|
||||
#thread-pool = 8
|
||||
|
||||
#[global.tracing]
|
||||
#method = "stdout"
|
||||
#level = "trace"
|
||||
|
||||
#[global.tracing]
|
||||
#method = "open-telemetry"
|
||||
#transport = "http"
|
||||
#endpoint = "https://127.0.0.1/otel"
|
||||
#headers = ["Authorization: <place_auth_here>"]
|
||||
#level = "debug"
|
||||
|
||||
[global.tracing]
|
||||
method = "log"
|
||||
path = "/usr/local/stalwart-smtp/logs"
|
||||
prefix = "smtp.log"
|
||||
rotate = "daily"
|
||||
level = "info"
|
||||
|
||||
[session]
|
||||
timeout = "5m"
|
||||
transfer-limit = 262144000 # 250 MB
|
||||
@@ -88,6 +37,10 @@ requiretls = true
|
||||
no-soliciting = ""
|
||||
dsn = [ { if = "authenticated-as", ne = "", then = true},
|
||||
{ else = false } ]
|
||||
expn = [ { if = "authenticated-as", ne = "", then = true},
|
||||
{ else = false } ]
|
||||
vrfy = [ { if = "authenticated-as", ne = "", then = true},
|
||||
{ else = false } ]
|
||||
future-release = [ { if = "authenticated-as", ne = "", then = "7d"},
|
||||
{ else = false } ]
|
||||
deliver-by = [ { if = "authenticated-as", ne = "", then = "15d"},
|
||||
@@ -98,7 +51,7 @@ mt-priority = [ { if = "authenticated-as", ne = "", then = "mixer"},
|
||||
[session.auth]
|
||||
mechanisms = [ { if = "listener", ne = "smtp", then = ["plain", "login"]},
|
||||
{ else = [] } ]
|
||||
directory = [ { if = "listener", ne = "smtp", then = "remote/imap" },
|
||||
directory = [ { if = "listener", ne = "smtp", then = "local" },
|
||||
{ else = false } ]
|
||||
require = [ { if = "listener", ne = "smtp", then = true},
|
||||
{ else = false } ]
|
||||
@@ -115,9 +68,8 @@ wait = "5s"
|
||||
relay = [ { if = "authenticated-as", ne = "", then = true },
|
||||
{ else = false } ]
|
||||
max-recipients = 25
|
||||
directory = [ { if = "authenticated-as", ne = "", then = "remote/lmtp" },
|
||||
directory = [ { if = "authenticated-as", ne = "", then = "local" },
|
||||
{ else = false } ]
|
||||
domains = "list/domains"
|
||||
|
||||
[session.rcpt.cache]
|
||||
entries = 1000
|
||||
@@ -166,6 +118,7 @@ rate = "25/1h"
|
||||
[auth.dnsbl]
|
||||
verify = [ { if = "listener", eq = "smtp", then = ["ip", "iprev", "ehlo", "return-path", "from"] },
|
||||
{ else = [] } ]
|
||||
|
||||
[auth.dnsbl.lookup]
|
||||
ip = ["zen.spamhaus.org", "bl.spamcop.net", "b.barracudacentral.org"]
|
||||
domain = ["dbl.spamhaus.org"]
|
||||
@@ -194,7 +147,7 @@ verify = [ { if = "listener", eq = "smtp", then = "relaxed" },
|
||||
{ else = "disable" } ]
|
||||
|
||||
[queue]
|
||||
path = "/usr/local/stalwart-smtp/queue"
|
||||
path = "__PATH__/queue"
|
||||
hash = 64
|
||||
|
||||
[queue.schedule]
|
||||
@@ -204,7 +157,7 @@ expire = "5d"
|
||||
|
||||
[queue.outbound]
|
||||
#hostname = "__HOST__"
|
||||
next-hop = [ { if = "rcpt-domain", in-list = "list/domains", then = "lmtp" },
|
||||
next-hop = [ { if = "rcpt-domain", in-list = "local/domains", then = "lmtp" },
|
||||
{ else = false } ]
|
||||
ip-strategy = "ipv4-then-ipv6"
|
||||
|
||||
@@ -260,14 +213,14 @@ tlsa = 1024
|
||||
mta-sts = 1024
|
||||
|
||||
[report]
|
||||
path = "/usr/local/stalwart-smtp/reports"
|
||||
path = "__PATH__/reports"
|
||||
hash = 64
|
||||
#submitter = "mx.domain.org"
|
||||
|
||||
[report.analysis]
|
||||
addresses = ["dmarc@*", "abuse@*"]
|
||||
forward = true
|
||||
#store = "/usr/local/stalwart-smtp/incoming"
|
||||
#store = "__PATH__/incoming"
|
||||
|
||||
[report.dsn]
|
||||
from-name = "Mail Delivery Subsystem"
|
||||
@@ -314,8 +267,8 @@ max-size = 26214400 # 25 mb
|
||||
sign = ["rsa"]
|
||||
|
||||
[signature."rsa"]
|
||||
#public-key = "file:///usr/local/stalwart-smtp/etc/certs/dkim.crt"
|
||||
private-key = "file:///usr/local/stalwart-smtp/etc/private/dkim.key"
|
||||
#public-key = "file://__PATH__/etc/certs/dkim.crt"
|
||||
private-key = "file://__PATH__/etc/private/dkim.key"
|
||||
domain = "__DOMAIN__"
|
||||
selector = "stalwart_smtp"
|
||||
headers = ["From", "To", "Date", "Subject", "Message-ID"]
|
||||
@@ -334,11 +287,6 @@ port = __LMTP_PORT__
|
||||
protocol = "lmtp"
|
||||
concurrency = 10
|
||||
timeout = "1m"
|
||||
lookup = true
|
||||
|
||||
[remote."lmtp".cache]
|
||||
entries = 1000
|
||||
ttl = {positive = "1d", negative = "1h"}
|
||||
|
||||
[remote."lmtp".tls]
|
||||
implicit = false
|
||||
@@ -348,28 +296,8 @@ allow-invalid-certs = true
|
||||
#username = ""
|
||||
#secret = ""
|
||||
|
||||
[remote."lmtp".limits]
|
||||
errors = 3
|
||||
requests = 50
|
||||
|
||||
[remote."imap"]
|
||||
address = "localhost"
|
||||
port = 143
|
||||
protocol = "imap"
|
||||
concurrency = 10
|
||||
timeout = "1m"
|
||||
lookup = true
|
||||
|
||||
[remote."imap".cache]
|
||||
entries = 1000
|
||||
ttl = {positive = "1d", negative = "1h"}
|
||||
|
||||
[remote."imap".tls]
|
||||
implicit = false
|
||||
allow-invalid-certs = true
|
||||
|
||||
[database."sql"]
|
||||
#address = "sqlite:///usr/local/stalwart-smtp/etc/sqlite.db?mode=rwc"
|
||||
#address = "sqlite://__PATH__/etc/sqlite.db?mode=rwc"
|
||||
address = "postgres://postgres:password@localhost/test"
|
||||
max-connections = 10
|
||||
min-connections = 0
|
||||
@@ -409,14 +337,14 @@ duplicate-expiry = "7d"
|
||||
connect = '''
|
||||
require ["variables", "extlists", "reject"];
|
||||
|
||||
if string :list "${env.remote_ip}" "list/blocked-ips" {
|
||||
if string :list "${env.remote_ip}" "local/blocked-ips" {
|
||||
reject "Your IP '${env.remote_ip}' is not welcomed here.";
|
||||
}
|
||||
'''
|
||||
ehlo = '''
|
||||
require ["variables", "extlists", "reject"];
|
||||
|
||||
if string :list "${env.helo_domain}" "list/blocked-domains" {
|
||||
if string :list "${env.helo_domain}" "local/blocked-domains" {
|
||||
reject "551 5.1.1 Your domain '${env.helo_domain}' has been blacklisted.";
|
||||
}
|
||||
'''
|
||||
@@ -457,13 +385,3 @@ data = '''
|
||||
[management]
|
||||
directory = "local"
|
||||
|
||||
[list]
|
||||
domains = ["__DOMAIN__"]
|
||||
admin = ["admin:__ADMIN_PASS__"]
|
||||
#blocked-ips = ["10.0.0.1"]
|
||||
#blocked-domains = ["mail.spammer.com"]
|
||||
#users = "file:///usr/local/stalwart-smtp/etc/users.txt"
|
||||
|
||||
[certificate."default"]
|
||||
cert = "file:///usr/local/stalwart-smtp/etc/certs/tls.crt"
|
||||
private-key = "file:///usr/local/stalwart-smtp/etc/private/tls.key"
|
||||
Reference in New Issue
Block a user