Fix SMTP submission HELO handling
CI / test (push) Successful in 29s
CI / publish (push) Failing after 28s

This commit is contained in:
Joe Julian
2026-03-28 16:35:34 -07:00
parent 2596dee885
commit 21e6ff3e9e
3 changed files with 40 additions and 0 deletions
+1
View File
@@ -21,6 +21,7 @@ Recommended settings:
- `ALMA_PASSWORD`
- `SMTP_PORT=587`
- `SMTP_STARTTLS=true`
- `SMTP_HELO_NAME=mailer.example.invalid`
- `SMTP_USERNAME`
- `SMTP_PASSWORD`
- `PRINT_REPORT=true`
+30
View File
@@ -39,6 +39,7 @@ type Config struct {
SMTPUsername string
SMTPPassword string
SMTPStartTLS bool
SMTPHeloName string
EmailFrom string
EmailTo []string
PrintReport bool
@@ -172,6 +173,10 @@ func loadConfig() (Config, error) {
return Config{}, err
}
smtpStartTLS := readBool("SMTP_STARTTLS", true)
smtpHeloName, err := readValue("SMTP_HELO_NAME", "", false)
if err != nil {
return Config{}, err
}
emailFrom, err := readValue("EMAIL_FROM", "", false)
if err != nil {
return Config{}, err
@@ -204,6 +209,7 @@ func loadConfig() (Config, error) {
SMTPUsername: smtpUsername,
SMTPPassword: smtpPassword,
SMTPStartTLS: smtpStartTLS,
SMTPHeloName: normalizeSMTPHeloName(smtpHeloName),
EmailFrom: emailFrom,
EmailTo: emailTo,
PrintReport: printReport,
@@ -594,11 +600,18 @@ func sendEmail(cfg Config, subject, body string) error {
defer conn.Close()
host := cfg.SMTPHost
heloName := normalizeSMTPHeloName(cfg.SMTPHeloName)
if err := conn.Hello(heloName); err != nil {
return err
}
if cfg.SMTPStartTLS {
if ok, _ := conn.Extension("STARTTLS"); ok {
if err := conn.StartTLS(&tls.Config{ServerName: host, MinVersion: tls.VersionTLS12}); err != nil {
return err
}
if err := conn.Hello(heloName); err != nil {
return err
}
}
}
if cfg.SMTPUsername != "" {
@@ -641,6 +654,23 @@ func sendEmail(cfg Config, subject, body string) error {
return conn.Quit()
}
func normalizeSMTPHeloName(value string) string {
value = strings.TrimSpace(value)
if value == "" {
hostname, err := os.Hostname()
if err == nil {
value = strings.TrimSpace(hostname)
}
}
if value == "" {
return "localhost.localdomain"
}
if strings.Contains(value, ".") {
return value
}
return value + ".localdomain"
}
func inferAssignmentDate(monthDay string, now time.Time) time.Time {
return inferDate(monthDay, now, false)
}
+9
View File
@@ -132,6 +132,15 @@ func TestLoadAlmaCredsFromFile(t *testing.T) {
}
}
func TestNormalizeSMTPHeloName(t *testing.T) {
if got := normalizeSMTPHeloName("mail.example.invalid"); got != "mail.example.invalid" {
t.Fatalf("got %q", got)
}
if got := normalizeSMTPHeloName("mailer"); got != "mailer.localdomain" {
t.Fatalf("got %q", got)
}
}
func mustParseHTML(text string) *html.Node {
doc, err := html.Parse(strings.NewReader(text))
if err != nil {