Checkpoint: Ajout de la possibilité d'envoyer des emails via SMTP directement (sans Resend) :

**Modifications de la base de données** :
- Ajout des champs SMTP dans la table `emailConfig` : smtpHost, smtpPort, smtpSecure, smtpUser, smtpPassword

**Backend** :
- Installation de `nodemailer` pour l'envoi SMTP
- Création de `server/_core/smtpSender.ts` avec les fonctions d'envoi SMTP et de test de connexion
- Modification de `server/_core/emailSender.ts` pour supporter les deux méthodes (Resend et SMTP)
- Priorité donnée à SMTP si configuré, sinon fallback sur Resend

**Frontend** :
- Mise à jour de `AdminEmailConfig.tsx` pour permettre le choix entre Resend et SMTP
- Ajout d'un sélecteur de méthode d'envoi (Resend API / SMTP Direct)
- Formulaire de configuration SMTP avec :
  * Hôte SMTP (ex: smtp.gmail.com)
  * Port (587, 465, 25)
  * Sécurité (TLS, SSL, None)
  * Identifiants (utilisateur/mot de passe)
  * Email expéditeur

**Compatibilité** :
- Support des principaux fournisseurs SMTP (Gmail, Outlook, serveurs SMTP personnalisés)
- Instructions pour les mots de passe d'application Gmail
- Mode simulation toujours disponible pour les tests
This commit is contained in:
Manus Sandbox
2025-11-28 06:33:25 -05:00
parent c0446e5ba8
commit 40964c8369
11 changed files with 2193 additions and 48 deletions

View File

@@ -200,6 +200,17 @@ export const emailConfig = mysqlTable("emailConfig", {
domainVerified: boolean("domainVerified").default(false).notNull(),
/** Actif ou non */
active: boolean("active").default(true).notNull(),
// Champs SMTP
/** Hôte SMTP (ex: smtp.gmail.com) */
smtpHost: varchar("smtpHost", { length: 255 }),
/** Port SMTP (ex: 587, 465, 25) */
smtpPort: int("smtpPort"),
/** Sécurité SMTP (none, tls, ssl) */
smtpSecure: mysqlEnum("smtpSecure", ["none", "tls", "ssl"]).default("tls"),
/** Nom d'utilisateur SMTP */
smtpUser: varchar("smtpUser", { length: 320 }),
/** Mot de passe SMTP (chiffré) */
smtpPassword: text("smtpPassword"),
createdAt: timestamp("createdAt").defaultNow().notNull(),
updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
});