Email queue + async sending; legal settings and placeholders

- Add in-memory email queue with rate limiting (MAX_EMAILS_PER_HOUR)
- Bulk send to event attendees now queues and returns immediately
- Frontend shows 'Emails are being sent in the background'
- Legal pages, settings, and placeholders updates

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Michilis
2026-02-12 21:03:49 +00:00
parent 18254c566e
commit b9f46b02cc
17 changed files with 1410 additions and 352 deletions

View File

@@ -5,6 +5,7 @@ import { requireAuth } from '../lib/auth.js';
import { getNow, generateId } from '../lib/utils.js';
import emailService from '../lib/email.js';
import { getTemplateVariables, defaultTemplates } from '../lib/emailTemplates.js';
import { getQueueStatus } from '../lib/emailQueue.js';
const emailsRouter = new Hono();
@@ -195,7 +196,7 @@ emailsRouter.get('/templates/:slug/variables', requireAuth(['admin', 'organizer'
// ==================== Email Sending Routes ====================
// Send email using template to event attendees
// Send email using template to event attendees (non-blocking, queued)
emailsRouter.post('/send/event/:eventId', requireAuth(['admin', 'organizer']), async (c) => {
const { eventId } = c.req.param();
const user = (c as any).get('user');
@@ -206,7 +207,8 @@ emailsRouter.post('/send/event/:eventId', requireAuth(['admin', 'organizer']), a
return c.json({ error: 'Template slug is required' }, 400);
}
const result = await emailService.sendToEventAttendees({
// Queue emails for background processing instead of sending synchronously
const result = await emailService.queueEventEmails({
eventId,
templateSlug,
customVariables,
@@ -411,4 +413,10 @@ emailsRouter.post('/test', requireAuth(['admin']), async (c) => {
return c.json(result);
});
// Get email queue status
emailsRouter.get('/queue/status', requireAuth(['admin']), async (c) => {
const status = getQueueStatus();
return c.json({ status });
});
export default emailsRouter;