131 lines
3.3 KiB
Go
131 lines
3.3 KiB
Go
package clients
|
|
|
|
import (
|
|
"fmt"
|
|
"net/smtp"
|
|
"crypto/tls"
|
|
|
|
"github.com/spf13/viper"
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
type SMTPSettings struct {
|
|
Host string
|
|
Port int
|
|
Username string
|
|
Password string
|
|
Encryption string // "tls", "ssl", "none"
|
|
FromAddress string
|
|
FromName string
|
|
}
|
|
|
|
var smtpSettings SMTPSettings
|
|
|
|
func InitSMTPSettings() {
|
|
smtpSettings = SMTPSettings{
|
|
Host: viper.GetString("smtp.host"),
|
|
Port: viper.GetInt("smtp.port"),
|
|
Username: viper.GetString("smtp.username"),
|
|
Password: viper.GetString("smtp.password"),
|
|
Encryption: viper.GetString("smtp.encryption"),
|
|
FromAddress: viper.GetString("smtp.from_address"),
|
|
FromName: viper.GetString("smtp.from_name"),
|
|
}
|
|
|
|
if smtpSettings.Host == "" || smtpSettings.Port == 0 || smtpSettings.FromAddress == "" {
|
|
log.Warn().Msg("SMTP configuration incomplete. Email sending may not work.")
|
|
} else {
|
|
log.Info().Msgf("SMTP client initialized for %s:%d", smtpSettings.Host, smtpSettings.Port)
|
|
}
|
|
}
|
|
|
|
func GetSMTPSettings() SMTPSettings {
|
|
return smtpSettings
|
|
}
|
|
|
|
// SendEmail sends an email using the configured SMTP settings.
|
|
func SendEmail(toAddress, subject, body string) error {
|
|
if smtpSettings.Host == "" {
|
|
return fmt.Errorf("SMTP client not initialized or host is empty")
|
|
}
|
|
|
|
addr := fmt.Sprintf("%s:%d", smtpSettings.Host, smtpSettings.Port)
|
|
|
|
// Setup authentication
|
|
auth := smtp.PlainAuth("", smtpSettings.Username, smtpSettings.Password, smtpSettings.Host)
|
|
|
|
// Construct the email message
|
|
mime := "MIME-version: 1.0;\nContent-Type: text/html; charset=\"UTF-8\";\n"
|
|
msg := []byte("From: " + smtpSettings.FromName + " <" + smtpSettings.FromAddress + ">\r\n" +
|
|
"To: " + toAddress + "\r\n" +
|
|
"Subject: " + subject + "\r\n" +
|
|
mime + "\r\n" +
|
|
body + "\r\n")
|
|
|
|
var err error
|
|
switch smtpSettings.Encryption {
|
|
case "tls":
|
|
// TLS encryption
|
|
err = sendMailTLS(addr, auth, smtpSettings.FromAddress, []string{toAddress}, msg)
|
|
case "ssl":
|
|
// SSL encryption (usually port 465)
|
|
err = smtp.SendMail(addr, auth, smtpSettings.FromAddress, []string{toAddress}, msg)
|
|
case "none":
|
|
// No encryption (usually port 25 or 587 without STARTTLS)
|
|
err = smtp.SendMail(addr, auth, smtpSettings.FromAddress, []string{toAddress}, msg)
|
|
default:
|
|
return fmt.Errorf("unsupported SMTP encryption type: %s", smtpSettings.Encryption)
|
|
}
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("failed to send email: %w", err)
|
|
}
|
|
log.Info().Msgf("Email sent successfully to %s", toAddress)
|
|
return nil
|
|
}
|
|
|
|
// sendMailTLS sends an email over a TLS connection.
|
|
func sendMailTLS(addr string, auth smtp.Auth, from string, to []string, msg []byte) error {
|
|
conn, err := tls.Dial("tcp", addr, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer conn.Close()
|
|
|
|
client, err := smtp.NewClient(conn, smtpSettings.Host)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer client.Close()
|
|
|
|
if auth != nil {
|
|
if ok, _ := client.Extension("AUTH"); ok {
|
|
if err = client.Auth(auth); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
if err = client.Mail(from); err != nil {
|
|
return err
|
|
}
|
|
for _, addr := range to {
|
|
if err = client.Rcpt(addr); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
w, err := client.Data()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = w.Write(msg)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = w.Close()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return client.Quit()
|
|
}
|