74 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			74 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package notify
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"net/smtp"
 | 
						|
	"strings"
 | 
						|
)
 | 
						|
 | 
						|
// smtpNotifier 实现了 Notifier 接口,用于通过 SMTP 发送邮件通知。
 | 
						|
type smtpNotifier struct {
 | 
						|
	host     string // SMTP 服务器地址
 | 
						|
	port     int    // SMTP 服务器端口
 | 
						|
	username string // 发件人邮箱地址
 | 
						|
	password string // 发件人邮箱授权码
 | 
						|
	sender   string // 发件人名称或地址,显示在邮件的 \"From\" 字段
 | 
						|
}
 | 
						|
 | 
						|
// NewSMTPNotifier 创建一个新的 smtpNotifier 实例。
 | 
						|
// 调用者需要注入 SMTP 相关的配置。
 | 
						|
func NewSMTPNotifier(host string, port int, username, password, sender string) Notifier {
 | 
						|
	return &smtpNotifier{
 | 
						|
		host:     host,
 | 
						|
		port:     port,
 | 
						|
		username: username,
 | 
						|
		password: password,
 | 
						|
		sender:   sender,
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// Send 使用 net/smtp 包发送一封邮件。
 | 
						|
func (s *smtpNotifier) Send(content AlarmContent, toAddr string) error {
 | 
						|
	// 1. 设置认证信息
 | 
						|
	auth := smtp.PlainAuth("", s.username, s.password, s.host)
 | 
						|
 | 
						|
	// 2. 构建邮件内容
 | 
						|
	// 邮件头
 | 
						|
	subject := content.Title
 | 
						|
	contentType := "Content-Type: text/plain; charset=UTF-8"
 | 
						|
	fromHeader := fmt.Sprintf("From: %s", s.sender)
 | 
						|
	toHeader := fmt.Sprintf("To: %s", toAddr)
 | 
						|
	subjectHeader := fmt.Sprintf("Subject: %s", subject)
 | 
						|
 | 
						|
	// 邮件正文
 | 
						|
	body := fmt.Sprintf("级别: %s\n时间: %s\n\n%s",
 | 
						|
		content.Level.String(),
 | 
						|
		content.Timestamp.Format(DefaultTimeFormat),
 | 
						|
		content.Message,
 | 
						|
	)
 | 
						|
 | 
						|
	// 拼接完整的邮件报文
 | 
						|
	msg := strings.Join([]string{
 | 
						|
		fromHeader,
 | 
						|
		toHeader,
 | 
						|
		subjectHeader,
 | 
						|
		contentType,
 | 
						|
		"", // 邮件头和正文之间的空行
 | 
						|
		body,
 | 
						|
	}, "\r\n")
 | 
						|
 | 
						|
	// 3. 发送邮件
 | 
						|
	addr := fmt.Sprintf("%s:%d", s.host, s.port)
 | 
						|
	err := smtp.SendMail(addr, auth, s.username, []string{toAddr}, []byte(msg))
 | 
						|
	if err != nil {
 | 
						|
		return fmt.Errorf("发送邮件失败: %w", err)
 | 
						|
	}
 | 
						|
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// Type 返回通知器的类型
 | 
						|
func (s *smtpNotifier) Type() NotifierType {
 | 
						|
	return NotifierTypeSMTP
 | 
						|
}
 |