package mailer import ( "crypto/tls" "fmt" "net/smtp" "os" "strconv" "strings" ) func envBool(key string) bool { v, err := strconv.ParseBool(strings.TrimSpace(os.Getenv(key))) if err != nil { return false } return v } func Send(to, subject, body string) error { host := strings.TrimSpace(os.Getenv("EMAIL_HOST")) port := strings.TrimSpace(os.Getenv("EMAIL_PORT")) from := strings.TrimSpace(os.Getenv("EMAIL_FROM")) username := strings.TrimSpace(os.Getenv("EMAIL_HOST_USER")) password := strings.TrimSpace(os.Getenv("EMAIL_HOST_PASSWORD")) if host == "" || port == "" || from == "" { return fmt.Errorf("email configuration is incomplete") } addr := host + ":" + port msg := strings.Join([]string{ "From: " + from, "To: " + to, "Subject: " + subject, "MIME-Version: 1.0", "Content-Type: text/plain; charset=UTF-8", "", body, }, "\r\n") var auth smtp.Auth if username != "" { auth = smtp.PlainAuth("", username, password, host) } useSSL := envBool("EMAIL_USE_SSL") useTLS := envBool("EMAIL_USE_TLS") if useSSL { conn, err := tls.Dial("tcp", addr, &tls.Config{ServerName: host}) if err != nil { return err } defer conn.Close() client, err := smtp.NewClient(conn, host) if err != nil { return err } defer client.Quit() if auth != nil { if err := client.Auth(auth); err != nil { return err } } if err := client.Mail(from); err != nil { return err } if err := client.Rcpt(to); err != nil { return err } w, err := client.Data() if err != nil { return err } if _, err := w.Write([]byte(msg)); err != nil { _ = w.Close() return err } return w.Close() } if !useTLS { return smtp.SendMail(addr, auth, from, []string{to}, []byte(msg)) } client, err := smtp.Dial(addr) if err != nil { return err } defer client.Quit() if err := client.StartTLS(&tls.Config{ServerName: host}); err != nil { return err } if auth != nil { if err := client.Auth(auth); err != nil { return err } } if err := client.Mail(from); err != nil { return err } if err := client.Rcpt(to); err != nil { return err } w, err := client.Data() if err != nil { return err } if _, err := w.Write([]byte(msg)); err != nil { _ = w.Close() return err } return w.Close() }