feat: send RSVP confirmation emails using environment-based SMTP config; split EMAIL_FROM into EMAIL_FROM_NAME and EMAIL_FROM_ADDRESS
This commit is contained in:
63
backend/src/email.ts
Normal file
63
backend/src/email.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import nodemailer from 'nodemailer';
|
||||
|
||||
const transporter = nodemailer.createTransport({
|
||||
host: process.env.EMAIL_HOST,
|
||||
port: Number(process.env.EMAIL_PORT),
|
||||
secure: process.env.EMAIL_SECURE === 'true', // true for 465, false for other ports
|
||||
auth: {
|
||||
user: process.env.EMAIL_USER,
|
||||
pass: process.env.EMAIL_PASS,
|
||||
},
|
||||
});
|
||||
|
||||
export interface RSVPEmailData {
|
||||
eventTitle: string;
|
||||
name: string;
|
||||
attending: string;
|
||||
bringingGuests: string;
|
||||
guestCount: number;
|
||||
guestNames: string[];
|
||||
itemsBringing: string[];
|
||||
otherItems: string;
|
||||
to: string;
|
||||
}
|
||||
|
||||
export async function sendRSVPEmail(data: RSVPEmailData) {
|
||||
const {
|
||||
eventTitle,
|
||||
name,
|
||||
attending,
|
||||
bringingGuests,
|
||||
guestCount,
|
||||
guestNames,
|
||||
itemsBringing,
|
||||
otherItems,
|
||||
to,
|
||||
} = data;
|
||||
|
||||
const subject = `RSVP Confirmation for ${eventTitle}`;
|
||||
const guestList = guestNames.length ? guestNames.join(', ') : 'None';
|
||||
const itemsList = itemsBringing.length ? itemsBringing.join(', ') : 'None';
|
||||
const otherItemsList = otherItems ? otherItems : 'None';
|
||||
|
||||
const html = `
|
||||
<h2>RSVP Confirmation</h2>
|
||||
<p><strong>Event:</strong> ${eventTitle}</p>
|
||||
<p><strong>Name:</strong> ${name}</p>
|
||||
<p><strong>Attending:</strong> ${attending}</p>
|
||||
<p><strong>Bringing Guests:</strong> ${bringingGuests} (${guestCount})</p>
|
||||
<p><strong>Guest Names:</strong> ${guestList}</p>
|
||||
<p><strong>Items Bringing (from needed list):</strong> ${itemsList}</p>
|
||||
<p><strong>Other Items:</strong> ${otherItemsList}</p>
|
||||
`;
|
||||
|
||||
await transporter.sendMail({
|
||||
from: {
|
||||
name: process.env.EMAIL_FROM_NAME || '',
|
||||
address: process.env.EMAIL_FROM_ADDRESS || process.env.EMAIL_USER || '',
|
||||
},
|
||||
to,
|
||||
subject,
|
||||
html,
|
||||
});
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import dotenv from 'dotenv';
|
||||
import path from 'path';
|
||||
import multer from 'multer';
|
||||
import fs from 'fs';
|
||||
import { sendRSVPEmail } from './email';
|
||||
|
||||
dotenv.config();
|
||||
|
||||
@@ -294,6 +295,29 @@ app.post('/api/events/:slug/rsvp', async (req: Request, res: Response) => {
|
||||
[eventId, name, attending, bringing_guests, guest_count, JSON.stringify(parsedGuestNames), JSON.stringify(parsedItemsBringing), other_items || '']
|
||||
);
|
||||
|
||||
// Fetch event title for the email
|
||||
const eventInfo = await db.get('SELECT title FROM events WHERE id = ?', [eventId]);
|
||||
const eventTitle = eventInfo ? eventInfo.title : slug;
|
||||
|
||||
// Send RSVP confirmation email (if email provided)
|
||||
if (req.body.email) {
|
||||
try {
|
||||
await sendRSVPEmail({
|
||||
eventTitle,
|
||||
name,
|
||||
attending,
|
||||
bringingGuests: bringing_guests,
|
||||
guestCount: guest_count,
|
||||
guestNames: parsedGuestNames,
|
||||
itemsBringing: parsedItemsBringing,
|
||||
otherItems: other_items || '',
|
||||
to: req.body.email,
|
||||
});
|
||||
} catch (emailErr) {
|
||||
console.error('Error sending RSVP email:', emailErr);
|
||||
}
|
||||
}
|
||||
|
||||
// Return the complete RSVP data including the parsed arrays
|
||||
res.status(201).json({
|
||||
id: result.lastID,
|
||||
|
||||
Reference in New Issue
Block a user