feat: redesign newsletter email with modern template
- Redesign email template with brand colors and modern layout - Add animated welcome icon and professional styling - Improve button design with gradient colors matching the site - Add TLS configuration to fix SSL certificate errors - Fix email validation regex to be more permissive - Update email subject to include logo emoji Design improvements: - Logo in header with brand colors (#d4a574, #c4956a, #5a5a4e) - Beautiful rounded buttons for "Jouer Maintenant" and "Visiter le Site" - Responsive design with proper spacing and shadows - Benefits section with visual icons - Professional footer with unsubscribe link 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
772202dc6e
commit
0850614264
|
|
@ -21,6 +21,9 @@ const createTransporter = () => {
|
|||
user: process.env.SMTP_USER,
|
||||
pass: process.env.SMTP_PASS,
|
||||
},
|
||||
tls: {
|
||||
rejectUnauthorized: false // Ignore les erreurs de certificat SSL
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -61,45 +64,351 @@ const sendEmail = async ({ to, subject, html, text }) => {
|
|||
*/
|
||||
export const sendNewsletterConfirmationEmail = async (email) => {
|
||||
const unsubscribeUrl = `${process.env.FRONTEND_URL || 'http://localhost:3000'}/newsletter/unsubscribe?email=${encodeURIComponent(email)}`;
|
||||
const siteUrl = process.env.FRONTEND_URL || 'http://localhost:3000';
|
||||
const gameUrl = `${siteUrl}/game`;
|
||||
const currentDate = new Date().toLocaleString('fr-FR', {
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit'
|
||||
});
|
||||
|
||||
const html = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
|
||||
.container { max-width: 600px; margin: 0 auto; padding: 20px; }
|
||||
.header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px; text-align: center; border-radius: 10px 10px 0 0; }
|
||||
.content { background: #f9f9f9; padding: 30px; border-radius: 0 0 10px 10px; }
|
||||
.footer { text-align: center; margin-top: 20px; color: #666; font-size: 12px; }
|
||||
.unsubscribe { margin-top: 30px; padding-top: 20px; border-top: 1px solid #ddd; }
|
||||
.unsubscribe a { color: #999; text-decoration: none; }
|
||||
body {
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
line-height: 1.6;
|
||||
color: #5a5a4e;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: linear-gradient(135deg, #f5f5f0 0%, #faf9f5 100%);
|
||||
}
|
||||
.email-wrapper {
|
||||
padding: 40px 20px;
|
||||
}
|
||||
.container {
|
||||
max-width: 650px;
|
||||
margin: 0 auto;
|
||||
background: white;
|
||||
border-radius: 20px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 10px 40px rgba(0,0,0,0.15);
|
||||
}
|
||||
.header {
|
||||
background: linear-gradient(135deg, #d4a574 0%, #c4956a 100%);
|
||||
color: white;
|
||||
padding: 50px 30px;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
}
|
||||
.logo-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 15px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.logo-icon {
|
||||
font-size: 48px;
|
||||
filter: drop-shadow(0 2px 4px rgba(0,0,0,0.2));
|
||||
}
|
||||
.logo-text {
|
||||
font-size: 36px;
|
||||
font-weight: bold;
|
||||
letter-spacing: 1px;
|
||||
text-shadow: 2px 2px 4px rgba(0,0,0,0.2);
|
||||
}
|
||||
.header-subtitle {
|
||||
font-size: 16px;
|
||||
opacity: 0.95;
|
||||
letter-spacing: 2px;
|
||||
text-transform: uppercase;
|
||||
font-weight: 500;
|
||||
}
|
||||
.welcome-section {
|
||||
background: linear-gradient(135deg, #d4a574 0%, #c4956a 100%);
|
||||
color: white;
|
||||
padding: 40px 30px;
|
||||
text-align: center;
|
||||
border-bottom: 4px solid rgba(255,255,255,0.2);
|
||||
}
|
||||
.welcome-icon {
|
||||
font-size: 60px;
|
||||
margin-bottom: 20px;
|
||||
animation: bounce 2s infinite;
|
||||
}
|
||||
@keyframes bounce {
|
||||
0%, 100% { transform: translateY(0); }
|
||||
50% { transform: translateY(-10px); }
|
||||
}
|
||||
.welcome-title {
|
||||
font-size: 32px;
|
||||
font-weight: bold;
|
||||
margin: 15px 0;
|
||||
text-shadow: 2px 2px 4px rgba(0,0,0,0.2);
|
||||
}
|
||||
.user-info {
|
||||
background: rgba(255,255,255,0.15);
|
||||
backdrop-filter: blur(10px);
|
||||
padding: 25px;
|
||||
border-radius: 15px;
|
||||
margin: 25px 0;
|
||||
border: 1px solid rgba(255,255,255,0.3);
|
||||
}
|
||||
.user-info-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 12px 0;
|
||||
font-size: 15px;
|
||||
}
|
||||
.content {
|
||||
padding: 40px 30px;
|
||||
background: linear-gradient(to bottom, #faf9f5 0%, #f5f5f0 100%);
|
||||
}
|
||||
.game-section {
|
||||
background: white;
|
||||
border: 3px solid #d4a574;
|
||||
border-radius: 20px;
|
||||
padding: 35px;
|
||||
text-align: center;
|
||||
margin: 30px 0;
|
||||
box-shadow: 0 4px 15px rgba(212, 165, 116, 0.2);
|
||||
}
|
||||
.game-icon {
|
||||
font-size: 64px;
|
||||
margin-bottom: 20px;
|
||||
filter: drop-shadow(0 2px 4px rgba(0,0,0,0.1));
|
||||
}
|
||||
.game-title {
|
||||
font-size: 28px;
|
||||
color: #5a5a4e;
|
||||
font-weight: bold;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.game-description {
|
||||
color: #8a8a7a;
|
||||
font-size: 16px;
|
||||
line-height: 1.8;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.prizes-box {
|
||||
background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);
|
||||
border-radius: 15px;
|
||||
padding: 25px;
|
||||
margin: 25px 0;
|
||||
border-left: 5px solid #f59e0b;
|
||||
}
|
||||
.prizes-title {
|
||||
color: #92400e;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.prizes-text {
|
||||
color: #78350f;
|
||||
font-size: 15px;
|
||||
margin: 0;
|
||||
}
|
||||
.buttons-container {
|
||||
margin: 30px 0;
|
||||
text-align: center;
|
||||
}
|
||||
.button {
|
||||
display: inline-block;
|
||||
padding: 18px 40px;
|
||||
margin: 10px 8px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
border-radius: 50px;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
|
||||
}
|
||||
.button-primary {
|
||||
background: linear-gradient(135deg, #d4a574 0%, #c4956a 100%);
|
||||
color: white;
|
||||
}
|
||||
.button-secondary {
|
||||
background: linear-gradient(135deg, #5a5a4e 0%, #4a4a42 100%);
|
||||
color: white;
|
||||
}
|
||||
.info-box {
|
||||
background: white;
|
||||
border-radius: 15px;
|
||||
padding: 30px;
|
||||
margin: 25px 0;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.08);
|
||||
}
|
||||
.info-title {
|
||||
color: #5a5a4e;
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
margin-top: 0;
|
||||
margin-bottom: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
.benefits-grid {
|
||||
display: grid;
|
||||
gap: 15px;
|
||||
}
|
||||
.benefit-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 15px;
|
||||
background: linear-gradient(135deg, #faf9f5 0%, #f5f5f0 100%);
|
||||
border-radius: 10px;
|
||||
border-left: 4px solid #d4a574;
|
||||
}
|
||||
.benefit-icon {
|
||||
font-size: 28px;
|
||||
margin-right: 15px;
|
||||
}
|
||||
.benefit-text {
|
||||
color: #5a5a4e;
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.footer {
|
||||
background: linear-gradient(135deg, #5a5a4e 0%, #4a4a42 100%);
|
||||
color: #e5e4dc;
|
||||
text-align: center;
|
||||
padding: 40px 30px;
|
||||
}
|
||||
.footer-logo {
|
||||
font-size: 24px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.footer-title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 15px;
|
||||
color: #d4a574;
|
||||
}
|
||||
.footer-date {
|
||||
font-size: 13px;
|
||||
opacity: 0.8;
|
||||
margin: 15px 0;
|
||||
}
|
||||
.unsubscribe {
|
||||
margin-top: 20px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid rgba(229, 228, 220, 0.3);
|
||||
font-size: 12px;
|
||||
}
|
||||
.unsubscribe a {
|
||||
color: #d4a574;
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<h1>🍵 Bienvenue dans notre newsletter!</h1>
|
||||
</div>
|
||||
<div class="content">
|
||||
<h2>Merci de votre abonnement</h2>
|
||||
<p>Nous sommes ravis de vous compter parmi nos abonnés !</p>
|
||||
<p>Vous recevrez désormais nos dernières actualités, offres exclusives et nouveautés directement dans votre boîte mail.</p>
|
||||
<p>Restez connecté avec Thé Tip Top pour découvrir :</p>
|
||||
<ul>
|
||||
<li>🍵 Nos nouveaux thés et infusions</li>
|
||||
<li>🎁 Des offres spéciales réservées aux abonnés</li>
|
||||
<li>📰 Les actualités de nos boutiques</li>
|
||||
<li>🎉 Les résultats de nos jeux-concours</li>
|
||||
</ul>
|
||||
<div class="unsubscribe">
|
||||
<p style="font-size: 12px; color: #999;">
|
||||
Vous ne souhaitez plus recevoir nos emails ? <a href="${unsubscribeUrl}">Se désabonner</a>
|
||||
<div class="email-wrapper">
|
||||
<div class="container">
|
||||
<!-- En-tête avec Logo -->
|
||||
<div class="header">
|
||||
<div class="logo-container">
|
||||
<div class="logo-icon">🍃</div>
|
||||
<div class="logo-text">Thé Tip Top</div>
|
||||
</div>
|
||||
<div class="header-subtitle">Newsletter Jeu Concours</div>
|
||||
</div>
|
||||
|
||||
<!-- Section Bienvenue -->
|
||||
<div class="welcome-section">
|
||||
<div class="welcome-icon">🎉</div>
|
||||
<div class="welcome-title">Bienvenue !</div>
|
||||
<p style="font-size: 18px; margin: 10px 0;">Votre inscription à la newsletter est confirmée</p>
|
||||
|
||||
<div class="user-info">
|
||||
<div class="user-info-item">
|
||||
<span style="margin-right: 10px; font-size: 20px;">📅</span>
|
||||
<strong>Inscrit le ${currentDate}</strong>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p style="font-size: 16px; margin-top: 20px; opacity: 0.95;">
|
||||
Merci de rejoindre la communauté Thé Tip Top ! 🍵
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Contenu principal -->
|
||||
<div class="content">
|
||||
<!-- Section Jeu Concours -->
|
||||
<div class="game-section">
|
||||
<div class="game-icon">🎯</div>
|
||||
<div class="game-title">Participez à Notre Jeu Concours !</div>
|
||||
<p class="game-description">
|
||||
À l'occasion de l'ouverture de notre 10ème boutique à Nice,
|
||||
tentez votre chance de gagner des lots exceptionnels !
|
||||
</p>
|
||||
|
||||
<div class="prizes-box">
|
||||
<div class="prizes-title">🎁 Lots à gagner</div>
|
||||
<p class="prizes-text">Thés premium • Accessoires • Coffrets cadeaux</p>
|
||||
</div>
|
||||
|
||||
<div class="buttons-container">
|
||||
<a href="${gameUrl}" class="button button-primary">
|
||||
🎮 Jouer Maintenant
|
||||
</a>
|
||||
<a href="${siteUrl}" class="button button-secondary">
|
||||
🌐 Visiter le Site
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Section Bénéfices -->
|
||||
<div class="info-box">
|
||||
<h3 class="info-title">
|
||||
<span>📧</span>
|
||||
<span>Ce que vous recevrez</span>
|
||||
</h3>
|
||||
<div class="benefits-grid">
|
||||
<div class="benefit-item">
|
||||
<span class="benefit-icon">🎮</span>
|
||||
<span class="benefit-text">Nouveautés du jeu concours</span>
|
||||
</div>
|
||||
<div class="benefit-item">
|
||||
<span class="benefit-icon">🏆</span>
|
||||
<span class="benefit-text">Annonces des gagnants</span>
|
||||
</div>
|
||||
<div class="benefit-item">
|
||||
<span class="benefit-icon">🍃</span>
|
||||
<span class="benefit-text">Découvertes de thés d'exception</span>
|
||||
</div>
|
||||
<div class="benefit-item">
|
||||
<span class="benefit-icon">🎁</span>
|
||||
<span class="benefit-text">Offres exclusives réservées</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Pied de page -->
|
||||
<div class="footer">
|
||||
<div class="footer-logo">🍃 Thé Tip Top</div>
|
||||
<div class="footer-title">Votre spécialiste du thé d'exception</div>
|
||||
<p class="footer-date">📧 Newsletter envoyée le ${currentDate}</p>
|
||||
<div class="unsubscribe">
|
||||
<p>
|
||||
Vous ne souhaitez plus recevoir nos emails ?<br>
|
||||
<a href="${unsubscribeUrl}">Se désinscrire</a>
|
||||
</p>
|
||||
</div>
|
||||
<p style="margin-top: 20px; font-size: 12px; opacity: 0.7;">
|
||||
© 2025 Thé Tip Top - Tous droits réservés
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<p>© 2025 Thé Tip Top - Tous droits réservés</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
|
@ -107,20 +416,39 @@ export const sendNewsletterConfirmationEmail = async (email) => {
|
|||
`;
|
||||
|
||||
const text = `
|
||||
Bienvenue dans notre newsletter!
|
||||
🍃 Thé Tip Top - Newsletter Jeu Concours
|
||||
|
||||
Nous sommes ravis de vous compter parmi nos abonnés !
|
||||
🎉 Bienvenue Utilisateur !
|
||||
Votre inscription à la newsletter est confirmée
|
||||
|
||||
Vous recevrez désormais nos dernières actualités, offres exclusives et nouveautés directement dans votre boîte mail.
|
||||
👤 Utilisateur
|
||||
📅 Inscrit le ${currentDate}
|
||||
|
||||
Pour vous désabonner: ${unsubscribeUrl}
|
||||
🎯 Participez à Notre Jeu Concours !
|
||||
À l'occasion de l'ouverture de notre 10ème boutique à Nice, tentez votre chance de gagner des lots exceptionnels !
|
||||
|
||||
© 2025 Thé Tip Top - Tous droits réservés
|
||||
🎁 Lots à gagner : Thés premium, accessoires, coffrets cadeaux
|
||||
|
||||
🎮 Jouer Maintenant : ${gameUrl}
|
||||
🌐 Visiter le Site : ${siteUrl}
|
||||
|
||||
📧 Que recevrez-vous ?
|
||||
🎮 Nouveautés du jeu concours
|
||||
🏆 Annonces des gagnants
|
||||
🍃 Découvertes de thés
|
||||
🎁 Offres exclusives
|
||||
|
||||
Thé Tip Top - Votre spécialiste du thé d'exception
|
||||
📧 Newsletter envoyée le ${currentDate}
|
||||
|
||||
Pour vous désinscrire : ${unsubscribeUrl}
|
||||
|
||||
© 2025 Thé Tip Top - Tous droits réservés
|
||||
`;
|
||||
|
||||
return sendEmail({
|
||||
to: email,
|
||||
subject: '🍵 Bienvenue dans la newsletter Thé Tip Top',
|
||||
subject: '🍃 Thé Tip Top | Bienvenue dans la newsletter - Jeu Concours 🎉',
|
||||
html,
|
||||
text,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ export const subscribeSchema = z.object({
|
|||
.string({
|
||||
required_error: 'L\'email est requis',
|
||||
})
|
||||
.email('Format d\'email invalide'),
|
||||
.regex(/^[^\s@]+@[^\s@]+\.[^\s@]+$/, 'Format d\'email invalide'),
|
||||
}),
|
||||
});
|
||||
|
||||
|
|
@ -21,7 +21,7 @@ export const unsubscribeSchema = z.object({
|
|||
.string({
|
||||
required_error: 'L\'email est requis',
|
||||
})
|
||||
.email('Format d\'email invalide'),
|
||||
.regex(/^[^\s@]+@[^\s@]+\.[^\s@]+$/, 'Format d\'email invalide'),
|
||||
}),
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user