From 336aa9b2ce5630710c85017b59862e4d5a05e75e Mon Sep 17 00:00:00 2001 From: smail Date: Thu, 1 Oct 2026 20:59:47 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=85=A8=E6=96=B0=E9=83=A8?= =?UTF-8?q?=E7=BD=B2=E5=8F=8D=E4=BB=A3=E6=A8=A1=E5=BC=8F=E8=AF=81=E4=B9=A6?= =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E5=A4=B1=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/config/ssl_policy.go | 7 ++++--- backend/config/ssl_policy_test.go | 25 +++++++++++++++++++++++++ backend/services/setup/finish.go | 3 ++- backend/services/setup/finish_test.go | 26 ++++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 4 deletions(-) diff --git a/backend/config/ssl_policy.go b/backend/config/ssl_policy.go index 92f08bc..37cd3d0 100644 --- a/backend/config/ssl_policy.go +++ b/backend/config/ssl_policy.go @@ -1,10 +1,11 @@ package config -import "strings" - // UsesProxyHTTPS 表示网页 HTTPS 由反向代理终止,不代表邮件协议可以关闭 TLS。 func (c *Config) UsesProxyHTTPS() bool { - return c != nil && strings.EqualFold(strings.TrimSpace(c.TLSMode), HTTPSTLSModeProxy) + if c == nil { + return false + } + return ResolveHTTPPortDefaults(HTTPConfig{TLSMode: c.TLSMode}, 0).TLSMode == HTTPSTLSModeProxy } // EffectiveSSLType 以证书管理责任为准,仅在旧配置未记录管理方式时兼容旧类型。 diff --git a/backend/config/ssl_policy_test.go b/backend/config/ssl_policy_test.go index d9b559a..f75da70 100644 --- a/backend/config/ssl_policy_test.go +++ b/backend/config/ssl_policy_test.go @@ -38,6 +38,31 @@ func TestSSLPolicyFollowsManagement(t *testing.T) { } } +func TestSSLPolicyFollowsRuntimeTLSOverride(t *testing.T) { + for _, test := range []struct { + name string + stored string + override string + wantProxy bool + }{ + {name: "bootstrap_proxy", override: HTTPSTLSModeProxy, wantProxy: true}, + {name: "direct_to_proxy", stored: HTTPSTLSModeDirect, override: " PROXY ", wantProxy: true}, + {name: "proxy_to_direct", stored: HTTPSTLSModeProxy, override: HTTPSTLSModeDirect}, + {name: "invalid_override", stored: HTTPSTLSModeProxy, override: "invalid", wantProxy: true}, + } { + t.Run(test.name, func(t *testing.T) { + t.Setenv("SMAIL_HTTP_TLS_MODE_OVERRIDE", test.override) + cfg := &Config{TLSMode: test.stored, SSLType: SSLTypeAutoHTTP} + if got := cfg.UsesProxyHTTPS(); got != test.wantProxy { + t.Fatalf("proxy policy = %t, want %t", got, test.wantProxy) + } + if cfg.AutomaticSSLEnabled() == test.wantProxy { + t.Fatal("certificate policy disagrees with effective TLS mode") + } + }) + } +} + func TestExternalCertificateReloadIgnoresLegacyDNSMode(t *testing.T) { previousRoot := ROOT_PATH ROOT_PATH = t.TempDir() diff --git a/backend/services/setup/finish.go b/backend/services/setup/finish.go index dc322cb..e21452b 100644 --- a/backend/services/setup/finish.go +++ b/backend/services/setup/finish.go @@ -64,9 +64,10 @@ func applyServicePorts(cfg *config.Config) bool { HTTPSEnabled: cfg.HttpsEnabled != 2, TLSMode: cfg.TLSMode, }, cfg.GetSetupPort()) - changed := cfg.HttpPort != resolved.Port || cfg.HttpsPort != resolved.HTTPSPort + changed := cfg.HttpPort != resolved.Port || cfg.HttpsPort != resolved.HTTPSPort || cfg.TLSMode != resolved.TLSMode cfg.HttpPort = resolved.Port cfg.HttpsPort = resolved.HTTPSPort + cfg.TLSMode = resolved.TLSMode if resolved.TLSMode == config.HTTPSTLSModeProxy && cfg.HttpsEnabled != 2 { cfg.HttpsEnabled = 2 changed = true diff --git a/backend/services/setup/finish_test.go b/backend/services/setup/finish_test.go index b858245..4dd7db8 100644 --- a/backend/services/setup/finish_test.go +++ b/backend/services/setup/finish_test.go @@ -166,6 +166,32 @@ func TestFinishRejectsInvalidConfigBeforeReady(t *testing.T) { } } +func TestFinishPersistsRuntimeProxyMode(t *testing.T) { + prepareFinishConfigTest(t) + t.Setenv("SMAIL_HTTP_TLS_MODE_OVERRIDE", config.HTTPSTLSModeProxy) + t.Setenv("SMAIL_HTTP_PORT_OVERRIDE", "8001") + if err := config.WriteConfig(&config.Config{ + SetupState: config.SetupStateBootstrap, + HttpsEnabled: 2, + Domain: "example.com", + WebDomain: "mail.example.com", + DbType: config.DBTypeSQLite, + DbDSN: filepath.Join(config.ROOT_PATH, "data", "smail.db"), + }); err != nil { + t.Fatal(err) + } + if err := Finish(); err != nil { + t.Fatal(err) + } + loaded, err := config.ReadConfig() + if err != nil { + t.Fatal(err) + } + if loaded.TLSMode != config.HTTPSTLSModeProxy || loaded.HttpsPort != 0 || loaded.HttpsEnabled != 2 || loaded.HttpPort != 8001 { + t.Fatalf("unexpected HTTP settings: mode=%q port=%d httpsPort=%d enabled=%d", loaded.TLSMode, loaded.HttpPort, loaded.HttpsPort, loaded.HttpsEnabled) + } +} + func prepareFinishConfigTest(t *testing.T) { t.Helper() previousRoot := config.ROOT_PATH