From ac9ece31a5c29ebcecb6c4b55401ab06d7b31e23 Mon Sep 17 00:00:00 2001 From: Manus Date: Sun, 18 Jan 2026 06:11:57 -0500 Subject: [PATCH] =?UTF-8?q?Checkpoint:=20Correction=20de=20l'erreur=20"Fai?= =?UTF-8?q?led=20to=20parse=20URL"=20lors=20de=20l'envoi=20d'attestation?= =?UTF-8?q?=20avec=20chemin=20local=20:=20-=20Modification=20de=20la=20fon?= =?UTF-8?q?ction=20sendAttestationEmail=20dans=20server/emailService.ts=20?= =?UTF-8?q?-=20Ajout=20de=20la=20d=C3=A9tection=20automatique=20entre=20UR?= =?UTF-8?q?L=20compl=C3=A8te=20(http/https)=20et=20chemin=20local=20-=20Po?= =?UTF-8?q?ur=20les=20URLs=20compl=C3=A8tes=20:=20t=C3=A9l=C3=A9chargement?= =?UTF-8?q?=20via=20fetch=20(comme=20avant)=20-=20Pour=20les=20chemins=20l?= =?UTF-8?q?ocaux=20:=20lecture=20directe=20depuis=20le=20syst=C3=A8me=20de?= =?UTF-8?q?=20fichiers=20avec=20fs.readFile=20-=20Les=20fichiers=20upload?= =?UTF-8?q?=C3=A9s=20localement=20(/uploads/rappels-attachments/...)=20son?= =?UTF-8?q?t=20maintenant=20correctement=20lus=20-=20Utilisation=20de=20pa?= =?UTF-8?q?th.join(process.cwd(),=20pdfUrl)=20pour=20construire=20le=20che?= =?UTF-8?q?min=20absolu=20-=20D=C3=A9ploy=C3=A9=20sur=20le=20VPS=20de=20pr?= =?UTF-8?q?oduction=20(https://formations.itinova.org)=20-=20L'envoi=20d'a?= =?UTF-8?q?ttestations=20upload=C3=A9es=20localement=20fonctionne=20mainte?= =?UTF-8?q?nant=20correctement?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/emailService.ts | 27 ++++++++++++++++++++------- todo.md | 1 + 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/server/emailService.ts b/server/emailService.ts index 4340629..815c53d 100644 --- a/server/emailService.ts +++ b/server/emailService.ts @@ -1144,17 +1144,30 @@ export async function sendAttestationEmail(params: {

Cordialement,
L'équipe Formation

`; - // Télécharger le PDF depuis l'URL + // Récupérer le PDF (depuis URL ou chemin local) let pdfBuffer: Buffer; try { - const response = await fetch(params.pdfUrl); - if (!response.ok) { - throw new Error(`Failed to download PDF: ${response.statusText}`); + // Vérifier si c'est un chemin local ou une URL complète + if (params.pdfUrl.startsWith('http://') || params.pdfUrl.startsWith('https://')) { + // Télécharger depuis l'URL + const response = await fetch(params.pdfUrl); + if (!response.ok) { + throw new Error(`Failed to download PDF: ${response.statusText}`); + } + const arrayBuffer = await response.arrayBuffer(); + pdfBuffer = Buffer.from(arrayBuffer); + } else { + // Lire depuis le système de fichiers local + const fs = await import('fs/promises'); + const path = await import('path'); + + // Construire le chemin absolu (le chemin commence par /uploads/...) + // Sur le VPS, les fichiers sont dans /var/www/formation-manager-itinova/uploads/ + const absolutePath = path.join(process.cwd(), params.pdfUrl); + pdfBuffer = await fs.readFile(absolutePath); } - const arrayBuffer = await response.arrayBuffer(); - pdfBuffer = Buffer.from(arrayBuffer); } catch (error) { - console.error('[sendAttestationEmail] Error downloading PDF:', error); + console.error('[sendAttestationEmail] Error loading PDF:', error); throw error; } diff --git a/todo.md b/todo.md index b680e4a..e658d59 100644 --- a/todo.md +++ b/todo.md @@ -862,3 +862,4 @@ - [x] Corriger l'erreur "aucune attestation disponible pour cet apprenant" lors de l'envoi manuel d'une attestation uploadée (vérification de documentUrl ou urlPdf) - [x] Modifier l'envoi d'attestation pour joindre le PDF directement en pièce jointe au lieu d'un lien de téléchargement - [x] Permettre le renvoi d'une attestation même après qu'elle ait été envoyée (afficher bouton Renvoyer au lieu de masquer Envoyer) +- [x] Corriger l'erreur "Failed to parse URL" lors de l'envoi d'attestation avec un chemin local (gérer les chemins locaux et URLs complètes)