package service import ( "bytes" "embed" "fmt" "html/template" "time" "gopkg.in/gomail.v2" ) type MailService interface { SendEmail(to, subject, body string) error SendTemplateEmail(to, subject string, templateName string, data interface{}) error SendConfirmationEmail(to, token string) error SendPasswordResetEmail(to, token string) error } type mailService struct { from string smtpHost string smtpPort int smtpUser string smtpPass string templates *template.Template } //go:embed templates/* var templateFS embed.FS func NewMailService(from, smtpHost string, smtpPort int, smtpUser, smtpPass string) (MailService, error) { // Загружаем шаблоны писем templates, err := template.ParseFS(templateFS, "templates/*.html") if err != nil { return nil, fmt.Errorf("failed to parse email templates: %w", err) } return &mailService{ from: from, smtpHost: smtpHost, smtpPort: smtpPort, smtpUser: smtpUser, smtpPass: smtpPass, templates: templates, }, nil } func (s *mailService) SendEmail(to, subject, body string) error { mail := gomail.NewMessage() mail.SetHeader("From", s.from) mail.SetHeader("To", to) mail.SetHeader("Subject", subject) mail.SetBody("text/html", body) dialer := gomail.NewDialer(s.smtpHost, s.smtpPort, s.smtpUser, s.smtpPass) return dialer.DialAndSend(mail) } func (s *mailService) SendTemplateEmail(to, subject string, templateName string, data interface{}) error { var body bytes.Buffer if err := s.templates.ExecuteTemplate(&body, templateName+".html", data); err != nil { return fmt.Errorf("failed to execute template: %w", err) } return s.SendEmail(to, subject, body.String()) } func (s *mailService) SendConfirmationEmail(to, token string) error { data := struct { Email string Token string Year int }{ Email: to, Token: token, Year: time.Now().Year(), } return s.SendTemplateEmail(to, "Подтверждение email", "confirmation", data) } func (s *mailService) SendPasswordResetEmail(to, token string) error { data := struct { Email string Token string Year int }{ Email: to, Token: token, Year: time.Now().Year(), } return s.SendTemplateEmail(to, "Сброс пароля", "password_reset", data) }