108 lines
3.4 KiB
TypeScript
108 lines
3.4 KiB
TypeScript
import nodemailer from 'nodemailer';
|
|
|
|
interface EmailOptions {
|
|
to: string;
|
|
subject: string;
|
|
html: string;
|
|
}
|
|
|
|
// Create reusable transporter object using SMTP transport
|
|
const transporter = nodemailer.createTransport({
|
|
service: 'gmail',
|
|
auth: {
|
|
user: process.env.EMAIL_USER,
|
|
pass: process.env.EMAIL_PASSWORD, // Use App Password for Gmail
|
|
},
|
|
});
|
|
|
|
export async function sendEmail({ to, subject, html }: EmailOptions) {
|
|
try {
|
|
const info = await transporter.sendMail({
|
|
from: `"Table Tennis Booking" <${process.env.EMAIL_USER}>`,
|
|
to,
|
|
subject,
|
|
html,
|
|
});
|
|
|
|
console.log('Email sent: %s', info.messageId);
|
|
return { success: true, messageId: info.messageId };
|
|
} catch (error) {
|
|
console.error('Error sending email:', error);
|
|
return { success: false, error };
|
|
}
|
|
}
|
|
|
|
export function generateBookingConfirmationEmail(booking: {
|
|
id: string;
|
|
date: string;
|
|
startTime: string;
|
|
endTime: string;
|
|
courtName: string;
|
|
userName: string;
|
|
}) {
|
|
return {
|
|
subject: 'Booking Confirmation - Table Tennis Court',
|
|
html: `
|
|
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
|
|
<h2 style="color: #333;">Booking Confirmed!</h2>
|
|
<p>Hello ${booking.userName},</p>
|
|
<p>Your table tennis court booking has been confirmed:</p>
|
|
|
|
<div style="background-color: #f5f5f5; padding: 20px; border-radius: 8px; margin: 20px 0;">
|
|
<h3 style="margin-top: 0;">Booking Details</h3>
|
|
<p><strong>Booking ID:</strong> ${booking.id}</p>
|
|
<p><strong>Date:</strong> ${booking.date}</p>
|
|
<p><strong>Time:</strong> ${booking.startTime} - ${booking.endTime}</p>
|
|
<p><strong>Court:</strong> ${booking.courtName}</p>
|
|
</div>
|
|
|
|
<p>Please arrive 5 minutes before your booking time. If you need to cancel or modify your booking, please log in to your account.</p>
|
|
|
|
<p>Thank you for choosing our table tennis facility!</p>
|
|
|
|
<hr style="margin: 30px 0;">
|
|
<p style="font-size: 12px; color: #666;">
|
|
This is an automated email. Please do not reply to this message.
|
|
</p>
|
|
</div>
|
|
`,
|
|
};
|
|
}
|
|
|
|
export function generateBookingCancellationEmail(booking: {
|
|
id: string;
|
|
date: string;
|
|
startTime: string;
|
|
endTime: string;
|
|
courtName: string;
|
|
userName: string;
|
|
}) {
|
|
return {
|
|
subject: 'Booking Cancelled - Table Tennis Court',
|
|
html: `
|
|
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
|
|
<h2 style="color: #d32f2f;">Booking Cancelled</h2>
|
|
<p>Hello ${booking.userName},</p>
|
|
<p>Your table tennis court booking has been cancelled:</p>
|
|
|
|
<div style="background-color: #f5f5f5; padding: 20px; border-radius: 8px; margin: 20px 0;">
|
|
<h3 style="margin-top: 0;">Cancelled Booking Details</h3>
|
|
<p><strong>Booking ID:</strong> ${booking.id}</p>
|
|
<p><strong>Date:</strong> ${booking.date}</p>
|
|
<p><strong>Time:</strong> ${booking.startTime} - ${booking.endTime}</p>
|
|
<p><strong>Court:</strong> ${booking.courtName}</p>
|
|
</div>
|
|
|
|
<p>You can make a new booking anytime through our booking system.</p>
|
|
|
|
<p>Thank you for using our table tennis facility!</p>
|
|
|
|
<hr style="margin: 30px 0;">
|
|
<p style="font-size: 12px; color: #666;">
|
|
This is an automated email. Please do not reply to this message.
|
|
</p>
|
|
</div>
|
|
`,
|
|
};
|
|
}
|