Add optional inbound relay (backup-MX) behind INBOUND_RELAY_ENABLE.
test / test (push) Waiting to run
test / test (push) Waiting to run
Port 25 accepts only configured domains and listed recipients, then forwards to an upstream; the outbound path is unchanged when the flag is off. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -15,6 +15,11 @@ var documentedPublic = []string{
|
||||
"PANEL_SESSION_IDLE_DAYS",
|
||||
"SELFPOST_DNS_RESOLVERS",
|
||||
"TRUSTED_PROXY_CIDR",
|
||||
"INBOUND_RELAY_ENABLE",
|
||||
"INBOUND_ANTISPAM_MILTER",
|
||||
"INBOUND_ANTISPAM_MILTER_ACTION",
|
||||
"INBOUND_RATE_LIMIT_MESSAGES_PER_IP",
|
||||
"INBOUND_MESSAGE_SIZE_LIMIT",
|
||||
}
|
||||
|
||||
// documentedInternal matches architecture.md § Configuration "Internal env vars".
|
||||
@@ -34,6 +39,10 @@ var documentedInternal = []string{
|
||||
"POSTFIX_DIR",
|
||||
"POSTFIX_SENDER_LOGIN_MAPS",
|
||||
"POSTFIX_QUEUE_DIR",
|
||||
"POSTFIX_RELAY_DOMAINS",
|
||||
"POSTFIX_TRANSPORT_MAPS",
|
||||
"POSTFIX_RELAY_RECIPIENTS",
|
||||
"POSTFIX_TLS_POLICY_MAPS",
|
||||
"SELFPOST_DEPLOY_ROOT",
|
||||
"MILTER_CONNECT_TIMEOUT",
|
||||
"MILTER_COMMAND_TIMEOUT",
|
||||
@@ -73,6 +82,7 @@ var loadConfigKeys = []string{
|
||||
"SASL_REALM",
|
||||
"POSTFIX_DIR",
|
||||
"SELFPOST_DEPLOY_ROOT",
|
||||
"INBOUND_RELAY_ENABLE",
|
||||
}
|
||||
|
||||
// buildScriptKeys is every ${VAR:-…} / os.Getenv used in build/*.sh and entrypoint.sh
|
||||
@@ -90,6 +100,15 @@ var buildScriptKeys = []string{
|
||||
"POSTFIX_QUEUE_DIR",
|
||||
"SASL_DB_PATH",
|
||||
"SUBMISSION_ENABLE",
|
||||
"INBOUND_RELAY_ENABLE",
|
||||
"INBOUND_ANTISPAM_MILTER",
|
||||
"INBOUND_ANTISPAM_MILTER_ACTION",
|
||||
"INBOUND_RATE_LIMIT_MESSAGES_PER_IP",
|
||||
"INBOUND_MESSAGE_SIZE_LIMIT",
|
||||
"POSTFIX_RELAY_DOMAINS",
|
||||
"POSTFIX_TRANSPORT_MAPS",
|
||||
"POSTFIX_RELAY_RECIPIENTS",
|
||||
"POSTFIX_TLS_POLICY_MAPS",
|
||||
"MILTER_CONNECT_TIMEOUT",
|
||||
"MILTER_COMMAND_TIMEOUT",
|
||||
"MILTER_CONTENT_TIMEOUT",
|
||||
|
||||
+16
-6
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/mixeme/selfpost/internal/app"
|
||||
"github.com/mixeme/selfpost/internal/buildinfo"
|
||||
"github.com/mixeme/selfpost/internal/domain"
|
||||
"github.com/mixeme/selfpost/internal/inbound"
|
||||
"github.com/mixeme/selfpost/internal/postfix"
|
||||
"github.com/mixeme/selfpost/internal/store"
|
||||
"github.com/mixeme/selfpost/internal/web"
|
||||
@@ -19,10 +20,12 @@ import (
|
||||
// mailStack is the panel's domain and application services plus the on-disk
|
||||
// mail-path adapters they write through.
|
||||
type mailStack struct {
|
||||
Domains *domain.Service
|
||||
Apps *app.Service
|
||||
pf *postfix.Postfix
|
||||
odk *domain.OpenDKIM
|
||||
Domains *domain.Service
|
||||
Apps *app.Service
|
||||
Inbound *inbound.Service
|
||||
pf *postfix.Postfix
|
||||
odk *domain.OpenDKIM
|
||||
inboundEnabled bool
|
||||
}
|
||||
|
||||
func newMailStack(cfg config, st *store.Store) *mailStack {
|
||||
@@ -30,7 +33,8 @@ func newMailStack(cfg config, st *store.Store) *mailStack {
|
||||
odk := domain.NewOpenDKIM(cfg.opendkimDir)
|
||||
apps := app.NewService(st, app.NewSASLDB(cfg.saslDBPath, cfg.saslRealm), pf)
|
||||
domains := domain.NewService(st, odk, apps, cfg.dkimSelectorDef)
|
||||
return &mailStack{Domains: domains, Apps: apps, pf: pf, odk: odk}
|
||||
inb := inbound.NewService(st, pf)
|
||||
return &mailStack{Domains: domains, Apps: apps, Inbound: inb, pf: pf, odk: odk, inboundEnabled: cfg.inboundEnabled}
|
||||
}
|
||||
|
||||
// Resync rebuilds OpenDKIM's tables and Postfix's sender map from SQLite and
|
||||
@@ -42,6 +46,11 @@ func (m *mailStack) Resync() error {
|
||||
if err := m.Apps.Resync(); err != nil {
|
||||
return fmt.Errorf("postfix resync: %w", err)
|
||||
}
|
||||
if m.inboundEnabled {
|
||||
if err := m.Inbound.Resync(); err != nil {
|
||||
return fmt.Errorf("inbound maps resync: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -70,7 +79,7 @@ func newPanel(cfg config, st *store.Store) (*web.Server, error) {
|
||||
// effective config, including a manual override; the panel keeps this
|
||||
// snapshot for the process lifetime (architecture.md).
|
||||
retryPolicy := postfix.LoadRetryPolicy()
|
||||
return web.New(st, ms.Domains, ms.Apps, web.Config{
|
||||
return web.New(st, ms.Domains, ms.Apps, ms.Inbound, web.Config{
|
||||
Hostname: cfg.hostname,
|
||||
CookieSecure: cfg.cookieSecure,
|
||||
SubmissionEnabled: cfg.submissionEnabled,
|
||||
@@ -88,6 +97,7 @@ func newPanel(cfg config, st *store.Store) (*web.Server, error) {
|
||||
RateLimitMessagesPerIP: cfg.rateLimitMessagesPerIP,
|
||||
RateLimitWindowSeconds: cfg.rateLimitWindowSeconds,
|
||||
RetryPolicy: retryPolicy,
|
||||
InboundEnabled: cfg.inboundEnabled,
|
||||
}, cfg.setupTokenPath)
|
||||
}
|
||||
|
||||
|
||||
@@ -79,6 +79,8 @@ type config struct {
|
||||
saslRealm string
|
||||
postfixDir string
|
||||
deployRoot string
|
||||
|
||||
inboundEnabled bool
|
||||
}
|
||||
|
||||
func loadConfig() config {
|
||||
@@ -140,6 +142,8 @@ func loadConfig() config {
|
||||
saslRealm: saslRealm(),
|
||||
postfixDir: envDefault("POSTFIX_DIR", filepath.Join(dataDir, "postfix")),
|
||||
deployRoot: envDefault("SELFPOST_DEPLOY_ROOT", "/selfpost-deploy"),
|
||||
// Optional inbound relay (backup-MX / forwarder). Off unless exactly "true".
|
||||
inboundEnabled: os.Getenv("INBOUND_RELAY_ENABLE") == "true",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user