Files
formation-manager-itinova/server/emailService.ts

284 lines
8.4 KiB
TypeScript

/**
* Service d'envoi d'emails pour les formations
* Note: Ce module utilise console.log pour simuler l'envoi d'emails
* Dans un environnement de production, intégrer un service SMTP réel
*/
import { generateFormationICS } from "./icsGenerator";
interface EmailParams {
to: string;
subject: string;
html: string;
attachments?: Array<{
filename: string;
content: string;
contentType: string;
}>;
}
/**
* Simule l'envoi d'un email (à remplacer par un vrai service SMTP)
*/
async function sendEmail(params: EmailParams): Promise<boolean> {
console.log('=== EMAIL SIMULÉ ===');
console.log('To:', params.to);
console.log('Subject:', params.subject);
console.log('HTML:', params.html.substring(0, 200) + '...');
if (params.attachments) {
console.log('Attachments:', params.attachments.map(a => a.filename).join(', '));
}
console.log('===================');
// Simuler un délai d'envoi
await new Promise(resolve => setTimeout(resolve, 100));
return true;
}
/**
* Template HTML de base pour les emails
*/
function getEmailTemplate(content: string): string {
return `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
.container { max-width: 600px; margin: 0 auto; padding: 20px; }
.header { background-color: #2563eb; color: white; padding: 20px; text-align: center; }
.content { background-color: #f9fafb; padding: 30px; }
.footer { background-color: #f3f4f6; padding: 20px; text-align: center; font-size: 12px; color: #6b7280; }
.button { display: inline-block; padding: 12px 24px; background-color: #2563eb; color: white; text-decoration: none; border-radius: 6px; margin: 10px 0; }
.info-box { background-color: #dbeafe; border-left: 4px solid #2563eb; padding: 15px; margin: 15px 0; }
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>Formation Manager Itinova</h1>
</div>
<div class="content">
${content}
</div>
<div class="footer">
<p>Cet email a été envoyé automatiquement par le système de gestion des formations Itinova.</p>
<p>Pour toute question, veuillez contacter le service RH.</p>
</div>
</div>
</body>
</html>
`.trim();
}
/**
* Envoie un email de confirmation d'inscription avec invitation Outlook
*/
export async function sendInscriptionConfirmation(params: {
apprenantEmail: string;
apprenantNom: string;
apprenantPrenom: string;
formationNom: string;
sessionNom: string;
dateDebut: Date;
dateFin: Date;
lieu: string;
statut: 'confirmee' | 'liste_attente';
}): Promise<boolean> {
const isConfirmed = params.statut === 'confirmee';
const content = `
<h2>Confirmation d'inscription</h2>
<p>Bonjour ${params.apprenantPrenom} ${params.apprenantNom},</p>
${isConfirmed
? '<p><strong>Votre inscription a été confirmée !</strong></p>'
: '<p><strong>Vous avez été ajouté à la liste d\'attente.</strong></p>'
}
<div class="info-box">
<h3>Détails de la formation</h3>
<p><strong>Formation :</strong> ${params.formationNom}</p>
<p><strong>Session :</strong> ${params.sessionNom}</p>
<p><strong>Date de début :</strong> ${params.dateDebut.toLocaleDateString('fr-FR', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
})}</p>
<p><strong>Date de fin :</strong> ${params.dateFin.toLocaleDateString('fr-FR', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
})}</p>
<p><strong>Lieu :</strong> ${params.lieu}</p>
</div>
${isConfirmed
? `<p>Une invitation Outlook est jointe à cet email. Merci de l'ajouter à votre calendrier pour bloquer votre agenda.</p>
<p><strong>Important :</strong> Les inscriptions seront bloquées 15 jours avant le début de la session. Après cette date, aucune modification ne sera possible.</p>`
: '<p>Nous vous contacterons dès qu\'une place se libère.</p>'
}
<p>À bientôt pour cette formation !</p>
`;
const attachments = isConfirmed ? [{
filename: 'invitation.ics',
content: generateFormationICS({
formationNom: params.formationNom,
sessionNom: params.sessionNom,
dateDebut: params.dateDebut,
dateFin: params.dateFin,
lieu: params.lieu,
apprenantNom: params.apprenantNom,
apprenantPrenom: params.apprenantPrenom,
apprenantEmail: params.apprenantEmail,
}),
contentType: 'text/calendar',
}] : undefined;
return sendEmail({
to: params.apprenantEmail,
subject: isConfirmed
? `Confirmation d'inscription - ${params.formationNom}`
: `Liste d'attente - ${params.formationNom}`,
html: getEmailTemplate(content),
attachments,
});
}
/**
* Envoie un email teaser pour une session
*/
export async function sendTeaserEmail(params: {
apprenantEmail: string;
apprenantPrenom: string;
formationNom: string;
sessionNom: string;
dateDebut: Date;
}): Promise<boolean> {
const content = `
<h2>Votre formation approche !</h2>
<p>Bonjour ${params.apprenantPrenom},</p>
<p>Nous sommes ravis de vous accueillir prochainement pour la formation <strong>${params.formationNom}</strong>.</p>
<div class="info-box">
<p><strong>Session :</strong> ${params.sessionNom}</p>
<p><strong>Date :</strong> ${params.dateDebut.toLocaleDateString('fr-FR', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric'
})}</p>
</div>
<p>Préparez-vous à vivre une expérience enrichissante qui vous permettra de développer vos compétences managériales.</p>
<p>À très bientôt !</p>
`;
return sendEmail({
to: params.apprenantEmail,
subject: `Votre formation ${params.formationNom} approche !`,
html: getEmailTemplate(content),
});
}
/**
* Envoie un email de rappel J-7
*/
export async function sendRappelJ7Email(params: {
apprenantEmail: string;
apprenantPrenom: string;
formationNom: string;
sessionNom: string;
dateDebut: Date;
lieu: string;
}): Promise<boolean> {
const content = `
<h2>Rappel : Votre formation dans 7 jours</h2>
<p>Bonjour ${params.apprenantPrenom},</p>
<p>Nous vous rappelons que votre formation <strong>${params.formationNom}</strong> commence dans 7 jours.</p>
<div class="info-box">
<h3>Informations pratiques</h3>
<p><strong>Session :</strong> ${params.sessionNom}</p>
<p><strong>Date :</strong> ${params.dateDebut.toLocaleDateString('fr-FR', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
})}</p>
<p><strong>Lieu :</strong> ${params.lieu}</p>
</div>
<p><strong>Merci de vous présenter à l'heure indiquée.</strong></p>
<p>Si vous avez des questions, n'hésitez pas à contacter le service RH.</p>
<p>À très bientôt !</p>
`;
return sendEmail({
to: params.apprenantEmail,
subject: `Rappel J-7 : ${params.formationNom}`,
html: getEmailTemplate(content),
});
}
/**
* Envoie des emails groupés à tous les inscrits d'une session
*/
export async function sendGroupEmail(params: {
recipients: Array<{ email: string; prenom: string }>;
formationNom: string;
sessionNom: string;
type: 'teaser' | 'rappel';
dateDebut: Date;
lieu?: 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,
formationNom: params.formationNom,
sessionNom: params.sessionNom,
dateDebut: params.dateDebut,
});
} else {
await sendRappelJ7Email({
apprenantEmail: recipient.email,
apprenantPrenom: recipient.prenom,
formationNom: params.formationNom,
sessionNom: params.sessionNom,
dateDebut: params.dateDebut,
lieu: params.lieu || '',
});
}
sent++;
} catch (error) {
console.error(`Erreur envoi email à ${recipient.email}:`, error);
failed++;
}
}
return { sent, failed };
}