/** * Service d'envoi d'emails pour les formations * Utilise le système de notification Manus pour envoyer des emails */ import { generateFormationICS } from "./icsGenerator"; import { sendEmail as sendEmailViaService, isEmailServiceConfigured } from "./_core/emailSender"; import { generateEmailFromTemplate } from "./emailTemplateGenerator"; import { EmailVariables } from "./emailTemplateUtils"; interface EmailParams { to: string; subject: string; html: string; attachments?: Array<{ filename: string; content: string; contentType: string; }>; } /** * Envoie un email via le service d'envoi configuré * Utilise Resend si RESEND_API_KEY est configuré, sinon simule l'envoi */ async function sendEmail(params: EmailParams): Promise { return await sendEmailViaService(params); } /** * Template HTML de base pour les emails (avec template personnalisé) */ async function getEmailTemplate( content: string, templateType: string = 'inscription', variables?: EmailVariables ): Promise { return await generateEmailFromTemplate(templateType, content, variables); } /** * Envoie un email de confirmation d'inscription avec invitations Outlook pour toutes les dates */ export async function sendInscriptionConfirmation(params: { apprenantEmail: string; apprenantNom: string; apprenantPrenom: string; apprenantFonction: string; formationNom: string; sequenceNom: string; dates: Array<{ dateDebut: Date; dateFin: Date; ordre: number }>; lieu: string; statut: 'confirmee' | 'liste_attente'; }): Promise { const isConfirmed = params.statut === 'confirmee'; const fonctionLabel = params.apprenantFonction === 'directeur' ? 'Directeur' : params.apprenantFonction === 'chef_service' ? 'Chef de service' : 'Autre'; // Générer la liste des dates const datesHTML = params.dates.map(date => `
Date ${date.ordre} :
Du ${date.dateDebut.toLocaleDateString('fr-FR', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit' })}
au ${date.dateFin.toLocaleDateString('fr-FR', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit' })}
`).join(''); const content = `

Confirmation d'inscription

Bonjour ${fonctionLabel} ${params.apprenantPrenom} ${params.apprenantNom},

${isConfirmed ? '

Votre inscription a été confirmée !

' : '

Vous avez été ajouté à la liste d\'attente.

' }

Détails de la formation

Formation : ${params.formationNom}

Séquence : ${params.sequenceNom}

Lieu : ${params.lieu}

Dates de formation (${params.dates.length} séance${params.dates.length > 1 ? 's' : ''}) :

${datesHTML}
${isConfirmed ? `

Des invitations Outlook sont jointes à cet email pour chaque date de formation. Merci de les ajouter à votre calendrier pour bloquer votre agenda.

Important : Les inscriptions seront bloquées 15 jours avant le début de la séquence. Après cette date, aucune modification ne sera possible.

` : '

Nous vous contacterons dès qu\'une place se libère.

' }

À bientôt pour cette formation !

`; // Générer une invitation ICS pour chaque date const attachments = isConfirmed ? params.dates.map((date, index) => ({ filename: `invitation_date_${date.ordre}.ics`, content: generateFormationICS({ formationNom: params.formationNom, sessionNom: `${params.sequenceNom} - Date ${date.ordre}`, dateDebut: date.dateDebut, dateFin: date.dateFin, lieu: params.lieu, apprenantNom: params.apprenantNom, apprenantPrenom: params.apprenantPrenom, apprenantEmail: params.apprenantEmail, }), contentType: 'text/calendar', })) : undefined; // Préparer les variables pour le remplacement (avec alias pour compatibilité) const variables: EmailVariables = { nomApprenant: params.apprenantNom, prenomApprenant: params.apprenantPrenom, nomFormation: params.formationNom, nomSequence: params.sequenceNom, dateDebut: params.dates[0]?.dateDebut.toLocaleDateString('fr-FR') || '', dateFin: params.dates[params.dates.length - 1]?.dateFin.toLocaleDateString('fr-FR') || '', lieu: params.lieu, datesHTML: datesHTML, // HTML formaté de toutes les dates // Alias pour compatibilité avec les templates utilisant les noms courts nom: params.apprenantNom, prenom: params.apprenantPrenom, formation: params.formationNom, sequence: params.sequenceNom, }; return sendEmail({ to: params.apprenantEmail, subject: isConfirmed ? `Confirmation d'inscription - ${params.formationNom}` : `Liste d'attente - ${params.formationNom}`, html: await getEmailTemplate(content, 'inscription', variables), attachments, }); } /** * Envoie un email teaser pour une séquence */ export async function sendTeaserEmail(params: { apprenantEmail: string; apprenantPrenom: string; apprenantNom: string; apprenantFonction: string; formationNom: string; sequenceNom: string; dates: Array<{ dateDebut: Date; dateFin: Date; ordre: number }>; lieu?: string; formateur?: string; }): Promise { const fonctionLabel = params.apprenantFonction === 'directeur' ? 'Directeur' : params.apprenantFonction === 'chef_service' ? 'Chef de service' : ''; const salutation = fonctionLabel ? `${fonctionLabel} ${params.apprenantPrenom} ${params.apprenantNom}` : params.apprenantPrenom; const datesHTML = params.dates.map(date => `
Date ${date.ordre} : ${date.dateDebut.toLocaleDateString('fr-FR', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' })}
`).join(''); const content = `

Votre formation approche !

Bonjour ${salutation},

Nous sommes ravis de vous accueillir prochainement pour la formation ${params.formationNom}.

Séquence : ${params.sequenceNom}

Dates :

${datesHTML} ${params.lieu ? `

Lieu : ${params.lieu}

` : ''} ${params.formateur ? `

Formateur : ${params.formateur}

` : ''}

Préparez-vous à vivre une expérience enrichissante qui vous permettra de développer vos compétences managériales.

À très bientôt !

`; const variables = { nomApprenant: params.apprenantNom, prenomApprenant: params.apprenantPrenom, nomFormation: params.formationNom, nomSequence: params.sequenceNom, dateDebut: params.dates[0]?.dateDebut.toLocaleDateString('fr-FR') || '', dateFin: params.dates[params.dates.length - 1]?.dateFin.toLocaleDateString('fr-FR') || '', datesHTML: datesHTML, // Ajouter le HTML des dates lieu: params.lieu || '', formateur: params.formateur || '', }; return sendEmail({ to: params.apprenantEmail, subject: `Votre formation ${params.formationNom} approche !`, html: await getEmailTemplate(content, 'teaser', variables), }); } /** * Envoie un email de rappel J-7 */ export async function sendRappelJ7Email(params: { apprenantEmail: string; apprenantPrenom: string; apprenantNom: string; apprenantFonction: string; formationNom: string; sequenceNom: string; dates: Array<{ dateDebut: Date; dateFin: Date; ordre: number }>; lieu: string; }): Promise { const fonctionLabel = params.apprenantFonction === 'directeur' ? 'Directeur' : params.apprenantFonction === 'chef_service' ? 'Chef de service' : ''; const salutation = fonctionLabel ? `${fonctionLabel} ${params.apprenantPrenom} ${params.apprenantNom}` : params.apprenantPrenom; const datesHTML = params.dates.map(date => `
Date ${date.ordre} :
${date.dateDebut.toLocaleDateString('fr-FR', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit' })}
`).join(''); const content = `

Rappel : Votre formation dans 7 jours

Bonjour ${salutation},

Nous vous rappelons que votre formation ${params.formationNom} commence dans 7 jours.

Informations pratiques

Séquence : ${params.sequenceNom}

Lieu : ${params.lieu}

Dates :

${datesHTML}

Merci de vous présenter à l'heure indiquée.

Si vous avez des questions, n'hésitez pas à contacter le service RH.

À très bientôt !

`; const variables = { nomApprenant: params.apprenantNom, prenomApprenant: params.apprenantPrenom, nomFormation: params.formationNom, nomSequence: params.sequenceNom, dateDebut: params.dates[0]?.dateDebut.toLocaleDateString('fr-FR') || '', dateFin: params.dates[params.dates.length - 1]?.dateFin.toLocaleDateString('fr-FR') || '', datesHTML: datesHTML, // Ajouter le HTML des dates lieu: params.lieu, }; return sendEmail({ to: params.apprenantEmail, subject: `Rappel J-7 : ${params.formationNom}`, html: await getEmailTemplate(content, 'rappel', variables), }); } /** * Envoie un email de rappel J-1 à un apprenant */ export async function sendRappelJ1Email(params: { apprenantEmail: string; apprenantNom: string; apprenantPrenom: string; apprenantFonction: string; formationNom: string; sequenceNom: string; dates: Array<{ dateDebut: Date; dateFin: Date; ordre: number }>; lieu?: string; formateur?: string; }): Promise { const fonctionLabel = params.apprenantFonction === 'directeur' ? 'Directeur' : params.apprenantFonction === 'chef_service' ? 'Chef de service' : ''; const salutation = fonctionLabel ? `${fonctionLabel} ${params.apprenantPrenom} ${params.apprenantNom}` : params.apprenantPrenom; const datesHTML = params.dates.map(date => `
Date ${date.ordre} : ${date.dateDebut.toLocaleDateString('fr-FR', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit' })} - ${date.dateFin.toLocaleDateString('fr-FR', { hour: '2-digit', minute: '2-digit' })}
`).join(''); const content = `

Rappel : Votre formation commence demain !

Bonjour ${salutation},

Nous vous rappelons que votre formation ${params.formationNom} commence demain.

Informations pratiques

Séquence : ${params.sequenceNom}

${params.lieu ? `

Lieu : ${params.lieu}

` : ''} ${params.formateur ? `

Formateur : ${params.formateur}

` : ''}

Dates :

${datesHTML}

Merci de vous présenter à l'heure indiquée.

N'oubliez pas d'apporter le matériel nécessaire.

Si vous avez des questions de dernière minute, n'hésitez pas à contacter le service RH.

À demain !

`; const variables = { nomApprenant: params.apprenantNom, prenomApprenant: params.apprenantPrenom, nomFormation: params.formationNom, nomSequence: params.sequenceNom, dateDebut: params.dates[0]?.dateDebut.toLocaleDateString('fr-FR') || '', dateFin: params.dates[params.dates.length - 1]?.dateFin.toLocaleDateString('fr-FR') || '', datesHTML: datesHTML, // Ajouter le HTML des dates lieu: params.lieu || '', formateur: params.formateur || '', }; return sendEmail({ to: params.apprenantEmail, subject: `Rappel J-1 : ${params.formationNom} - C'est demain !`, html: await getEmailTemplate(content, 'rappel', variables), }); } /** * Envoie des emails groupés à tous les inscrits d'une séquence */ export async function sendGroupEmail(params: { recipients: Array<{ email: string; prenom: string; nom: string; fonction: string }>; formationNom: string; sequenceNom: string; type: 'teaser' | 'rappel' | 'rappel_j1'; dates: Array<{ dateDebut: Date; dateFin: Date; ordre: number }>; lieu?: string; formateur?: string; }): Promise<{ sent: number; failed: number }> { let sent = 0; let failed = 0; for (const recipient of params.recipients) { try { if (params.type === 'teaser') { await sendTeaserEmail({ apprenantEmail: recipient.email, apprenantPrenom: recipient.prenom, apprenantNom: recipient.nom, apprenantFonction: recipient.fonction, formationNom: params.formationNom, sequenceNom: params.sequenceNom, dates: params.dates, lieu: params.lieu, formateur: params.formateur, }); } else if (params.type === 'rappel') { await sendRappelJ7Email({ apprenantEmail: recipient.email, apprenantPrenom: recipient.prenom, apprenantNom: recipient.nom, apprenantFonction: recipient.fonction, formationNom: params.formationNom, sequenceNom: params.sequenceNom, dates: params.dates, lieu: params.lieu || '', }); } else { // rappel_j1 await sendRappelJ1Email({ apprenantEmail: recipient.email, apprenantPrenom: recipient.prenom, apprenantNom: recipient.nom, apprenantFonction: recipient.fonction, formationNom: params.formationNom, sequenceNom: params.sequenceNom, dates: params.dates, lieu: params.lieu, formateur: params.formateur, }); } sent++; } catch (error) { console.error(`Erreur envoi email à ${recipient.email}:`, error); failed++; } } return { sent, failed }; } /** * Envoie un email de réinitialisation de mot de passe */ export async function sendPasswordResetEmail(params: { apprenantEmail: string; apprenantNom: string; apprenantPrenom: string; resetLink: string; }): Promise { const content = `

Réinitialisation de mot de passe

Bonjour ${params.apprenantPrenom} ${params.apprenantNom},

Vous avez demandé la réinitialisation de votre mot de passe pour votre compte Manager Itinova.

Cliquez sur le bouton ci-dessous pour créer un nouveau mot de passe :

Ou copiez ce lien dans votre navigateur :

${params.resetLink}

⚠️ Important :

  • Ce lien est valide pendant 24 heures seulement
  • Il ne peut être utilisé qu'une seule fois
  • Si vous n'avez pas demandé cette réinitialisation, ignorez cet email

Pour toute question, contactez le service RH.

`; return sendEmail({ to: params.apprenantEmail, subject: 'Réinitialisation de votre mot de passe - Manager Itinova', html: await getEmailTemplate(content, 'reset_password'), }); }