Checkpoint: Ajout de l'interface de configuration SMTP avec Resend : formulaire de configuration (API key, email expéditeur, nom), basculement simulation/production, test d'envoi immédiat, stockage sécurisé en base de données, et guide de configuration intégré

This commit is contained in:
Manus Sandbox
2025-11-18 02:00:48 -05:00
parent 20dc80cd74
commit 9d67724e83
11 changed files with 1298 additions and 13 deletions

View File

@@ -11,6 +11,7 @@
import { ENV } from "./env";
import { notifyOwner } from "./notification";
import { getActiveEmailConfig } from "../db";
interface EmailParams {
to: string;
@@ -37,9 +38,11 @@ interface ResendEmailRequest {
/**
* Envoie un email via Resend API
*/
async function sendViaResend(params: EmailParams): Promise<boolean> {
const resendApiKey = process.env.RESEND_API_KEY;
const fromEmail = process.env.RESEND_FROM_EMAIL || 'noreply@manusvm.computer';
async function sendViaResend(params: EmailParams, config?: { apiKey: string; fromEmail: string; fromName: string }): Promise<boolean> {
// Utiliser la config fournie ou les variables d'environnement
const resendApiKey = config?.apiKey || process.env.RESEND_API_KEY;
const fromEmail = config?.fromEmail || process.env.RESEND_FROM_EMAIL || 'noreply@manusvm.computer';
const fromName = config?.fromName || 'Formation Manager Itinova';
if (!resendApiKey) {
console.warn('[Email] RESEND_API_KEY non configurée, email simulé');
@@ -48,7 +51,7 @@ async function sendViaResend(params: EmailParams): Promise<boolean> {
try {
const payload: ResendEmailRequest = {
from: fromEmail,
from: `${fromName} <${fromEmail}>`,
to: [params.to],
subject: params.subject,
html: params.html,
@@ -126,15 +129,32 @@ ${params.attachments ? `Pièces jointes: ${params.attachments.map(a => a.filenam
* Envoie un email (réel ou simulé selon la configuration)
*/
export async function sendEmail(params: EmailParams): Promise<boolean> {
// Tenter d'envoyer via Resend
const sent = await sendViaResend(params);
// Récupérer la configuration depuis la base de données
const config = await getActiveEmailConfig();
// Si l'envoi échoue (pas de clé API ou erreur), simuler
if (!sent) {
// Si mode simulation ou pas de config, simuler
if (!config || config.mode === 'simulation') {
return await simulateEmail(params);
}
return true;
// Si mode production, tenter d'envoyer via Resend
if (config.mode === 'production' && config.apiKey) {
const sent = await sendViaResend(params, {
apiKey: config.apiKey,
fromEmail: config.fromEmail,
fromName: config.fromName,
});
// Si l'envoi échoue, simuler en fallback
if (!sent) {
return await simulateEmail(params);
}
return true;
}
// Fallback: simuler
return await simulateEmail(params);
}
/**