diff --git a/backend/internal/handler/admin/setting_handler_email.go b/backend/internal/handler/admin/setting_handler_email.go index 68d76de6cc..d64ac29aca 100644 --- a/backend/internal/handler/admin/setting_handler_email.go +++ b/backend/internal/handler/admin/setting_handler_email.go @@ -17,7 +17,14 @@ type TestSMTPRequest struct { SMTPPort int `json:"smtp_port"` SMTPUsername string `json:"smtp_username"` SMTPPassword string `json:"smtp_password"` - SMTPUseTLS bool `json:"smtp_use_tls"` + SMTPUseTLS *bool `json:"smtp_use_tls"` +} + +func resolveSMTPUseTLS(requested *bool, savedConfig *service.SMTPConfig) bool { + if requested != nil { + return *requested + } + return savedConfig != nil && savedConfig.UseTLS } // TestSMTPConnection 测试SMTP连接 @@ -64,7 +71,7 @@ func (h *SettingHandler) TestSMTPConnection(c *gin.Context) { Port: req.SMTPPort, Username: req.SMTPUsername, Password: password, - UseTLS: req.SMTPUseTLS, + UseTLS: resolveSMTPUseTLS(req.SMTPUseTLS, savedConfig), } err := h.emailService.TestSMTPConnectionWithConfig(config) @@ -85,7 +92,7 @@ type SendTestEmailRequest struct { SMTPPassword string `json:"smtp_password"` SMTPFrom string `json:"smtp_from_email"` SMTPFromName string `json:"smtp_from_name"` - SMTPUseTLS bool `json:"smtp_use_tls"` + SMTPUseTLS *bool `json:"smtp_use_tls"` } // SendTestEmail 发送测试邮件 @@ -142,7 +149,7 @@ func (h *SettingHandler) SendTestEmail(c *gin.Context) { Password: password, From: req.SMTPFrom, FromName: req.SMTPFromName, - UseTLS: req.SMTPUseTLS, + UseTLS: resolveSMTPUseTLS(req.SMTPUseTLS, savedConfig), } siteName := h.settingService.GetSiteName(c.Request.Context()) diff --git a/backend/internal/handler/admin/setting_handler_email_test.go b/backend/internal/handler/admin/setting_handler_email_test.go new file mode 100644 index 0000000000..aeb79c3f2c --- /dev/null +++ b/backend/internal/handler/admin/setting_handler_email_test.go @@ -0,0 +1,58 @@ +//go:build unit + +package admin + +import ( + "bytes" + "net/http" + "net/http/httptest" + "testing" + + "github.com/Wei-Shaw/sub2api/internal/service" + + "github.com/gin-gonic/gin" + "github.com/stretchr/testify/require" +) + +func bindSMTPRequest[T any](t *testing.T, body string) T { + t.Helper() + + req := httptest.NewRequest(http.MethodPost, "/", bytes.NewBufferString(body)) + req.Header.Set("Content-Type", "application/json") + c, _ := gin.CreateTestContext(httptest.NewRecorder()) + c.Request = req + + var payload T + require.NoError(t, c.ShouldBindJSON(&payload)) + return payload +} + +func TestTestSMTPRequestUseTLSOmissionFallsBackToSavedSetting(t *testing.T) { + req := bindSMTPRequest[TestSMTPRequest](t, `{}`) + + require.Nil(t, req.SMTPUseTLS) + require.True(t, resolveSMTPUseTLS(req.SMTPUseTLS, &service.SMTPConfig{UseTLS: true})) +} + +func TestTestSMTPRequestExplicitFalseOverridesSavedUseTLS(t *testing.T) { + req := bindSMTPRequest[TestSMTPRequest](t, `{"smtp_use_tls":false}`) + + require.NotNil(t, req.SMTPUseTLS) + require.False(t, resolveSMTPUseTLS(req.SMTPUseTLS, &service.SMTPConfig{UseTLS: true})) +} + +func TestTestSMTPRequestExplicitTrueOverridesMissingSavedUseTLS(t *testing.T) { + req := bindSMTPRequest[TestSMTPRequest](t, `{"smtp_use_tls":true}`) + + require.NotNil(t, req.SMTPUseTLS) + require.True(t, resolveSMTPUseTLS(req.SMTPUseTLS, nil)) +} + +func TestSendTestEmailRequestPreservesUseTLSOmissionSemantics(t *testing.T) { + omitted := bindSMTPRequest[SendTestEmailRequest](t, `{"email":"admin@example.com"}`) + explicitFalse := bindSMTPRequest[SendTestEmailRequest](t, `{"email":"admin@example.com","smtp_use_tls":false}`) + saved := &service.SMTPConfig{UseTLS: true} + + require.True(t, resolveSMTPUseTLS(omitted.SMTPUseTLS, saved)) + require.False(t, resolveSMTPUseTLS(explicitFalse.SMTPUseTLS, saved)) +}