mirror of
https://github.com/Dvorinka/beszel.git
synced 2026-06-03 21:02:56 +00:00
147 lines
3.6 KiB
Go
147 lines
3.6 KiB
Go
package providers
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"fmt"
|
|
"net/smtp"
|
|
"strings"
|
|
|
|
"github.com/henrygd/beszel/internal/entities/notification"
|
|
)
|
|
|
|
// EmailProvider implements email notifications via SMTP
|
|
type EmailProvider struct {
|
|
settings notification.EmailSettings
|
|
}
|
|
|
|
// NewEmailProvider creates a new email provider
|
|
func NewEmailProvider(settings notification.EmailSettings) *EmailProvider {
|
|
return &EmailProvider{settings: settings}
|
|
}
|
|
|
|
// Validate checks if the email settings are valid
|
|
func (p *EmailProvider) Validate() error {
|
|
if p.settings.SMTPHost == "" {
|
|
return fmt.Errorf("SMTP host is required")
|
|
}
|
|
if p.settings.SMTPPort == 0 {
|
|
return fmt.Errorf("SMTP port is required")
|
|
}
|
|
if p.settings.FromEmail == "" {
|
|
return fmt.Errorf("from email is required")
|
|
}
|
|
if p.settings.ToEmail == "" {
|
|
return fmt.Errorf("to email is required")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Send sends an email notification
|
|
func (p *EmailProvider) Send(msg *notification.NotificationMessage) error {
|
|
if err := p.Validate(); err != nil {
|
|
return err
|
|
}
|
|
|
|
subject := fmt.Sprintf("[%s] %s - %s", msg.Status, msg.MonitorName, msg.Title)
|
|
body := p.formatBody(msg)
|
|
|
|
// Build email content
|
|
email := fmt.Sprintf(
|
|
"From: %s\r\nTo: %s\r\nSubject: %s\r\nContent-Type: text/plain; charset=UTF-8\r\n\r\n%s",
|
|
p.settings.FromEmail,
|
|
p.settings.ToEmail,
|
|
subject,
|
|
body,
|
|
)
|
|
|
|
// Connect to SMTP server
|
|
addr := fmt.Sprintf("%s:%d", p.settings.SMTPHost, p.settings.SMTPPort)
|
|
|
|
var auth smtp.Auth
|
|
if p.settings.SMTPUser != "" {
|
|
auth = smtp.PlainAuth("", p.settings.SMTPUser, p.settings.SMTPPassword, p.settings.SMTPHost)
|
|
}
|
|
|
|
// Send email
|
|
if p.settings.UseTLS {
|
|
return p.sendTLS(addr, auth, email)
|
|
}
|
|
|
|
return smtp.SendMail(
|
|
addr,
|
|
auth,
|
|
p.settings.FromEmail,
|
|
[]string{p.settings.ToEmail},
|
|
[]byte(email),
|
|
)
|
|
}
|
|
|
|
// sendTLS sends email using TLS
|
|
func (p *EmailProvider) sendTLS(addr string, auth smtp.Auth, email string) error {
|
|
conn, err := tls.Dial("tcp", addr, &tls.Config{ServerName: p.settings.SMTPHost})
|
|
if err != nil {
|
|
return fmt.Errorf("failed to connect via TLS: %w", err)
|
|
}
|
|
defer conn.Close()
|
|
|
|
client, err := smtp.NewClient(conn, p.settings.SMTPHost)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create SMTP client: %w", err)
|
|
}
|
|
defer client.Close()
|
|
|
|
if auth != nil {
|
|
if err := client.Auth(auth); err != nil {
|
|
return fmt.Errorf("authentication failed: %w", err)
|
|
}
|
|
}
|
|
|
|
if err := client.Mail(p.settings.FromEmail); err != nil {
|
|
return fmt.Errorf("failed to set sender: %w", err)
|
|
}
|
|
if err := client.Rcpt(p.settings.ToEmail); err != nil {
|
|
return fmt.Errorf("failed to set recipient: %w", err)
|
|
}
|
|
|
|
w, err := client.Data()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get data writer: %w", err)
|
|
}
|
|
|
|
_, err = w.Write([]byte(email))
|
|
if err != nil {
|
|
w.Close()
|
|
return fmt.Errorf("failed to write email: %w", err)
|
|
}
|
|
|
|
if err := w.Close(); err != nil {
|
|
return fmt.Errorf("failed to close data writer: %w", err)
|
|
}
|
|
|
|
return client.Quit()
|
|
}
|
|
|
|
// formatBody formats the email body
|
|
func (p *EmailProvider) formatBody(msg *notification.NotificationMessage) string {
|
|
var b strings.Builder
|
|
|
|
b.WriteString(fmt.Sprintf("Monitor: %s\n", msg.MonitorName))
|
|
if msg.MonitorURL != "" {
|
|
b.WriteString(fmt.Sprintf("URL: %s\n", msg.MonitorURL))
|
|
}
|
|
b.WriteString(fmt.Sprintf("Status: %s\n", msg.Status))
|
|
b.WriteString(fmt.Sprintf("Time: %s\n", msg.Timestamp.Format("2006-01-02 15:04:05")))
|
|
|
|
if msg.Ping > 0 {
|
|
b.WriteString(fmt.Sprintf("Response Time: %dms\n", msg.Ping))
|
|
}
|
|
|
|
if msg.Message != "" {
|
|
b.WriteString(fmt.Sprintf("\nMessage: %s\n", msg.Message))
|
|
}
|
|
|
|
b.WriteString(fmt.Sprintf("\n%s\n", msg.Body))
|
|
|
|
return b.String()
|
|
}
|