317 lines
9.9 KiB
TypeScript
317 lines
9.9 KiB
TypeScript
/**
|
|
* Service d'envoi d'emails pour les formations
|
|
* Utilise le système de notification Manus pour envoyer des emails
|
|
*/
|
|
|
|
import { generateFormationICS } from "./icsGenerator";
|
|
import { notifyOwner } from "./_core/notification";
|
|
|
|
interface EmailParams {
|
|
to: string;
|
|
subject: string;
|
|
html: string;
|
|
attachments?: Array<{
|
|
filename: string;
|
|
content: string;
|
|
contentType: string;
|
|
}>;
|
|
}
|
|
|
|
/**
|
|
* Envoie un email en utilisant le système de notification Manus
|
|
* Note: Pour un envoi SMTP réel, intégrer un service comme SendGrid ou Mailgun
|
|
*/
|
|
async function sendEmail(params: EmailParams): Promise<boolean> {
|
|
console.log('=== EMAIL ENVOYÉ ===');
|
|
console.log('To:', params.to);
|
|
console.log('Subject:', params.subject);
|
|
|
|
// Envoyer une notification au propriétaire du projet
|
|
const emailContent = `
|
|
Destinataire: ${params.to}
|
|
Sujet: ${params.subject}
|
|
|
|
${params.html.replace(/<[^>]*>/g, '').substring(0, 500)}...
|
|
|
|
${params.attachments ? `Pièces jointes: ${params.attachments.map(a => a.filename).join(', ')}` : ''}`;
|
|
|
|
try {
|
|
await notifyOwner({
|
|
title: `Email envoyé: ${params.subject}`,
|
|
content: emailContent,
|
|
});
|
|
console.log('✓ Email traité avec succès');
|
|
} catch (error) {
|
|
console.error('Erreur lors de l\'envoi de la notification:', error);
|
|
}
|
|
|
|
console.log('===================');
|
|
|
|
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;
|
|
apprenantFonction: string;
|
|
formationNom: string;
|
|
sessionNom: string;
|
|
dateDebut: Date;
|
|
dateFin: Date;
|
|
lieu: string;
|
|
statut: 'confirmee' | 'liste_attente';
|
|
}): Promise<boolean> {
|
|
const isConfirmed = params.statut === 'confirmee';
|
|
const fonctionLabel = params.apprenantFonction === 'directeur' ? 'Directeur' :
|
|
params.apprenantFonction === 'chef_service' ? 'Chef de service' : 'Autre';
|
|
|
|
const content = `
|
|
<h2>Confirmation d'inscription</h2>
|
|
<p>Bonjour ${fonctionLabel} ${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;
|
|
apprenantNom: string;
|
|
apprenantFonction: string;
|
|
formationNom: string;
|
|
sessionNom: string;
|
|
dateDebut: Date;
|
|
}): Promise<boolean> {
|
|
const fonctionLabel = params.apprenantFonction === 'directeur' ? 'Directeur' :
|
|
params.apprenantFonction === 'chef_service' ? 'Chef de service' : '';
|
|
const salutation = fonctionLabel ? `${fonctionLabel} ${params.apprenantPrenom} ${params.apprenantNom}` : params.apprenantPrenom;
|
|
|
|
const content = `
|
|
<h2>Votre formation approche !</h2>
|
|
<p>Bonjour ${salutation},</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;
|
|
apprenantNom: string;
|
|
apprenantFonction: string;
|
|
formationNom: string;
|
|
sessionNom: string;
|
|
dateDebut: Date;
|
|
lieu: string;
|
|
}): Promise<boolean> {
|
|
const fonctionLabel = params.apprenantFonction === 'directeur' ? 'Directeur' :
|
|
params.apprenantFonction === 'chef_service' ? 'Chef de service' : '';
|
|
const salutation = fonctionLabel ? `${fonctionLabel} ${params.apprenantPrenom} ${params.apprenantNom}` : params.apprenantPrenom;
|
|
|
|
const content = `
|
|
<h2>Rappel : Votre formation dans 7 jours</h2>
|
|
<p>Bonjour ${salutation},</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; nom: string; fonction: 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,
|
|
apprenantNom: recipient.nom,
|
|
apprenantFonction: recipient.fonction,
|
|
formationNom: params.formationNom,
|
|
sessionNom: params.sessionNom,
|
|
dateDebut: params.dateDebut,
|
|
});
|
|
} else {
|
|
await sendRappelJ7Email({
|
|
apprenantEmail: recipient.email,
|
|
apprenantPrenom: recipient.prenom,
|
|
apprenantNom: recipient.nom,
|
|
apprenantFonction: recipient.fonction,
|
|
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 };
|
|
}
|