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:
27
.manus/db/db-query-1764345424841.json
Normal file
27
.manus/db/db-query-1764345424841.json
Normal 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
|
||||||
|
}
|
||||||
21
.manus/db/db-query-1764345617656.json
Normal file
21
.manus/db/db-query-1764345617656.json
Normal 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
|
||||||
|
}
|
||||||
9
.manus/db/db-query-1764345693447.json
Normal file
9
.manus/db/db-query-1764345693447.json
Normal 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
|
||||||
|
}
|
||||||
58
.manus/db/db-query-1764345842345.json
Normal file
58
.manus/db/db-query-1764345842345.json
Normal 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
|
||||||
|
}
|
||||||
9
.manus/db/db-query-1764345856570.json
Normal file
9
.manus/db/db-query-1764345856570.json
Normal 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
|
||||||
|
}
|
||||||
27
.manus/db/db-query-1764345891283.json
Normal file
27
.manus/db/db-query-1764345891283.json
Normal 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
|
||||||
|
}
|
||||||
@@ -126,6 +126,8 @@ export default function AdminEmailConfig() {
|
|||||||
<p className="text-sm text-muted-foreground">
|
<p className="text-sm text-muted-foreground">
|
||||||
{formData.mode === "simulation"
|
{formData.mode === "simulation"
|
||||||
? "Les emails sont simulés et envoyés comme notifications"
|
? "Les emails sont simulés et envoyés comme notifications"
|
||||||
|
: formData.provider === "smtp"
|
||||||
|
? "Les emails sont envoyés via SMTP Direct"
|
||||||
: "Les emails sont envoyés via Resend"}
|
: "Les emails sont envoyés via Resend"}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -138,7 +140,7 @@ export default function AdminEmailConfig() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{formData.apiKey && (
|
{formData.provider === "resend" && formData.apiKey && (
|
||||||
<Alert>
|
<Alert>
|
||||||
<CheckCircle2 className="h-4 w-4" />
|
<CheckCircle2 className="h-4 w-4" />
|
||||||
<AlertDescription>
|
<AlertDescription>
|
||||||
@@ -147,11 +149,29 @@ export default function AdminEmailConfig() {
|
|||||||
</Alert>
|
</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>
|
<Alert>
|
||||||
<AlertCircle className="h-4 w-4" />
|
<AlertCircle className="h-4 w-4" />
|
||||||
<AlertDescription>
|
<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>
|
</AlertDescription>
|
||||||
</Alert>
|
</Alert>
|
||||||
)}
|
)}
|
||||||
|
|||||||
21
server/db.ts
21
server/db.ts
@@ -692,15 +692,30 @@ export async function upsertEmailConfig(data: InsertEmailConfig) {
|
|||||||
const db = await getDb();
|
const db = await getDb();
|
||||||
if (!db) return;
|
if (!db) return;
|
||||||
|
|
||||||
// Désactiver toutes les configurations existantes
|
// Vérifier s'il existe déjà une configuration active
|
||||||
await db.update(emailConfig).set({ active: false });
|
const existing = await db
|
||||||
|
.select()
|
||||||
|
.from(emailConfig)
|
||||||
|
.where(eq(emailConfig.active, true))
|
||||||
|
.limit(1);
|
||||||
|
|
||||||
// Créer la nouvelle configuration
|
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({
|
await db.insert(emailConfig).values({
|
||||||
...data,
|
...data,
|
||||||
active: true,
|
active: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Met à jour la configuration email
|
* Met à jour la configuration email
|
||||||
|
|||||||
12
todo.md
12
todo.md
@@ -744,3 +744,15 @@
|
|||||||
- [x] Vérifier les procédures tRPC emailConfig
|
- [x] Vérifier les procédures tRPC emailConfig
|
||||||
- [x] Corriger la mutation upsert pour supporter les champs SMTP
|
- [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)
|
- [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)
|
||||||
|
|||||||
Reference in New Issue
Block a user