package main import ( "fmt" "net/smtp" "strings" "time" ) type MailRequest struct { sendto []string title string content string } type MailSender struct { queue chan *MailRequest } const ( LOOP_DELAY = 3 LOOP_QUEUE_SIZE = 10 PUSH_TIMEOUT = 3 ) func NewMailSender() *MailSender { return &MailSender{ queue: make(chan *MailRequest, 100), } } func (s *MailSender) Loop() { timer := time.NewTimer(time.Second * LOOP_DELAY) timeouted := false for { list := make([]*MailRequest, 0) //一次取10条记录 for i := 0; i < LOOP_QUEUE_SIZE; i++ { timer.Reset(time.Second * LOOP_DELAY) select { case req, ok := <-s.queue: timeouted = false timer.Stop() if ok { list = append(list, req) } case <-timer.C: timeouted = true } //如果不足10条也返回 if timeouted { break } } //发送邮件 if len(list) > 0 { s.Send(list) } } } func (s *MailSender) Send(list []*MailRequest) { if len(list) == 0 { return } //取SMTP配置 cfg := SysCfg.GetMulti([]string{"smtp_host", "smtp_port", "smtp_user", "smtp_pwd", "smtp_sender"}) auth := smtp.PlainAuth("", cfg["smtp_user"], cfg["smtp_pwd"], cfg["smtp_host"]) address := fmt.Sprintf("%s:%s", cfg["smtp_host"], cfg["smtp_port"]) //循环发送 for _, req := range list { data := "From: " + cfg["smtp_user"] + "\r\nSender: " + cfg["smtp_sender"] + "\r\nTo: " + strings.Join(req.sendto, ";") + "\r\nContent-Type: text/html;charset=utf-8\r\nSubject: " + req.title + "\r\n\r\n" + req.content err := smtp.SendMail(address, auth, cfg["smtp_user"], req.sendto, []byte(data)) if err != nil { SYSLOG("ERROR", fmt.Sprintf("邮件发送失败:%s,邮件内容如下:%s", err.Error(), data)) } } } func (s *MailSender) Push(req *MailRequest) { timer := time.NewTimer(time.Second * PUSH_TIMEOUT) select { case s.queue <- req: timer.Stop() case <-timer.C: } }