From bc57f96b7061175eb3d2339b3ad8dfcfb59c242b Mon Sep 17 00:00:00 2001 From: Magnus Root Date: Fri, 27 Mar 2026 17:36:52 +0300 Subject: [PATCH] Added smtp alerts --- email.go | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/email.go b/email.go index 6e85514..defa974 100644 --- a/email.go +++ b/email.go @@ -32,7 +32,7 @@ func emailSendHTML(subject, message string) error { var auth smtp.Auth if cfgEmailSMTPUser != "" && cfgEmailSMTPPassword != "" { - auth = smtp.PlainAuth("", cfgEmailSMTPUser, cfgEmailSMTPPassword, cfgEmailSMTPHost) + auth = &emailLoginAuth{user: cfgEmailSMTPUser, password: cfgEmailSMTPPassword} } header := strings.Join([]string{ @@ -55,6 +55,34 @@ func emailSendHTML(subject, message string) error { return nil } +// ── LOGIN Auth ─────────────────────────────────────────────────────────────── +// Реализация AUTH LOGIN для SMTP-серверов которые не поддерживают AUTH PLAIN. +// Стандартный smtp.PlainAuth использует механизм PLAIN — некоторые серверы +// (например Microsoft Exchange) принимают только LOGIN. + +type emailLoginAuth struct { + user string + password string +} + +func (a *emailLoginAuth) Start(_ *smtp.ServerInfo) (string, []byte, error) { + return "LOGIN", nil, nil +} + +func (a *emailLoginAuth) Next(fromServer []byte, more bool) ([]byte, error) { + if !more { + return nil, nil + } + switch strings.ToLower(strings.TrimSpace(string(fromServer))) { + case "username:": + return []byte(a.user), nil + case "password:": + return []byte(a.password), nil + default: + return nil, fmt.Errorf("неожиданный запрос от SMTP-сервера: %q", string(fromServer)) + } +} + // emailBuildHTML оборачивает тело сообщения в HTML-шаблон письма. // Telegram-теги уже являются валидным HTML, поэтому конвертация не нужна. func emailBuildHTML(subject, body string) string {