package logic import ( "bytes" "log" "net/smtp" "sync" "text/template" "time" ) var EmailManager *EmailSender // EmailSender type EmailSender struct { lock sync.Mutex EmailTasks chan string // 处理email的队列 Auth smtp.Auth // 邮箱发送处理 FromEmail string // 发送的email, 公司email emailSending map[string]*EmailTask // 正在发送的邮件 ResendTimeLimit time.Duration // 重发时间限制 } // EmailTask type EmailTask struct { Email string // email SendTime time.Time // 处理的任务时间 } // ProcessEmailTasks 处理邮件队列 func (m *EmailSender) ProcessEmailTasks() { for { emailTarget, ok := <-m.EmailTasks if !ok { log.Println("Email task channel closed") break } m.lock.Lock() _, isSending := m.emailSending[emailTarget] if isSending { m.lock.Unlock() continue } m.emailSending[emailTarget] = &EmailTask{ Email: emailTarget, SendTime: time.Now(), } m.lock.Unlock() // TODO: Replace with actual email content content := []byte("Hello, this is a test email") err := smtp.SendMail(emailTarget, m.Auth, m.FromEmail, []string{emailTarget}, content) if err != nil { log.Printf("Failed to send email to %s: %v\n", emailTarget, err) m.Resend(emailTarget, content) } } } // Resend 重发邮件 func (m *EmailSender) Resend(emailTarget string, content []byte) { time.Sleep(m.ResendTimeLimit) m.lock.Lock() defer m.lock.Unlock() // Check if the email task still exists and has not been sent successfully if task, ok := m.emailSending[emailTarget]; ok && task.SendTime.Add(m.ResendTimeLimit).After(time.Now()) { err := smtp.SendMail(emailTarget, m.Auth, m.FromEmail, []string{emailTarget}, content) if err != nil { log.Printf("Failed to resend email to %s: %v\n", emailTarget, err) } else { delete(m.emailSending, emailTarget) } } } // ClearExpiredTasks 清除过期的邮件任务 func (m *EmailSender) ClearExpiredTasks() { ticker := time.NewTicker(time.Minute) defer ticker.Stop() for { <-ticker.C m.lock.Lock() for email, task := range m.emailSending { if task.SendTime.Add(m.ResendTimeLimit).Before(time.Now()) { delete(m.emailSending, email) } } m.lock.Unlock() } } func init() { // Initialize the email manager EmailManager = &EmailSender{ EmailTasks: make(chan string, 10), Auth: smtp.PlainAuth( "", "user@example.com", "password", "smtp.gmail.com", ), FromEmail: "user@example.com", emailSending: make(map[string]*EmailTask, 10), ResendTimeLimit: time.Minute * 1, } // Start processing email tasks go EmailManager.ProcessEmailTasks() // Start clearing expired tasks go EmailManager.ClearExpiredTasks() } const emailTemplate = `Subject: Your {{.CompanyName}} Account Confirmation Dear Thank you for creating an account with {{.CompanyName}}. We're excited to have you on board! Before we get started, we just need to confirm that this is the right email address. Please confirm your email address by clicking on the link below: {{.ConfirmationLink}} Once you've confirmed, you can get started with {{.CompanyName}}. If you have any questions, feel free to reply to this email. We're here to help! If you did not create an account with us, please ignore this email. Thanks, {{.SenderName}} {{.SenderTitle}} {{.CompanyName}} ` func RenderEmailTemplate(companyName, recipient, confirmationLink, senderName, senderTitle string) string { tmpl, err := template.New("email").Parse(emailTemplate) if err != nil { log.Fatal(err) } data := map[string]string{ "CompanyName": companyName, "ConfirmationLink": confirmationLink, "SenderName": senderName, "SenderTitle": senderTitle, } var result bytes.Buffer err = tmpl.Execute(&result, data) if err != nil { log.Fatal(err) } return result.String() }