130 lines
2.5 KiB
Go
130 lines
2.5 KiB
Go
package actions
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"fmt"
|
|
"net"
|
|
"net/smtp"
|
|
"strings"
|
|
|
|
"github.com/d3m0k1d/BanForge/internal/config"
|
|
)
|
|
|
|
func SendEmail(action config.Action) error {
|
|
if !action.Enabled {
|
|
return nil
|
|
}
|
|
|
|
if action.SMTPHost == "" {
|
|
return fmt.Errorf("SMTP host is empty")
|
|
}
|
|
|
|
if action.Email == "" {
|
|
return fmt.Errorf("recipient email is empty")
|
|
}
|
|
|
|
if action.EmailSender == "" {
|
|
return fmt.Errorf("sender email is empty")
|
|
}
|
|
|
|
addr := fmt.Sprintf("%s:%d", action.SMTPHost, action.SMTPPort)
|
|
|
|
subject := action.EmailSubject
|
|
if subject == "" {
|
|
subject = "BanForge Alert"
|
|
}
|
|
|
|
var body strings.Builder
|
|
body.WriteString("From: " + action.EmailSender + "\r\n")
|
|
body.WriteString("To: " + action.Email + "\r\n")
|
|
body.WriteString("Subject: " + subject + "\r\n")
|
|
body.WriteString("MIME-Version: 1.0\r\n")
|
|
body.WriteString("Content-Type: text/plain; charset=UTF-8\r\n")
|
|
body.WriteString("\r\n")
|
|
body.WriteString(action.Body)
|
|
|
|
auth := smtp.PlainAuth("", action.SMTPUser, action.SMTPPassword, action.SMTPHost)
|
|
|
|
if action.SMTPTLS {
|
|
return sendEmailWithTLS(
|
|
addr,
|
|
auth,
|
|
action.EmailSender,
|
|
[]string{action.Email},
|
|
body.String(),
|
|
)
|
|
}
|
|
|
|
return smtp.SendMail(
|
|
addr,
|
|
auth,
|
|
action.EmailSender,
|
|
[]string{action.Email},
|
|
[]byte(body.String()),
|
|
)
|
|
}
|
|
|
|
func sendEmailWithTLS(addr string, auth smtp.Auth, from string, to []string, msg string) error {
|
|
host, _, err := net.SplitHostPort(addr)
|
|
if err != nil {
|
|
return fmt.Errorf("split host port: %w", err)
|
|
}
|
|
|
|
tlsConfig := &tls.Config{
|
|
ServerName: host,
|
|
MinVersion: tls.VersionTLS12,
|
|
}
|
|
|
|
conn, err := tls.Dial("tcp", addr, tlsConfig)
|
|
if err != nil {
|
|
return fmt.Errorf("dial TLS: %w", err)
|
|
}
|
|
defer func() {
|
|
_ = conn.Close()
|
|
}()
|
|
|
|
c, err := smtp.NewClient(conn, host)
|
|
if err != nil {
|
|
return fmt.Errorf("create SMTP client: %w", err)
|
|
}
|
|
defer func() {
|
|
_ = c.Close()
|
|
}()
|
|
|
|
if auth != nil {
|
|
if ok, _ := c.Extension("AUTH"); !ok {
|
|
return fmt.Errorf("SMTP server does not support AUTH")
|
|
}
|
|
if err = c.Auth(auth); err != nil {
|
|
return fmt.Errorf("authenticate: %w", err)
|
|
}
|
|
}
|
|
|
|
if err = c.Mail(from); err != nil {
|
|
return fmt.Errorf("mail from: %w", err)
|
|
}
|
|
|
|
for _, addr := range to {
|
|
if err = c.Rcpt(addr); err != nil {
|
|
return fmt.Errorf("rcpt to: %w", err)
|
|
}
|
|
}
|
|
|
|
w, err := c.Data()
|
|
if err != nil {
|
|
return fmt.Errorf("data: %w", err)
|
|
}
|
|
|
|
_, err = w.Write([]byte(msg))
|
|
if err != nil {
|
|
return fmt.Errorf("write message: %w", err)
|
|
}
|
|
|
|
err = w.Close()
|
|
if err != nil {
|
|
return fmt.Errorf("close data: %w", err)
|
|
}
|
|
|
|
return c.Quit()
|
|
}
|