359 lines
8.8 KiB
Markdown
359 lines
8.8 KiB
Markdown
|
|
# Job Worker Email - Documentation Complète
|
||
|
|
|
||
|
|
## 📋 Vue d'ensemble
|
||
|
|
|
||
|
|
Le système de Job Worker Email permet l'envoi asynchrone d'emails transactionnels (password reset, welcome, notifications) via un système de queue et de workers en arrière-plan.
|
||
|
|
|
||
|
|
## 🏗️ Architecture
|
||
|
|
|
||
|
|
### Composants principaux
|
||
|
|
|
||
|
|
1. **JobWorker** (`internal/workers/job_worker.go`)
|
||
|
|
- Gère la queue de jobs
|
||
|
|
- Exécute les jobs via des workers en parallèle
|
||
|
|
- Gère les retries avec exponential backoff
|
||
|
|
- Supporte plusieurs types de jobs (email, thumbnail, analytics)
|
||
|
|
|
||
|
|
2. **EmailJob** (`internal/workers/email_job.go`)
|
||
|
|
- Représente un job d'envoi d'email
|
||
|
|
- Supporte l'envoi direct (body) ou via template
|
||
|
|
- Rend les templates HTML avec données dynamiques
|
||
|
|
|
||
|
|
3. **EmailSender** (`internal/email/sender.go`)
|
||
|
|
- Interface pour l'envoi d'emails
|
||
|
|
- Implémentation SMTP avec `SMTPEmailSender`
|
||
|
|
- Supporte MailHog en développement
|
||
|
|
|
||
|
|
4. **Templates Email** (`templates/email/`)
|
||
|
|
- Templates HTML pour différents types d'emails
|
||
|
|
- Utilise Go templates (`html/template`)
|
||
|
|
- Supporte les données dynamiques
|
||
|
|
|
||
|
|
## 🚀 Démarrage
|
||
|
|
|
||
|
|
### 1. Configuration SMTP
|
||
|
|
|
||
|
|
Le système charge la configuration SMTP depuis les variables d'environnement :
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Configuration SMTP (production)
|
||
|
|
SMTP_HOST=smtp.gmail.com
|
||
|
|
SMTP_PORT=587
|
||
|
|
SMTP_USERNAME=your-email@gmail.com
|
||
|
|
SMTP_PASSWORD=your-app-password
|
||
|
|
SMTP_FROM=noreply@veza.app
|
||
|
|
SMTP_FROM_NAME=Veza
|
||
|
|
|
||
|
|
# En développement, fallback sur MailHog
|
||
|
|
MAILHOG_HOST=localhost
|
||
|
|
MAILHOG_PORT=1025
|
||
|
|
```
|
||
|
|
|
||
|
|
**Note** : En développement, si `SMTP_HOST` n'est pas défini, le système utilise automatiquement MailHog (localhost:1025).
|
||
|
|
|
||
|
|
### 2. Démarrage automatique
|
||
|
|
|
||
|
|
Le Job Worker démarre automatiquement au lancement du backend dans `cmd/api/main.go` :
|
||
|
|
|
||
|
|
```go
|
||
|
|
if cfg.JobWorker != nil {
|
||
|
|
workerCtx, workerCancel := context.WithCancel(context.Background())
|
||
|
|
defer workerCancel()
|
||
|
|
cfg.JobWorker.Start(workerCtx)
|
||
|
|
logger.Info("✅ Job Worker démarré")
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 3. Configuration du répertoire des templates
|
||
|
|
|
||
|
|
Par défaut, les templates sont cherchés dans `templates/email/`. Vous pouvez changer cela via :
|
||
|
|
|
||
|
|
```bash
|
||
|
|
EMAIL_TEMPLATE_DIR=/path/to/templates
|
||
|
|
```
|
||
|
|
|
||
|
|
## 📧 Utilisation
|
||
|
|
|
||
|
|
### Envoi d'email simple
|
||
|
|
|
||
|
|
```go
|
||
|
|
// Depuis un service ou handler
|
||
|
|
jobWorker.EnqueueEmailJob(
|
||
|
|
"user@example.com",
|
||
|
|
"Welcome to Veza",
|
||
|
|
"<h1>Welcome!</h1><p>Thanks for joining.</p>",
|
||
|
|
)
|
||
|
|
```
|
||
|
|
|
||
|
|
### Envoi d'email avec template
|
||
|
|
|
||
|
|
```go
|
||
|
|
// Préparer les données du template
|
||
|
|
templateData := map[string]interface{}{
|
||
|
|
"Username": "john_doe",
|
||
|
|
"ResetURL": "http://localhost:5173/reset-password?token=abc123",
|
||
|
|
}
|
||
|
|
|
||
|
|
// Enqueue le job
|
||
|
|
jobWorker.EnqueueEmailJobWithTemplate(
|
||
|
|
"user@example.com",
|
||
|
|
"Reset your Veza password",
|
||
|
|
"password_reset", // Nom du template (sans .html)
|
||
|
|
templateData,
|
||
|
|
)
|
||
|
|
```
|
||
|
|
|
||
|
|
### Depuis AuthService (exemple : Password Reset)
|
||
|
|
|
||
|
|
Le `AuthService` utilise automatiquement le Job Worker pour envoyer les emails de reset :
|
||
|
|
|
||
|
|
```go
|
||
|
|
// Dans internal/core/auth/service.go
|
||
|
|
s.jobWorker.EnqueueEmailJobWithTemplate(
|
||
|
|
user.Email,
|
||
|
|
"Reset your Veza password",
|
||
|
|
"password_reset",
|
||
|
|
templateData,
|
||
|
|
)
|
||
|
|
```
|
||
|
|
|
||
|
|
## 📝 Templates Email
|
||
|
|
|
||
|
|
### Structure des templates
|
||
|
|
|
||
|
|
Les templates sont des fichiers HTML dans `templates/email/` avec l'extension `.html`.
|
||
|
|
|
||
|
|
**Exemple : `templates/email/password_reset.html`**
|
||
|
|
|
||
|
|
```html
|
||
|
|
<!DOCTYPE html>
|
||
|
|
<html>
|
||
|
|
<head>
|
||
|
|
<meta charset="UTF-8">
|
||
|
|
<title>Reset your Veza password</title>
|
||
|
|
</head>
|
||
|
|
<body>
|
||
|
|
<h1>Reset your password</h1>
|
||
|
|
<p>Hello {{.Username}},</p>
|
||
|
|
<p>Click here to reset: <a href="{{.ResetURL}}">Reset Password</a></p>
|
||
|
|
</body>
|
||
|
|
</html>
|
||
|
|
```
|
||
|
|
|
||
|
|
### Variables disponibles
|
||
|
|
|
||
|
|
Les variables sont passées via `templateData` dans `EnqueueEmailJobWithTemplate`.
|
||
|
|
|
||
|
|
**Template `password_reset.html`** :
|
||
|
|
- `{{.Username}}` - Nom d'utilisateur
|
||
|
|
- `{{.ResetURL}}` - URL de reset avec token
|
||
|
|
|
||
|
|
**Template `welcome.html`** :
|
||
|
|
- `{{.Username}}` - Nom d'utilisateur
|
||
|
|
- `{{.VerifyURL}}` - URL de vérification email
|
||
|
|
|
||
|
|
## 🧪 Tests
|
||
|
|
|
||
|
|
### Tests unitaires
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Tests du module email
|
||
|
|
go test ./internal/email/... -v
|
||
|
|
|
||
|
|
# Tests du job worker
|
||
|
|
go test ./internal/workers/... -v
|
||
|
|
```
|
||
|
|
|
||
|
|
### Tests d'intégration avec MailHog
|
||
|
|
|
||
|
|
1. **Démarrer MailHog** (en développement) :
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Via Docker
|
||
|
|
docker run -d -p 1025:1025 -p 8025:8025 mailhog/mailhog
|
||
|
|
|
||
|
|
# Ou installer MailHog localement
|
||
|
|
# https://github.com/mailhog/MailHog
|
||
|
|
```
|
||
|
|
|
||
|
|
2. **Configurer les variables d'environnement** :
|
||
|
|
|
||
|
|
```bash
|
||
|
|
MAILHOG_HOST=localhost
|
||
|
|
MAILHOG_PORT=1025
|
||
|
|
```
|
||
|
|
|
||
|
|
3. **Démarrer le backend** :
|
||
|
|
|
||
|
|
```bash
|
||
|
|
cd veza-backend-api
|
||
|
|
go run cmd/api/main.go
|
||
|
|
```
|
||
|
|
|
||
|
|
4. **Vérifier les emails dans MailHog** :
|
||
|
|
|
||
|
|
Ouvrir http://localhost:8025 dans votre navigateur pour voir les emails reçus.
|
||
|
|
|
||
|
|
### Test manuel : Envoyer un email de reset
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Via curl
|
||
|
|
curl -X POST http://localhost:8080/api/v1/auth/password/reset-request \
|
||
|
|
-H "Content-Type: application/json" \
|
||
|
|
-d '{"email": "test@example.com"}'
|
||
|
|
```
|
||
|
|
|
||
|
|
Vérifier dans MailHog que l'email a été reçu.
|
||
|
|
|
||
|
|
## 🔧 Configuration avancée
|
||
|
|
|
||
|
|
### Paramètres du Job Worker
|
||
|
|
|
||
|
|
Le Job Worker est configuré dans `internal/config/config.go` :
|
||
|
|
|
||
|
|
```go
|
||
|
|
config.JobWorker = workers.NewJobWorker(
|
||
|
|
config.Database.GormDB,
|
||
|
|
jobService,
|
||
|
|
logger,
|
||
|
|
100, // queueSize - Taille de la queue
|
||
|
|
3, // workers - Nombre de workers parallèles
|
||
|
|
3, // maxRetries - Nombre maximum de tentatives
|
||
|
|
config.EmailSender,
|
||
|
|
)
|
||
|
|
```
|
||
|
|
|
||
|
|
### Variables d'environnement
|
||
|
|
|
||
|
|
| Variable | Description | Défaut | Requis |
|
||
|
|
|----------|-------------|--------|--------|
|
||
|
|
| `SMTP_HOST` | Serveur SMTP | `localhost` (dev) | Production: Oui |
|
||
|
|
| `SMTP_PORT` | Port SMTP | `1025` (dev) | Production: Oui |
|
||
|
|
| `SMTP_USERNAME` | Utilisateur SMTP | - | Production: Oui |
|
||
|
|
| `SMTP_PASSWORD` | Mot de passe SMTP | - | Production: Oui |
|
||
|
|
| `SMTP_FROM` | Email expéditeur | - | Production: Oui |
|
||
|
|
| `SMTP_FROM_NAME` | Nom expéditeur | - | Non |
|
||
|
|
| `EMAIL_TEMPLATE_DIR` | Répertoire des templates | `templates/email` | Non |
|
||
|
|
| `FRONTEND_URL` | URL du frontend (pour liens) | `http://localhost:5173` | Non |
|
||
|
|
|
||
|
|
## 📊 Monitoring
|
||
|
|
|
||
|
|
### Statistiques du worker
|
||
|
|
|
||
|
|
```go
|
||
|
|
stats := jobWorker.GetStats()
|
||
|
|
// Retourne:
|
||
|
|
// - queue_size: Nombre de jobs en attente
|
||
|
|
// - workers: Nombre de workers actifs
|
||
|
|
// - max_retries: Nombre maximum de retries
|
||
|
|
```
|
||
|
|
|
||
|
|
### Logs
|
||
|
|
|
||
|
|
Le système log toutes les opérations importantes :
|
||
|
|
|
||
|
|
- **Enqueue** : `Job enqueued` (DEBUG)
|
||
|
|
- **Processing** : `Processing job` (INFO)
|
||
|
|
- **Success** : `Job executed successfully` (INFO)
|
||
|
|
- **Error** : `Job execution failed` (ERROR)
|
||
|
|
- **Retry** : `Retrying job` (INFO)
|
||
|
|
- **Final failure** : `Job permanently failed` (ERROR)
|
||
|
|
|
||
|
|
## 🐛 Dépannage
|
||
|
|
|
||
|
|
### Emails non envoyés
|
||
|
|
|
||
|
|
1. **Vérifier la configuration SMTP** :
|
||
|
|
```bash
|
||
|
|
echo $SMTP_HOST
|
||
|
|
echo $SMTP_PORT
|
||
|
|
```
|
||
|
|
|
||
|
|
2. **Vérifier les logs** :
|
||
|
|
- Chercher `Job execution failed` dans les logs
|
||
|
|
- Vérifier les erreurs SMTP
|
||
|
|
|
||
|
|
3. **Tester la connexion SMTP** :
|
||
|
|
```bash
|
||
|
|
telnet $SMTP_HOST $SMTP_PORT
|
||
|
|
```
|
||
|
|
|
||
|
|
### Template non trouvé
|
||
|
|
|
||
|
|
1. **Vérifier le chemin** :
|
||
|
|
```bash
|
||
|
|
ls -la templates/email/
|
||
|
|
```
|
||
|
|
|
||
|
|
2. **Vérifier la variable d'environnement** :
|
||
|
|
```bash
|
||
|
|
echo $EMAIL_TEMPLATE_DIR
|
||
|
|
```
|
||
|
|
|
||
|
|
3. **Vérifier les logs** :
|
||
|
|
- Chercher `Failed to read template file` dans les logs
|
||
|
|
|
||
|
|
### Queue pleine
|
||
|
|
|
||
|
|
Si la queue est pleine, les nouveaux jobs sont rejetés avec un warning :
|
||
|
|
```
|
||
|
|
Job queue full, dropping job
|
||
|
|
```
|
||
|
|
|
||
|
|
**Solution** : Augmenter la taille de la queue dans `config.go` :
|
||
|
|
```go
|
||
|
|
workers.NewJobWorker(..., 200, ...) // Augmenter queueSize
|
||
|
|
```
|
||
|
|
|
||
|
|
## 🔐 Sécurité
|
||
|
|
|
||
|
|
1. **Secrets SMTP** : Ne jamais commiter les credentials SMTP dans le code
|
||
|
|
2. **Validation email** : Les emails sont validés avant envoi
|
||
|
|
3. **Rate limiting** : Le système de rate limiting s'applique aussi aux endpoints qui envoient des emails
|
||
|
|
4. **Logs** : Les emails ne sont jamais loggés en clair (seulement les métadonnées)
|
||
|
|
|
||
|
|
## 🚀 Production
|
||
|
|
|
||
|
|
### Checklist avant déploiement
|
||
|
|
|
||
|
|
- [ ] Variables SMTP configurées et testées
|
||
|
|
- [ ] Templates email créés et testés
|
||
|
|
- [ ] MailHog désactivé (pas de fallback en prod)
|
||
|
|
- [ ] Monitoring configuré (logs, métriques)
|
||
|
|
- [ ] Tests d'intégration passés
|
||
|
|
- [ ] Documentation à jour
|
||
|
|
|
||
|
|
### Recommandations
|
||
|
|
|
||
|
|
1. **Utiliser un service SMTP professionnel** :
|
||
|
|
- SendGrid
|
||
|
|
- Mailgun
|
||
|
|
- AWS SES
|
||
|
|
- Postmark
|
||
|
|
|
||
|
|
2. **Monitoring** :
|
||
|
|
- Surveiller la taille de la queue
|
||
|
|
- Alerter sur les échecs répétés
|
||
|
|
- Tracer les temps d'envoi
|
||
|
|
|
||
|
|
3. **Scalabilité** :
|
||
|
|
- Augmenter le nombre de workers si nécessaire
|
||
|
|
- Considérer une queue persistante (Redis, RabbitMQ) pour haute charge
|
||
|
|
|
||
|
|
## 📚 Références
|
||
|
|
|
||
|
|
- [Go SMTP Package](https://pkg.go.dev/net/smtp)
|
||
|
|
- [Go Templates](https://pkg.go.dev/html/template)
|
||
|
|
- [MailHog Documentation](https://github.com/mailhog/MailHog)
|
||
|
|
|
||
|
|
## 🔄 Évolutions futures
|
||
|
|
|
||
|
|
- [ ] Support de plusieurs providers SMTP (SendGrid, Mailgun)
|
||
|
|
- [ ] Queue persistante (Redis, RabbitMQ)
|
||
|
|
- [ ] Dead letter queue pour les échecs définitifs
|
||
|
|
- [ ] Métriques Prometheus
|
||
|
|
- [ ] Dashboard de monitoring
|
||
|
|
- [ ] Support des pièces jointes
|
||
|
|
- [ ] Support du format texte + HTML
|
||
|
|
|