From c4fb0d9bfc3064a195741ab26edb6452acb38e19 Mon Sep 17 00:00:00 2001 From: zuevav Date: Tue, 6 Oct 2026 22:51:29 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=BE=D1=87=D1=82=D0=B0:=20=D0=BF=D0=BE?= =?UTF-8?q?=D0=BB=D0=B5=20=C2=AB=D0=9F=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BE?= =?UTF-8?q?=D1=87=D0=BD=D0=BE=D0=B5=20=D0=BF=D0=B8=D1=81=D1=8C=D0=BC=D0=BE?= =?UTF-8?q?=20=E2=80=94=20=D0=BA=D0=BE=D0=BC=D1=83=C2=BB=20=D0=B2=D0=B5?= =?UTF-8?q?=D1=80=D0=BD=D1=83=D0=BB=D0=BE=D1=81=D1=8C=20=E2=80=94=20=D0=BF?= =?UTF-8?q?=D0=BE=20=D1=83=D0=BC=D0=BE=D0=BB=D1=87=D0=B0=D0=BD=D0=B8=D1=8E?= =?UTF-8?q?=20=D0=B0=D0=B4=D0=BC=D0=B8=D0=BD=D0=B8=D1=81=D1=82=D1=80=D0=B0?= =?UTF-8?q?=D1=82=D0=BE=D1=80=20=D1=81=D0=B8=D1=81=D1=82=D0=B5=D0=BC=D1=8B?= =?UTF-8?q?,=20=D0=BC=D0=BE=D0=B6=D0=BD=D0=BE=20=D1=83=D0=BA=D0=B0=D0=B7?= =?UTF-8?q?=D0=B0=D1=82=D1=8C=20=D1=81=D0=B2=D0=BE=D0=B9=20=D0=B0=D0=B4?= =?UTF-8?q?=D1=80=D0=B5=D1=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_014FsEKyJrYF69Cj9ZXzFLRi --- internal/lkgateway/notifyadmin_test.go | 21 ++++++++++++++++++ internal/lkgateway/runtimeconfig.go | 22 ++++++++++--------- internal/lkgateway/setup.go | 22 +++++++++++++++++-- .../lkgateway/web/templates/part_alerts.html | 2 ++ 4 files changed, 55 insertions(+), 12 deletions(-) diff --git a/internal/lkgateway/notifyadmin_test.go b/internal/lkgateway/notifyadmin_test.go index ed0dddf..1df3673 100644 --- a/internal/lkgateway/notifyadmin_test.go +++ b/internal/lkgateway/notifyadmin_test.go @@ -1,6 +1,8 @@ package lkgateway import ( + "net/http" + "net/http/httptest" "path/filepath" "strings" "testing" @@ -136,3 +138,22 @@ func TestSMBLocation(t *testing.T) { t.Error("smbShareOK/smbWin") } } + +// Поле «Проверочное письмо — кому»: адрес администратора по умолчанию не дублируется, свой — запоминается. +func TestSMTPTestTo(t *testing.T) { + s := SMTPSettings{To: "it@example.ru", TestTo: "old@example.ru"} + req := func(body string) *http.Request { + r := httptest.NewRequest(http.MethodPost, "/admin/setup/alerts-smtp-test", strings.NewReader(body)) + r.Header.Set("Content-Type", "application/x-www-form-urlencoded") + return r + } + if got := smtpTestTo(req("test_to=me%40example.ru"), s); got != "me@example.ru" { + t.Errorf("свой адрес: %q", got) + } + if got := smtpTestTo(req("test_to=it%40example.ru"), s); got != "" { + t.Errorf("адрес администратора не хранится отдельно: %q", got) + } + if got := smtpTestTo(req("host=x"), s); got != "old@example.ru" { + t.Errorf("без поля — прежний: %q", got) + } +} diff --git a/internal/lkgateway/runtimeconfig.go b/internal/lkgateway/runtimeconfig.go index 27dfd7a..fb07495 100644 --- a/internal/lkgateway/runtimeconfig.go +++ b/internal/lkgateway/runtimeconfig.go @@ -557,16 +557,18 @@ type AlertSettings struct { // SMTPSettings — параметры отправки уведомлений по e-mail. type SMTPSettings struct { - Enabled bool `json:"enabled"` - Host string `json:"host"` - Port int `json:"port"` // 587 (STARTTLS), 465 (SSL), 25 - Security string `json:"security"` // "starttls" | "ssl" | "none" - Username string `json:"username"` - Password string `json:"password"` - From string `json:"from"` - To string `json:"to"` // получатели через запятую - LastMsg string `json:"last_msg"` - LastAt time.Time `json:"last_at"` + Enabled bool `json:"enabled"` + Host string `json:"host"` + Port int `json:"port"` // 587 (STARTTLS), 465 (SSL), 25 + Security string `json:"security"` // "starttls" | "ssl" | "none" + Username string `json:"username"` + Password string `json:"password"` + From string `json:"from"` + To string `json:"to"` // администратор системы (через запятую) — задаётся в «Кому писать» + // TestTo — куда слать проверочное письмо (поле в блоке «Почта»); пусто — администратору системы. + TestTo string `json:"test_to,omitempty"` + LastMsg string `json:"last_msg"` + LastAt time.Time `json:"last_at"` } // ZabbixSettings — trapper-хук: bj шлёт значение элемента данных на сервер/прокси diff --git a/internal/lkgateway/setup.go b/internal/lkgateway/setup.go index d65d8d8..4da27a5 100644 --- a/internal/lkgateway/setup.go +++ b/internal/lkgateway/setup.go @@ -1042,6 +1042,7 @@ func (h *setupHandlers) saveAlertsSMTP(w http.ResponseWriter, r *http.Request) { Password: pickStr(r.FormValue("password"), a.SMTP.Password), // пароль в страницу не выводится: пусто — прежний From: strings.TrimSpace(r.FormValue("from")), To: a.SMTP.To, // адрес администратора системы — в «Кому писать» (notifyGroupsCard) + TestTo: smtpTestTo(r, a.SMTP), LastMsg: a.SMTP.LastMsg, LastAt: a.SMTP.LastAt, } @@ -1052,6 +1053,20 @@ func (h *setupHandlers) saveAlertsSMTP(w http.ResponseWriter, r *http.Request) { setupFlash(w, r, "Настройки SMTP сохранены") } +// smtpTestTo — адрес проверочного письма из формы «Почта»; совпадает с адресом администратора — не храним отдельно +// (поле показывает его по умолчанию), поля в запросе нет — прежний. +func smtpTestTo(r *http.Request, s SMTPSettings) string { + _ = r.ParseForm() + if _, ok := r.Form["test_to"]; !ok { + return s.TestTo + } + v := strings.TrimSpace(r.FormValue("test_to")) + if v == strings.TrimSpace(s.To) { + return "" + } + return v +} + // testAlertsSMTP шлёт пробное письмо по текущим (сохранённым) настройкам. func (h *setupHandlers) testAlertsSMTP(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { @@ -1060,8 +1075,11 @@ func (h *setupHandlers) testAlertsSMTP(w http.ResponseWriter, r *http.Request) { } cfg := h.rc.Snapshot() a := cfg.Alerts - // кому: администратор системы, а пока его адреса нет — все адреса отделов из «Кому писать» + // кому: адрес из поля «Проверочное письмо — кому», иначе администратор системы, а пока его адреса нет — + // все адреса отделов из «Кому писать» + a.SMTP.TestTo = smtpTestTo(r, a.SMTP) test := a.SMTP + test.To = pickStr(a.SMTP.TestTo, a.SMTP.To) if strings.TrimSpace(test.To) == "" { var all []string for _, k := range notifyKinds { @@ -1070,7 +1088,7 @@ func (h *setupHandlers) testAlertsSMTP(w http.ResponseWriter, r *http.Request) { test.To = mergeEmails(all...) } if strings.TrimSpace(test.To) == "" { - setupFlash(w, r, "Проверка SMTP: укажите хотя бы один адрес в блоке «Кому писать» и сохраните") + setupFlash(w, r, "Проверка SMTP: укажите, куда отправить проверочное письмо") return } err := sendSMTP(test, "[bj] Проверка уведомлений", "Это проверочное письмо от bj-server. Если вы его получили — SMTP-канал оповещений работает.") diff --git a/internal/lkgateway/web/templates/part_alerts.html b/internal/lkgateway/web/templates/part_alerts.html index 7ed11de..8c9d8f9 100644 --- a/internal/lkgateway/web/templates/part_alerts.html +++ b/internal/lkgateway/web/templates/part_alerts.html @@ -20,6 +20,8 @@
+
+ По умолчанию — администратор системы из блока «Кому писать».