ajout envoi smtp (paramètres, test envois, envoi à 1 participant). protège vue mot de passe

- ajout filtre page statistiques
This commit is contained in:
Yannick Le Duc
2025-08-25 18:28:14 +02:00
parent caed358661
commit b0a945f07b
21 changed files with 3523 additions and 30 deletions

View File

@@ -0,0 +1,151 @@
import { NextRequest, NextResponse } from 'next/server';
import * as nodemailer from 'nodemailer';
import { SmtpSettings } from '@/types';
export async function POST(request: NextRequest) {
try {
const {
smtpSettings,
toEmail,
toName,
subject,
message,
campaignTitle,
voteUrl
} = await request.json();
// Validation des paramètres
if (!smtpSettings || !toEmail || !toName || !subject || !message) {
return NextResponse.json(
{ success: false, error: 'Paramètres manquants' },
{ status: 400 }
);
}
// Validation de l'email
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(toEmail)) {
return NextResponse.json(
{ success: false, error: 'Adresse email de destination invalide' },
{ status: 400 }
);
}
// Validation des paramètres SMTP
if (!smtpSettings.host || !smtpSettings.port || !smtpSettings.username || !smtpSettings.password) {
return NextResponse.json(
{ success: false, error: 'Paramètres SMTP incomplets' },
{ status: 400 }
);
}
// Créer le transporteur SMTP
const transporter = nodemailer.createTransport({
host: smtpSettings.host,
port: smtpSettings.port,
secure: smtpSettings.secure,
auth: {
user: smtpSettings.username,
pass: smtpSettings.password,
},
tls: {
rejectUnauthorized: false,
},
connectionTimeout: 10000,
greetingTimeout: 10000,
socketTimeout: 10000,
});
// Vérifier la connexion
await transporter.verify();
// Créer le contenu HTML de l'email
const htmlContent = `
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; line-height: 1.6;">
<div style="background-color: #2563eb; color: white; padding: 20px; text-align: center; border-radius: 8px 8px 0 0;">
<h1 style="margin: 0; font-size: 24px;">Mes Budgets Participatifs</h1>
</div>
<div style="background-color: #ffffff; padding: 30px; border: 1px solid #e5e7eb; border-top: none;">
<h2 style="color: #1f2937; margin-top: 0;">Bonjour ${toName},</h2>
<div style="background-color: #f3f4f6; padding: 20px; border-radius: 8px; margin: 20px 0;">
<h3 style="margin-top: 0; color: #374151;">Campagne : ${campaignTitle}</h3>
<p style="margin-bottom: 0; color: #6b7280;">${message.replace(/\n/g, '<br>')}</p>
</div>
<div style="text-align: center; margin: 30px 0;">
<a href="${voteUrl}"
style="background-color: #2563eb; color: white; padding: 15px 30px; text-decoration: none; border-radius: 6px; font-weight: bold; display: inline-block;">
🗳️ Voter maintenant
</a>
</div>
<div style="background-color: #fef3c7; padding: 15px; border-radius: 6px; margin: 20px 0;">
<p style="margin: 0; color: #92400e; font-size: 14px;">
<strong>💡 Conseil :</strong> Ce lien est personnel et unique. Ne le partagez pas avec d'autres personnes.
</p>
</div>
<hr style="border: none; border-top: 1px solid #e5e7eb; margin: 30px 0;">
<p style="color: #6b7280; font-size: 14px; margin-bottom: 10px;">
Si le bouton ne fonctionne pas, vous pouvez copier et coller ce lien dans votre navigateur :
</p>
<p style="background-color: #f3f4f6; padding: 10px; border-radius: 4px; font-family: monospace; font-size: 12px; word-break: break-all; color: #374151;">
${voteUrl}
</p>
</div>
<div style="background-color: #f9fafb; padding: 20px; text-align: center; border-radius: 0 0 8px 8px; border: 1px solid #e5e7eb; border-top: none;">
<p style="color: #6b7280; font-size: 12px; margin: 0;">
Cet email a été envoyé automatiquement par Mes Budgets Participatifs.<br>
Si vous avez des questions, contactez l'administrateur de la campagne.
</p>
</div>
</div>
`;
// Envoyer l'email
const info = await transporter.sendMail({
from: `"${smtpSettings.from_name}" <${smtpSettings.from_email}>`,
to: `"${toName}" <${toEmail}>`,
subject: subject,
text: message,
html: htmlContent,
});
return NextResponse.json({
success: true,
messageId: info.messageId,
message: 'Email envoyé avec succès'
});
} catch (error) {
console.error('Erreur lors de l\'envoi de l\'email au participant:', error);
let errorMessage = 'Erreur lors de l\'envoi de l\'email';
if (error instanceof Error) {
if (error.message.includes('EBADNAME')) {
errorMessage = 'Impossible de résoudre le nom d\'hôte SMTP. Vérifiez que le serveur SMTP est correct.';
} else if (error.message.includes('ECONNREFUSED')) {
errorMessage = 'Connexion refusée. Vérifiez le serveur et le port SMTP.';
} else if (error.message.includes('ETIMEDOUT')) {
errorMessage = 'Délai d\'attente dépassé. Vérifiez votre connexion internet et les paramètres SMTP.';
} else if (error.message.includes('EAUTH')) {
errorMessage = 'Authentification échouée. Vérifiez le nom d\'utilisateur et le mot de passe SMTP.';
} else {
errorMessage = error.message;
}
}
return NextResponse.json(
{
success: false,
error: errorMessage
},
{ status: 500 }
);
}
}

View File

@@ -0,0 +1,134 @@
import { NextRequest, NextResponse } from 'next/server';
import * as nodemailer from 'nodemailer';
import { SmtpSettings } from '@/types';
export async function POST(request: NextRequest) {
try {
const { smtpSettings, toEmail } = await request.json();
// Validation des paramètres
if (!smtpSettings || !toEmail) {
return NextResponse.json(
{ success: false, error: 'Paramètres manquants' },
{ status: 400 }
);
}
// Validation de l'email
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(toEmail)) {
return NextResponse.json(
{ success: false, error: 'Adresse email de destination invalide' },
{ status: 400 }
);
}
// Validation des paramètres SMTP
if (!smtpSettings.host || !smtpSettings.port || !smtpSettings.username || !smtpSettings.password) {
return NextResponse.json(
{ success: false, error: 'Paramètres SMTP incomplets' },
{ status: 400 }
);
}
// Créer le transporteur SMTP avec options de résolution DNS
const transporter = nodemailer.createTransport({
host: smtpSettings.host,
port: smtpSettings.port,
secure: smtpSettings.secure, // true pour 465, false pour les autres ports
auth: {
user: smtpSettings.username,
pass: smtpSettings.password,
},
// Options pour résoudre les problèmes DNS
tls: {
rejectUnauthorized: false, // Accepte les certificats auto-signés
},
// Timeout pour éviter les blocages
connectionTimeout: 10000, // 10 secondes
greetingTimeout: 10000,
socketTimeout: 10000,
});
// Vérifier la connexion
await transporter.verify();
// Envoyer l'email de test
const info = await transporter.sendMail({
from: `"${smtpSettings.from_name}" <${smtpSettings.from_email}>`,
to: toEmail,
subject: 'Test de configuration SMTP - Mes Budgets Participatifs',
html: `
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
<h2 style="color: #2563eb;">✅ Test de configuration SMTP réussi !</h2>
<p>Bonjour,</p>
<p>Cet email confirme que votre configuration SMTP fonctionne correctement.</p>
<div style="background-color: #f3f4f6; padding: 15px; border-radius: 8px; margin: 20px 0;">
<h3 style="margin-top: 0;">Configuration utilisée :</h3>
<ul style="margin: 0; padding-left: 20px;">
<li><strong>Serveur :</strong> ${smtpSettings.host}:${smtpSettings.port}</li>
<li><strong>Sécurisé :</strong> ${smtpSettings.secure ? 'Oui (SSL/TLS)' : 'Non'}</li>
<li><strong>Utilisateur :</strong> ${smtpSettings.username}</li>
<li><strong>Expéditeur :</strong> ${smtpSettings.from_name} &lt;${smtpSettings.from_email}&gt;</li>
</ul>
</div>
<p>Vous pouvez maintenant utiliser cette configuration pour envoyer des emails automatiques depuis votre application.</p>
<hr style="border: none; border-top: 1px solid #e5e7eb; margin: 20px 0;">
<p style="color: #6b7280; font-size: 12px;">
Cet email a été envoyé automatiquement par Mes Budgets Participatifs pour tester la configuration SMTP.
</p>
</div>
`,
text: `
Test de configuration SMTP réussi !
Bonjour,
Cet email confirme que votre configuration SMTP fonctionne correctement.
Configuration utilisée :
- Serveur : ${smtpSettings.host}:${smtpSettings.port}
- Sécurisé : ${smtpSettings.secure ? 'Oui (SSL/TLS)' : 'Non'}
- Utilisateur : ${smtpSettings.username}
- Expéditeur : ${smtpSettings.from_name} <${smtpSettings.from_email}>
Vous pouvez maintenant utiliser cette configuration pour envoyer des emails automatiques depuis votre application.
---
Cet email a été envoyé automatiquement par Mes Budgets Participatifs pour tester la configuration SMTP.
`
});
return NextResponse.json({
success: true,
messageId: info.messageId
});
} catch (error) {
console.error('Erreur lors de l\'envoi de l\'email de test:', error);
let errorMessage = 'Erreur lors de l\'envoi de l\'email';
if (error instanceof Error) {
if (error.message.includes('EBADNAME')) {
errorMessage = 'Impossible de résoudre le nom d\'hôte SMTP. Vérifiez que le serveur SMTP est correct.';
} else if (error.message.includes('ECONNREFUSED')) {
errorMessage = 'Connexion refusée. Vérifiez le serveur et le port SMTP.';
} else if (error.message.includes('ETIMEDOUT')) {
errorMessage = 'Délai d\'attente dépassé. Vérifiez votre connexion internet et les paramètres SMTP.';
} else if (error.message.includes('EAUTH')) {
errorMessage = 'Authentification échouée. Vérifiez le nom d\'utilisateur et le mot de passe.';
} else {
errorMessage = error.message;
}
}
return NextResponse.json(
{
success: false,
error: errorMessage
},
{ status: 500 }
);
}
}

View File

@@ -0,0 +1,95 @@
import { NextRequest, NextResponse } from 'next/server';
import * as nodemailer from 'nodemailer';
import { SmtpSettings } from '@/types';
export async function POST(request: NextRequest) {
try {
const { smtpSettings } = await request.json();
// Validation des paramètres
if (!smtpSettings) {
return NextResponse.json(
{ success: false, error: 'Paramètres SMTP manquants' },
{ status: 400 }
);
}
// Validation des paramètres SMTP
if (!smtpSettings.host || !smtpSettings.port || !smtpSettings.username || !smtpSettings.password) {
return NextResponse.json(
{ success: false, error: 'Paramètres SMTP incomplets' },
{ status: 400 }
);
}
// Validation du port
if (smtpSettings.port < 1 || smtpSettings.port > 65535) {
return NextResponse.json(
{ success: false, error: 'Port SMTP invalide' },
{ status: 400 }
);
}
// Validation de l'email d'expédition
if (!smtpSettings.from_email.includes('@')) {
return NextResponse.json(
{ success: false, error: 'Adresse email d\'expédition invalide' },
{ status: 400 }
);
}
// Créer le transporteur SMTP avec options de résolution DNS
const transporter = nodemailer.createTransport({
host: smtpSettings.host,
port: smtpSettings.port,
secure: smtpSettings.secure, // true pour 465, false pour les autres ports
auth: {
user: smtpSettings.username,
pass: smtpSettings.password,
},
// Options pour résoudre les problèmes DNS
tls: {
rejectUnauthorized: false, // Accepte les certificats auto-signés
},
// Timeout pour éviter les blocages
connectionTimeout: 10000, // 10 secondes
greetingTimeout: 10000,
socketTimeout: 10000,
});
// Vérifier la connexion
await transporter.verify();
return NextResponse.json({
success: true,
message: 'Connexion SMTP réussie'
});
} catch (error) {
console.error('Erreur lors du test de connexion SMTP:', error);
let errorMessage = 'Erreur de connexion SMTP';
if (error instanceof Error) {
if (error.message.includes('EBADNAME')) {
errorMessage = 'Impossible de résoudre le nom d\'hôte SMTP. Vérifiez que le serveur SMTP est correct.';
} else if (error.message.includes('ECONNREFUSED')) {
errorMessage = 'Connexion refusée. Vérifiez le serveur et le port SMTP.';
} else if (error.message.includes('ETIMEDOUT')) {
errorMessage = 'Délai d\'attente dépassé. Vérifiez votre connexion internet et les paramètres SMTP.';
} else if (error.message.includes('EAUTH')) {
errorMessage = 'Authentification échouée. Vérifiez le nom d\'utilisateur et le mot de passe.';
} else {
errorMessage = error.message;
}
}
return NextResponse.json(
{
success: false,
error: errorMessage
},
{ status: 500 }
);
}
}