Checkpoint: Corrections apportées :

- Ajout du support SMTP pour l'envoi d'emails (sans dépendre de Resend)
- Correction de l'affichage du statut pour montrer "SMTP Direct" au lieu de "Resend"
- Ajout d'alertes spécifiques pour la configuration SMTP
- Correction de la fonction upsertEmailConfig pour mettre à jour au lieu de créer une nouvelle configuration
- Correction du bug d'enregistrement des champs SMTP dans la base de données
- Mise à jour forcée du provider à "smtp" dans la base de données
This commit is contained in:
Manus Sandbox
2025-11-28 11:05:46 -05:00
parent 426337a6d5
commit cdb77b4f38
9 changed files with 209 additions and 11 deletions

View File

@@ -0,0 +1,27 @@
{
"query": "SELECT * FROM emailConfig LIMIT 1;",
"command": "mysql --batch --raw --column-names --default-character-set=utf8mb4 --host gateway02.us-east-1.prod.aws.tidbcloud.com --port 4000 --user 4CrrYuB5tme73Qo.root --database 7PAT67UmWoxv8vwp8Bbcv6 --execute SELECT * FROM emailConfig LIMIT 1;",
"rows": [
{
"id": "1",
"provider": "resend",
"apiKey": "re_86E4CTUv_JLJQQQh81PvbaX6dMrshNjHt",
"fromEmail": "o.pareige@itinova.org",
"fromName": "Formation Manager Itinova",
"mode": "simulation",
"domainVerified": "0",
"active": "0",
"createdAt": "2025-11-18 07:16:34",
"updatedAt": "2025-11-28 11:49:52",
"smtpHost": "NULL",
"smtpPort": "NULL",
"smtpSecure": "tls",
"smtpUser": "NULL",
"smtpPassword": "NULL"
}
],
"messages": [],
"stdout": "id\tprovider\tapiKey\tfromEmail\tfromName\tmode\tdomainVerified\tactive\tcreatedAt\tupdatedAt\tsmtpHost\tsmtpPort\tsmtpSecure\tsmtpUser\tsmtpPassword\n1\tresend\tre_86E4CTUv_JLJQQQh81PvbaX6dMrshNjHt\to.pareige@itinova.org\tFormation Manager Itinova\tsimulation\t0\t0\t2025-11-18 07:16:34\t2025-11-28 11:49:52\tNULL\tNULL\ttls\tNULL\tNULL\n",
"stderr": "",
"execution_time_ms": 592
}

View File

@@ -0,0 +1,21 @@
{
"query": "SELECT id, mode, provider, fromName, fromEmail, smtpHost, smtpPort, smtpSecure, smtpUser FROM emailConfig LIMIT 1;",
"command": "mysql --batch --raw --column-names --default-character-set=utf8mb4 --host gateway02.us-east-1.prod.aws.tidbcloud.com --port 4000 --user 4CrrYuB5tme73Qo.root --database 7PAT67UmWoxv8vwp8Bbcv6 --execute SELECT id, mode, provider, fromName, fromEmail, smtpHost, smtpPort, smtpSecure, smtpUser FROM emailConfig LIMIT 1;",
"rows": [
{
"id": "1",
"mode": "simulation",
"provider": "resend",
"fromName": "Formation Manager Itinova",
"fromEmail": "o.pareige@itinova.org",
"smtpHost": "NULL",
"smtpPort": "NULL",
"smtpSecure": "tls",
"smtpUser": "NULL"
}
],
"messages": [],
"stdout": "id\tmode\tprovider\tfromName\tfromEmail\tsmtpHost\tsmtpPort\tsmtpSecure\tsmtpUser\n1\tsimulation\tresend\tFormation Manager Itinova\to.pareige@itinova.org\tNULL\tNULL\ttls\tNULL\n",
"stderr": "",
"execution_time_ms": 53
}

View File

@@ -0,0 +1,9 @@
{
"query": "UPDATE emailConfig SET provider = 'smtp' WHERE id = 1;",
"command": "mysql --batch --raw --column-names --default-character-set=utf8mb4 --host gateway02.us-east-1.prod.aws.tidbcloud.com --port 4000 --user 4CrrYuB5tme73Qo.root --database 7PAT67UmWoxv8vwp8Bbcv6 --execute UPDATE emailConfig SET provider = 'smtp' WHERE id = 1;",
"rows": [],
"messages": [],
"stdout": "",
"stderr": "",
"execution_time_ms": 53
}

View File

@@ -0,0 +1,58 @@
{
"query": "SELECT id, provider, mode, active, smtpHost, smtpPort FROM emailConfig ORDER BY id DESC;",
"command": "mysql --batch --raw --column-names --default-character-set=utf8mb4 --host gateway02.us-east-1.prod.aws.tidbcloud.com --port 4000 --user 4CrrYuB5tme73Qo.root --database 7PAT67UmWoxv8vwp8Bbcv6 --execute SELECT id, provider, mode, active, smtpHost, smtpPort FROM emailConfig ORDER BY id DESC;",
"rows": [
{
"id": "90002",
"provider": "",
"mode": "production",
"active": "1",
"smtpHost": "smtp.itinova.org",
"smtpPort": "587"
},
{
"id": "90001",
"provider": "smtp",
"mode": "simulation",
"active": "0",
"smtpHost": "smtp.itinova.org",
"smtpPort": "587"
},
{
"id": "60002",
"provider": "smtp",
"mode": "simulation",
"active": "0",
"smtpHost": "NULL",
"smtpPort": "NULL"
},
{
"id": "60001",
"provider": "smtp",
"mode": "simulation",
"active": "0",
"smtpHost": "NULL",
"smtpPort": "NULL"
},
{
"id": "30001",
"provider": "smtp",
"mode": "simulation",
"active": "0",
"smtpHost": "NULL",
"smtpPort": "NULL"
},
{
"id": "1",
"provider": "smtp",
"mode": "simulation",
"active": "0",
"smtpHost": "NULL",
"smtpPort": "NULL"
}
],
"messages": [],
"stdout": "id\tprovider\tmode\tactive\tsmtpHost\tsmtpPort\n90002\t\tproduction\t1\tsmtp.itinova.org\t587\n90001\tsmtp\tsimulation\t0\tsmtp.itinova.org\t587\n60002\tsmtp\tsimulation\t0\tNULL\tNULL\n60001\tsmtp\tsimulation\t0\tNULL\tNULL\n30001\tsmtp\tsimulation\t0\tNULL\tNULL\n1\tsmtp\tsimulation\t0\tNULL\tNULL\n",
"stderr": "",
"execution_time_ms": 58
}

View File

@@ -0,0 +1,9 @@
{
"query": "UPDATE emailConfig SET provider = 'smtp' WHERE active = true;",
"command": "mysql --batch --raw --column-names --default-character-set=utf8mb4 --host gateway02.us-east-1.prod.aws.tidbcloud.com --port 4000 --user 4CrrYuB5tme73Qo.root --database 7PAT67UmWoxv8vwp8Bbcv6 --execute UPDATE emailConfig SET provider = 'smtp' WHERE active = true;",
"rows": [],
"messages": [],
"stdout": "",
"stderr": "",
"execution_time_ms": 62
}

View File

@@ -0,0 +1,27 @@
{
"query": "SELECT * FROM emailConfig WHERE active = true LIMIT 1;",
"command": "mysql --batch --raw --column-names --default-character-set=utf8mb4 --host gateway02.us-east-1.prod.aws.tidbcloud.com --port 4000 --user 4CrrYuB5tme73Qo.root --database 7PAT67UmWoxv8vwp8Bbcv6 --execute SELECT * FROM emailConfig WHERE active = true LIMIT 1;",
"rows": [
{
"id": "90002",
"provider": "smtp",
"apiKey": "re_86E4CTUv_JLJQQQh81PvbaX6dMrshNjHt",
"fromEmail": "o.pareige@itinova.org",
"fromName": "Formation Manager Itinova",
"mode": "production",
"domainVerified": "0",
"active": "1",
"createdAt": "2025-11-28 15:54:56",
"updatedAt": "2025-11-28 16:04:16",
"smtpHost": "smtp.itinova.org",
"smtpPort": "587",
"smtpSecure": "tls",
"smtpUser": "o.pareige@itinova.org",
"smtpPassword": "LEpetitchatestmort69-"
}
],
"messages": [],
"stdout": "id\tprovider\tapiKey\tfromEmail\tfromName\tmode\tdomainVerified\tactive\tcreatedAt\tupdatedAt\tsmtpHost\tsmtpPort\tsmtpSecure\tsmtpUser\tsmtpPassword\n90002\tsmtp\tre_86E4CTUv_JLJQQQh81PvbaX6dMrshNjHt\to.pareige@itinova.org\tFormation Manager Itinova\tproduction\t0\t1\t2025-11-28 15:54:56\t2025-11-28 16:04:16\tsmtp.itinova.org\t587\ttls\to.pareige@itinova.org\tLEpetitchatestmort69-\n",
"stderr": "",
"execution_time_ms": 51
}

View File

@@ -126,7 +126,9 @@ export default function AdminEmailConfig() {
<p className="text-sm text-muted-foreground">
{formData.mode === "simulation"
? "Les emails sont simulés et envoyés comme notifications"
: "Les emails sont envoyés via Resend"}
: formData.provider === "smtp"
? "Les emails sont envoyés via SMTP Direct"
: "Les emails sont envoyés via Resend"}
</p>
</div>
<div className={`px-3 py-1 rounded-full text-sm font-medium ${
@@ -138,7 +140,7 @@ export default function AdminEmailConfig() {
</div>
</div>
{formData.apiKey && (
{formData.provider === "resend" && formData.apiKey && (
<Alert>
<CheckCircle2 className="h-4 w-4" />
<AlertDescription>
@@ -147,11 +149,29 @@ export default function AdminEmailConfig() {
</Alert>
)}
{!formData.apiKey && (
{formData.provider === "smtp" && formData.smtpHost && formData.smtpUser && (
<Alert>
<CheckCircle2 className="h-4 w-4" />
<AlertDescription>
Configuration SMTP active ({formData.smtpHost}:{formData.smtpPort})
</AlertDescription>
</Alert>
)}
{formData.provider === "resend" && !formData.apiKey && (
<Alert>
<AlertCircle className="h-4 w-4" />
<AlertDescription>
Aucune clé API configurée. Les emails seront simulés.
Aucune clé API Resend configurée. Les emails seront simulés.
</AlertDescription>
</Alert>
)}
{formData.provider === "smtp" && (!formData.smtpHost || !formData.smtpUser) && (
<Alert>
<AlertCircle className="h-4 w-4" />
<AlertDescription>
Configuration SMTP incomplète. Les emails seront simulés.
</AlertDescription>
</Alert>
)}

View File

@@ -692,14 +692,29 @@ export async function upsertEmailConfig(data: InsertEmailConfig) {
const db = await getDb();
if (!db) return;
// Désactiver toutes les configurations existantes
await db.update(emailConfig).set({ active: false });
// Vérifier s'il existe déjà une configuration active
const existing = await db
.select()
.from(emailConfig)
.where(eq(emailConfig.active, true))
.limit(1);
// Créer la nouvelle configuration
await db.insert(emailConfig).values({
...data,
active: true,
});
if (existing.length > 0) {
// Mettre à jour la configuration existante
await db
.update(emailConfig)
.set({
...data,
updatedAt: new Date(),
})
.where(eq(emailConfig.id, existing[0].id));
} else {
// Créer une nouvelle configuration
await db.insert(emailConfig).values({
...data,
active: true,
});
}
}
/**

12
todo.md
View File

@@ -744,3 +744,15 @@
- [x] Vérifier les procédures tRPC emailConfig
- [x] Corriger la mutation upsert pour supporter les champs SMTP
- [x] Tester l'enregistrement de la configuration SMTP (champs ajoutés dans l'input tRPC)
## Bug email de test envoyé à la mauvaise adresse
- [x] Vérifier la fonction sendEmail dans emailSender.ts
- [x] Vérifier la fonction sendEmailViaSMTP dans smtpSender.ts
- [x] Vérifier pourquoi le mode production ne peut pas être activé (le switch fonctionne)
- [x] Corriger l'affichage du statut pour montrer SMTP au lieu de Resend
- [x] Ajouter des alertes spécifiques pour SMTP
- [x] Corriger la fonction upsertEmailConfig pour mettre à jour au lieu de créer
- [x] Forcer la mise à jour du provider dans la base de données
- [x] Vérifier que la configuration SMTP est bien enregistrée (provider=smtp)
- [ ] Tester l'envoi d'email de test en mode production (après hard refresh)