veza/veza-backend-api/internal/workers/email_job.go

109 lines
2.7 KiB
Go

package workers
import (
"bytes"
"context"
"fmt"
"html/template"
"os"
"path/filepath"
"veza-backend-api/internal/email"
"go.uber.org/zap"
)
// EmailJob représente un job d'envoi d'email
type EmailJob struct {
To string
Subject string
Body string
Template string // Nom du template (ex: "password_reset")
Data map[string]interface{} // Données pour le template
}
// NewEmailJob crée un nouveau job d'email
func NewEmailJob(to, subject, body string) *EmailJob {
return &EmailJob{
To: to,
Subject: subject,
Body: body,
Data: make(map[string]interface{}),
}
}
// NewEmailJobWithTemplate crée un job d'email avec template
func NewEmailJobWithTemplate(to, subject, templateName string, data map[string]interface{}) *EmailJob {
return &EmailJob{
To: to,
Subject: subject,
Template: templateName,
Data: data,
}
}
// Execute exécute le job d'email
func (j *EmailJob) Execute(ctx context.Context, sender email.EmailSender, logger *zap.Logger) error {
// Si un template est spécifié, le rendre
body := j.Body
if j.Template != "" {
rendered, err := j.renderTemplate(j.Template, j.Data)
if err != nil {
logger.Error("Failed to render email template",
zap.String("template", j.Template),
zap.Error(err),
)
return fmt.Errorf("failed to render template: %w", err)
}
body = rendered
}
// Envoyer l'email
if err := sender.Send(j.To, j.Subject, body); err != nil {
logger.Error("Failed to send email",
zap.String("to", j.To),
zap.String("subject", j.Subject),
zap.Error(err),
)
return fmt.Errorf("failed to send email: %w", err)
}
logger.Info("Email job executed successfully",
zap.String("to", j.To),
zap.String("subject", j.Subject),
zap.String("template", j.Template),
)
return nil
}
// renderTemplate rend un template email
func (j *EmailJob) renderTemplate(templateName string, data map[string]interface{}) (string, error) {
// Chercher le template dans templates/email/
templateDir := os.Getenv("EMAIL_TEMPLATE_DIR")
if templateDir == "" {
templateDir = "templates/email"
}
templatePath := filepath.Join(templateDir, templateName+".html")
// Lire le fichier template
tmplContent, err := os.ReadFile(templatePath)
if err != nil {
return "", fmt.Errorf("failed to read template file %s: %w", templatePath, err)
}
// Parser le template
tmpl, err := template.New(templateName).Parse(string(tmplContent))
if err != nil {
return "", fmt.Errorf("failed to parse template: %w", err)
}
// Rendre le template avec les données
var buf bytes.Buffer
if err := tmpl.Execute(&buf, data); err != nil {
return "", fmt.Errorf("failed to execute template: %w", err)
}
return buf.String(), nil
}