veza/veza-backend-api/internal/email/sender.go
okinrev b7955a680c P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.

Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.

Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).

Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.

Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 11:14:38 +01:00

120 lines
3 KiB
Go

package email
import (
"fmt"
"net/smtp"
"os"
"go.uber.org/zap"
)
// EmailSender interface pour l'envoi d'emails
type EmailSender interface {
Send(to, subject, body string) error
SendTemplate(to, template string, data map[string]interface{}) error
}
// SMTPConfig contient la configuration SMTP
type SMTPConfig struct {
Host string
Port string
Username string
Password string
From string
FromName string
}
// SMTPEmailSender implémente EmailSender avec SMTP réel
type SMTPEmailSender struct {
config SMTPConfig
logger *zap.Logger
}
// NewSMTPEmailSender crée un nouveau sender SMTP
func NewSMTPEmailSender(config SMTPConfig, logger *zap.Logger) *SMTPEmailSender {
return &SMTPEmailSender{
config: config,
logger: logger,
}
}
// Send envoie un email via SMTP
func (s *SMTPEmailSender) Send(to, subject, body string) error {
// Si pas de config SMTP, log seulement (dev mode)
if s.config.Host == "" {
s.logger.Info("SMTP not configured, email would be sent",
zap.String("to", to),
zap.String("subject", subject),
)
return nil
}
// SMTP auth
auth := smtp.PlainAuth("", s.config.Username, s.config.Password, s.config.Host)
// Email headers avec format correct
fromHeader := s.config.From
if s.config.FromName != "" {
fromHeader = fmt.Sprintf("%s <%s>", s.config.FromName, s.config.From)
}
msg := []byte(fmt.Sprintf("From: %s\r\n"+
"To: %s\r\n"+
"Subject: %s\r\n"+
"MIME-Version: 1.0\r\n"+
"Content-Type: text/html; charset=UTF-8\r\n"+
"\r\n"+
"%s", fromHeader, to, subject, body))
// Send email
addr := fmt.Sprintf("%s:%s", s.config.Host, s.config.Port)
err := smtp.SendMail(addr, auth, s.config.From, []string{to}, msg)
if err != nil {
return fmt.Errorf("failed to send email via SMTP: %w", err)
}
s.logger.Info("Email sent successfully",
zap.String("to", to),
zap.String("subject", subject),
)
return nil
}
// SendTemplate envoie un email avec un template
// Pour l'instant, cette méthode appelle Send avec le body généré
// L'implémentation complète avec template engine sera dans email_job.go
func (s *SMTPEmailSender) SendTemplate(to, template string, data map[string]interface{}) error {
// Cette méthode sera utilisée par EmailJob qui gère le rendu des templates
// Pour l'instant, on délègue au template renderer
return fmt.Errorf("SendTemplate not implemented directly, use EmailJob instead")
}
// LoadSMTPConfigFromEnv charge la config SMTP depuis les variables d'environnement
func LoadSMTPConfigFromEnv() SMTPConfig {
// En dev, fallback sur MailHog si pas de config
host := os.Getenv("SMTP_HOST")
port := os.Getenv("SMTP_PORT")
if host == "" {
host = os.Getenv("MAILHOG_HOST")
if host == "" {
host = "localhost"
}
}
if port == "" {
port = os.Getenv("MAILHOG_PORT")
if port == "" {
port = "1025" // MailHog default
}
}
return SMTPConfig{
Host: host,
Port: port,
Username: os.Getenv("SMTP_USERNAME"),
Password: os.Getenv("SMTP_PASSWORD"),
From: os.Getenv("SMTP_FROM"),
FromName: os.Getenv("SMTP_FROM_NAME"),
}
}