Add email functionality to AuthService; implement password reset email feature with nodemailer, including transporter initialization and email template for user notifications.

This commit is contained in:
Torsten Schulz (local)
2025-10-19 12:58:06 +02:00
parent 31d5d95a78
commit 2fa84d88be
5 changed files with 522 additions and 0 deletions

View File

@@ -1,6 +1,7 @@
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const crypto = require('crypto');
const nodemailer = require('nodemailer');
const database = require('../config/database');
/**
@@ -12,6 +13,28 @@ class AuthService {
this.jwtSecret = process.env.JWT_SECRET || 'your-secret-key-change-in-production';
this.jwtExpiration = process.env.JWT_EXPIRATION || '24h';
this.saltRounds = 10;
this.emailTransporter = null;
this.initializeEmailTransporter();
}
/**
* Initialisiert den Email-Transporter
*/
initializeEmailTransporter() {
if (process.env.EMAIL_HOST && process.env.EMAIL_USER && process.env.EMAIL_PASSWORD) {
this.emailTransporter = nodemailer.createTransport({
host: process.env.EMAIL_HOST,
port: parseInt(process.env.EMAIL_PORT) || 587,
secure: process.env.EMAIL_SECURE === 'true',
auth: {
user: process.env.EMAIL_USER,
pass: process.env.EMAIL_PASSWORD
}
});
console.log('✅ Email-Transporter konfiguriert');
} else {
console.warn('⚠️ Email-Konfiguration fehlt - Passwort-Reset-E-Mails können nicht versendet werden');
}
}
/**
@@ -234,6 +257,71 @@ class AuthService {
email_token_role: 1 // 1 = Password Reset
});
// E-Mail versenden (falls konfiguriert)
if (this.emailTransporter) {
const frontendUrl = process.env.FRONTEND_URL || 'http://localhost:5010';
const resetUrl = `${frontendUrl}/password-reset?token=${resetToken}`;
const mailOptions = {
from: `"${process.env.EMAIL_FROM_NAME || 'TimeClock'}" <${process.env.EMAIL_FROM}>`,
to: email,
subject: 'TimeClock - Passwort zurücksetzen',
text: `Hallo,
du hast eine Passwort-Zurücksetzen-Anfrage für dein TimeClock-Konto gestellt.
Klicke auf folgenden Link um dein Passwort zurückzusetzen:
${resetUrl}
Dieser Link ist 1 Stunde gültig.
Falls du diese Anfrage nicht gestellt hast, ignoriere diese E-Mail.
---
TimeClock Zeiterfassung
${frontendUrl}
`,
html: `
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
<h2 style="color: #333;">Passwort zurücksetzen</h2>
<p>Hallo,</p>
<p>du hast eine Passwort-Zurücksetzen-Anfrage für dein TimeClock-Konto gestellt.</p>
<p>
<a href="${resetUrl}" style="display: inline-block; padding: 12px 24px; background-color: #4CAF50; color: white; text-decoration: none; border-radius: 4px; margin: 16px 0;">
Passwort zurücksetzen
</a>
</p>
<p style="color: #666; font-size: 14px;">
Oder kopiere diesen Link in deinen Browser:<br>
<code style="background: #f5f5f5; padding: 4px 8px; border-radius: 4px; display: inline-block; margin-top: 8px;">${resetUrl}</code>
</p>
<p style="color: #666; font-size: 14px;">
<strong>Dieser Link ist 1 Stunde gültig.</strong>
</p>
<p style="color: #666; font-size: 14px;">
Falls du diese Anfrage nicht gestellt hast, ignoriere diese E-Mail.
</p>
<hr style="border: none; border-top: 1px solid #ddd; margin: 24px 0;">
<p style="color: #999; font-size: 12px;">
TimeClock Zeiterfassung<br>
<a href="${frontendUrl}">${frontendUrl}</a>
</p>
</div>
`
};
try {
await this.emailTransporter.sendMail(mailOptions);
console.log('✅ Passwort-Reset E-Mail gesendet an:', email);
} catch (error) {
console.error('❌ Fehler beim E-Mail-Versand:', error.message);
// Werfe keinen Fehler - Token wurde gespeichert, User kann es anders nutzen
}
} else {
console.warn('⚠️ E-Mail-Transporter nicht konfiguriert - Reset-Token erstellt aber keine E-Mail versendet');
console.log('Reset-Token:', resetToken);
}
return resetToken;
}