Refactor sendEmail function and add support for multiple SMTP auth methods (LOGIN, PLAIN, CRAM-MD5) and TLS verification option, fix syntax error in sendSMTPMessage function

This commit is contained in:
2026-01-22 19:34:05 +01:00
parent 4e61fdf9f4
commit 90d4ff4e9a
11 changed files with 275 additions and 81 deletions

View File

@@ -63,12 +63,14 @@ type AppSettingsRecord struct {
// Console output settings
ConsoleOutput bool
// SMTP settings
SMTPHost string
SMTPPort int
SMTPUsername string
SMTPPassword string
SMTPFrom string
SMTPUseTLS bool
SMTPHost string
SMTPPort int
SMTPUsername string
SMTPPassword string
SMTPFrom string
SMTPUseTLS bool
SMTPInsecureSkipVerify bool
SMTPAuthMethod string
// Fail2Ban DEFAULT settings
BantimeIncrement bool
DefaultJailEnable bool
@@ -192,17 +194,17 @@ func GetAppSettings(ctx context.Context) (AppSettingsRecord, bool, error) {
}
row := db.QueryRowContext(ctx, `
SELECT language, port, debug, restart_needed, callback_url, callback_secret, alert_countries, email_alerts_for_bans, email_alerts_for_unbans, smtp_host, smtp_port, smtp_username, smtp_password, smtp_from, smtp_use_tls, bantime_increment, default_jail_enable, ignore_ip, bantime, findtime, maxretry, destemail, banaction, banaction_allports, advanced_actions, geoip_provider, geoip_database_path, max_log_lines, console_output
SELECT language, port, debug, restart_needed, callback_url, callback_secret, alert_countries, email_alerts_for_bans, email_alerts_for_unbans, smtp_host, smtp_port, smtp_username, smtp_password, smtp_from, smtp_use_tls, bantime_increment, default_jail_enable, ignore_ip, bantime, findtime, maxretry, destemail, banaction, banaction_allports, advanced_actions, geoip_provider, geoip_database_path, max_log_lines, console_output, smtp_insecure_skip_verify, smtp_auth_method
FROM app_settings
WHERE id = 1`)
var (
lang, callback, callbackSecret, alerts, smtpHost, smtpUser, smtpPass, smtpFrom, ignoreIP, bantime, findtime, destemail, banaction, banactionAllports, advancedActions, geoipProvider, geoipDatabasePath sql.NullString
port, smtpPort, maxretry, maxLogLines sql.NullInt64
debug, restartNeeded, smtpTLS, bantimeInc, defaultJailEn, emailAlertsForBans, emailAlertsForUnbans, consoleOutput sql.NullInt64
lang, callback, callbackSecret, alerts, smtpHost, smtpUser, smtpPass, smtpFrom, ignoreIP, bantime, findtime, destemail, banaction, banactionAllports, advancedActions, geoipProvider, geoipDatabasePath, smtpAuthMethod sql.NullString
port, smtpPort, maxretry, maxLogLines sql.NullInt64
debug, restartNeeded, smtpTLS, bantimeInc, defaultJailEn, emailAlertsForBans, emailAlertsForUnbans, consoleOutput, smtpInsecureSkipVerify sql.NullInt64
)
err := row.Scan(&lang, &port, &debug, &restartNeeded, &callback, &callbackSecret, &alerts, &emailAlertsForBans, &emailAlertsForUnbans, &smtpHost, &smtpPort, &smtpUser, &smtpPass, &smtpFrom, &smtpTLS, &bantimeInc, &defaultJailEn, &ignoreIP, &bantime, &findtime, &maxretry, &destemail, &banaction, &banactionAllports, &advancedActions, &geoipProvider, &geoipDatabasePath, &maxLogLines, &consoleOutput)
err := row.Scan(&lang, &port, &debug, &restartNeeded, &callback, &callbackSecret, &alerts, &emailAlertsForBans, &emailAlertsForUnbans, &smtpHost, &smtpPort, &smtpUser, &smtpPass, &smtpFrom, &smtpTLS, &bantimeInc, &defaultJailEn, &ignoreIP, &bantime, &findtime, &maxretry, &destemail, &banaction, &banactionAllports, &advancedActions, &geoipProvider, &geoipDatabasePath, &maxLogLines, &consoleOutput, &smtpInsecureSkipVerify, &smtpAuthMethod)
if errors.Is(err, sql.ErrNoRows) {
return AppSettingsRecord{}, false, nil
}
@@ -224,12 +226,14 @@ WHERE id = 1`)
EmailAlertsForBans: intToBool(intFromNull(emailAlertsForBans)),
EmailAlertsForUnbans: intToBool(intFromNull(emailAlertsForUnbans)),
// SMTP settings
SMTPHost: stringFromNull(smtpHost),
SMTPPort: intFromNull(smtpPort),
SMTPUsername: stringFromNull(smtpUser),
SMTPPassword: stringFromNull(smtpPass),
SMTPFrom: stringFromNull(smtpFrom),
SMTPUseTLS: intToBool(intFromNull(smtpTLS)),
SMTPHost: stringFromNull(smtpHost),
SMTPPort: intFromNull(smtpPort),
SMTPUsername: stringFromNull(smtpUser),
SMTPPassword: stringFromNull(smtpPass),
SMTPFrom: stringFromNull(smtpFrom),
SMTPUseTLS: intToBool(intFromNull(smtpTLS)),
SMTPInsecureSkipVerify: intToBool(intFromNull(smtpInsecureSkipVerify)),
SMTPAuthMethod: stringFromNull(smtpAuthMethod),
// Fail2Ban DEFAULT settings
BantimeIncrement: intToBool(intFromNull(bantimeInc)),
DefaultJailEnable: intToBool(intFromNull(defaultJailEn)),
@@ -258,9 +262,9 @@ func SaveAppSettings(ctx context.Context, rec AppSettingsRecord) error {
}
_, err := db.ExecContext(ctx, `
INSERT INTO app_settings (
id, language, port, debug, restart_needed, callback_url, callback_secret, alert_countries, email_alerts_for_bans, email_alerts_for_unbans, smtp_host, smtp_port, smtp_username, smtp_password, smtp_from, smtp_use_tls, bantime_increment, default_jail_enable, ignore_ip, bantime, findtime, maxretry, destemail, banaction, banaction_allports, advanced_actions, geoip_provider, geoip_database_path, max_log_lines, console_output
id, language, port, debug, restart_needed, callback_url, callback_secret, alert_countries, email_alerts_for_bans, email_alerts_for_unbans, smtp_host, smtp_port, smtp_username, smtp_password, smtp_from, smtp_use_tls, bantime_increment, default_jail_enable, ignore_ip, bantime, findtime, maxretry, destemail, banaction, banaction_allports, advanced_actions, geoip_provider, geoip_database_path, max_log_lines, console_output, smtp_insecure_skip_verify, smtp_auth_method
) VALUES (
1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
) ON CONFLICT(id) DO UPDATE SET
language = excluded.language,
port = excluded.port,
@@ -290,7 +294,9 @@ INSERT INTO app_settings (
geoip_provider = excluded.geoip_provider,
geoip_database_path = excluded.geoip_database_path,
max_log_lines = excluded.max_log_lines,
console_output = excluded.console_output
console_output = excluded.console_output,
smtp_insecure_skip_verify = excluded.smtp_insecure_skip_verify,
smtp_auth_method = excluded.smtp_auth_method
`, rec.Language,
rec.Port,
boolToInt(rec.Debug),
@@ -319,7 +325,9 @@ INSERT INTO app_settings (
rec.GeoIPProvider,
rec.GeoIPDatabasePath,
rec.MaxLogLines,
boolToInt(rec.ConsoleOutput))
boolToInt(rec.ConsoleOutput),
boolToInt(rec.SMTPInsecureSkipVerify),
rec.SMTPAuthMethod)
return err
}
@@ -940,13 +948,25 @@ CREATE INDEX IF NOT EXISTS idx_perm_blocks_status ON permanent_blocks(status);
// return err
// }
// }
// Migration: Add console_output column if it doesn't exist
if _, err := db.ExecContext(ctx, `ALTER TABLE app_settings ADD COLUMN console_output INTEGER DEFAULT 0`); err != nil {
if err != nil && !strings.Contains(strings.ToLower(err.Error()), "duplicate column name") {
return err
}
}
// Migration: Add new SMTP columns if they don't exist
if _, err := db.ExecContext(ctx, `ALTER TABLE app_settings ADD COLUMN smtp_insecure_skip_verify INTEGER DEFAULT 0`); err != nil {
if err != nil && !strings.Contains(strings.ToLower(err.Error()), "duplicate column name") {
return err
}
}
if _, err := db.ExecContext(ctx, `ALTER TABLE app_settings ADD COLUMN smtp_auth_method TEXT DEFAULT 'auto'`); err != nil {
if err != nil && !strings.Contains(strings.ToLower(err.Error()), "duplicate column name") {
return err
}
}
_ = strings.Contains // Keep strings import for migration example above
return nil