diff --git a/server/api/service/feedback/index.post.ts b/server/api/service/feedback/index.post.ts index 4c74524..2280e7a 100644 --- a/server/api/service/feedback/index.post.ts +++ b/server/api/service/feedback/index.post.ts @@ -62,6 +62,7 @@ export default defineEventHandler(async (event) => { const highlightSelections = normaliseArray(body.highlightSelections) const frictionSelections = normaliseArray(body.frictionSelections) const allowContact = Boolean(body.contactConsent) + const fromAddress = email ? (name ? `${name} <${email}>` : email) : undefined const details: string[] = [] details.push(`Overall excitement: ${excitement}/5`) @@ -107,7 +108,7 @@ export default defineEventHandler(async (event) => { ['Discord', discordHandle || '—'], ['Okay to contact', allowContact ? 'Yes' : 'No'], ], - from: email || undefined, + replyTo: fromAddress, }) return { success: true } diff --git a/server/api/service/feedback/issues.post.ts b/server/api/service/feedback/issues.post.ts index 2128a8c..3b7bdba 100644 --- a/server/api/service/feedback/issues.post.ts +++ b/server/api/service/feedback/issues.post.ts @@ -30,6 +30,7 @@ export default defineEventHandler(async (event) => { const description = sanitize(body.description) const categories = sanitizeCategories(body.categories) const contactEmail = sanitize(body.contactEmail) + const fromAddress = contactEmail || undefined if (title.length < 4) { throw createError({ statusCode: 400, statusMessage: 'Title must be at least 4 characters long.' }) @@ -60,7 +61,7 @@ export default defineEventHandler(async (event) => { ['Categories', categories.join(', ')], ['Contact email', contactEmail || '—'], ], - from: contactEmail || undefined, + replyTo: fromAddress, }) return { diff --git a/server/api/service/updates.post.ts b/server/api/service/updates.post.ts index edb4cd6..c136af4 100644 --- a/server/api/service/updates.post.ts +++ b/server/api/service/updates.post.ts @@ -15,6 +15,7 @@ export default defineEventHandler(async (event) => { const email = body.email?.trim().toLowerCase() const name = body.name?.trim() const source = body.source?.trim() || 'landing-updates' + const fromAddress = email ? (name ? `${name} <${email}>` : email) : undefined if (!email) { throw createError({ statusCode: 400, statusMessage: 'Email is required' }) @@ -46,6 +47,7 @@ export default defineEventHandler(async (event) => { event: 'New updates signup', summary: `New updates signup: ${email}`, data: dataEntries, + replyTo: fromAddress, }) } diff --git a/server/api/service/waitlist.post.ts b/server/api/service/waitlist.post.ts index 6e4d546..dd4fcb0 100644 --- a/server/api/service/waitlist.post.ts +++ b/server/api/service/waitlist.post.ts @@ -20,6 +20,7 @@ export default defineEventHandler(async (event) => { const notes = body.notes?.trim() const source = body.source?.trim() || 'landing' const wantsProductUpdates = Boolean(body.wantsProductUpdates) + const fromAddress = email ? (name ? `${name} <${email}>` : email) : undefined if (!email) { throw createError({ statusCode: 400, statusMessage: 'Email is required' }) @@ -72,6 +73,7 @@ export default defineEventHandler(async (event) => { event: 'New updates signup (waitlist)', summary: `Product updates opt-in (waitlist): ${email}`, data: dataEntries, + replyTo: fromAddress, }) } } @@ -121,6 +123,7 @@ export default defineEventHandler(async (event) => { event: 'New waitlist signup', summary: `New waitlist signup: ${email}`, data: dataEntries, + replyTo: fromAddress, }) return { diff --git a/server/utils/notifications.ts b/server/utils/notifications.ts index 67ded91..2583ef9 100644 --- a/server/utils/notifications.ts +++ b/server/utils/notifications.ts @@ -6,6 +6,7 @@ interface MailOptions { text?: string html?: string from?: string + replyTo?: string } interface MailPayload extends MailOptions { @@ -20,6 +21,7 @@ interface AdminNotificationInput { message?: string data?: NotificationDataEntry[] from?: string + replyTo?: string } interface SmtpConfig { @@ -83,6 +85,7 @@ async function sendViaSmtp(payload: MailPayload) { subject: payload.subject, text: payload.text, html: payload.html, + replyTo: payload.replyTo, }) return true } catch (error) { @@ -159,7 +162,7 @@ function formatAdminNotification(notification: AdminNotificationInput) { } } - return { subject, text: lines.join('\n'), from: notification.from } + return { subject, text: lines.join('\n'), from: notification.from, replyTo: notification.replyTo } } export async function sendAdminNotification(notification: string | AdminNotificationInput, text?: string) { @@ -171,7 +174,13 @@ export async function sendAdminNotification(notification: string | AdminNotifica mailOptions = { to, subject: notification, text: text || '' } } else { const formatted = formatAdminNotification(notification) - mailOptions = { to, subject: formatted.subject, text: formatted.text, from: formatted.from } + mailOptions = { + to, + subject: formatted.subject, + text: formatted.text, + from: formatted.from, + replyTo: formatted.replyTo, + } } const success = await sendMail(mailOptions)