127 lines
3.4 KiB
TypeScript
127 lines
3.4 KiB
TypeScript
import { z } from 'zod'
|
|
|
|
const subscribeSchema = z.object({
|
|
email: z.string().email()
|
|
})
|
|
|
|
export default defineEventHandler(async (event) => {
|
|
const config = useRuntimeConfig()
|
|
|
|
// Validate request body
|
|
const body = await readBody(event)
|
|
const result = subscribeSchema.safeParse(body)
|
|
|
|
if (!result.success) {
|
|
throw createError({
|
|
statusCode: 400,
|
|
statusMessage: 'Invalid email address'
|
|
})
|
|
}
|
|
|
|
const { email } = result.data
|
|
|
|
// Check if API key is configured
|
|
if (!config.brevoApiKey) {
|
|
console.error('BREVO_API_KEY is not configured')
|
|
throw createError({
|
|
statusCode: 500,
|
|
statusMessage: 'Newsletter service is not configured'
|
|
})
|
|
}
|
|
|
|
// Check if DOI template ID is configured
|
|
if (!config.brevoDoiTemplateId) {
|
|
console.error('BREVO_DOI_TEMPLATE_ID is not configured')
|
|
throw createError({
|
|
statusCode: 500,
|
|
statusMessage: 'Newsletter service is not configured'
|
|
})
|
|
}
|
|
|
|
console.log('DOI_TEMPLATE_ID', config.brevoDoiTemplateId)
|
|
|
|
// Check if public site URL is configured (for DOI redirect)
|
|
if (!config.public.siteUrl) {
|
|
console.error('NUXT_PUBLIC_SITE_URL is not configured')
|
|
throw createError({
|
|
statusCode: 500,
|
|
statusMessage: 'Newsletter service is not configured'
|
|
})
|
|
}
|
|
|
|
// Check if newsletter list ID is configured
|
|
if (!config.brevoNewsletterListId) {
|
|
console.error('BREVO_NEWSLETTER_LIST_ID is not configured')
|
|
throw createError({
|
|
statusCode: 500,
|
|
statusMessage: 'Newsletter service is not configured'
|
|
})
|
|
}
|
|
|
|
const templateId = parseInt(config.brevoDoiTemplateId, 10)
|
|
if (isNaN(templateId)) {
|
|
console.error('BREVO_DOI_TEMPLATE_ID is not a valid number')
|
|
throw createError({
|
|
statusCode: 500,
|
|
statusMessage: 'Newsletter service is not configured'
|
|
})
|
|
}
|
|
|
|
const listId = parseInt(config.brevoNewsletterListId, 10)
|
|
if (isNaN(listId)) {
|
|
console.error('BREVO_NEWSLETTER_LIST_ID is not a valid number')
|
|
throw createError({
|
|
statusCode: 500,
|
|
statusMessage: 'Newsletter service is not configured'
|
|
})
|
|
}
|
|
|
|
// Build the redirection URL to the confirmation page
|
|
const redirectionUrl = `${config.public.siteUrl}/newsletter-bestaetigt`
|
|
|
|
try {
|
|
// Build request body for Brevo Double Opt-In API
|
|
const brevoBody = {
|
|
email,
|
|
templateId,
|
|
redirectionUrl,
|
|
includeListIds: [listId]
|
|
}
|
|
|
|
console.log('Brevo DOI request body:', brevoBody)
|
|
|
|
await $fetch('https://api.brevo.com/v3/contacts/doubleOptinConfirmation', {
|
|
method: 'POST',
|
|
headers: {
|
|
accept: 'application/json',
|
|
'api-key': config.brevoApiKey,
|
|
'content-type': 'application/json'
|
|
},
|
|
body: brevoBody
|
|
})
|
|
|
|
return {
|
|
success: true
|
|
}
|
|
} catch (error: unknown) {
|
|
// Handle Brevo API errors
|
|
const fetchError = error as { statusCode?: number; data?: { code?: string; message?: string } }
|
|
|
|
// Contact already exists (duplicate_parameter error) - treat as success
|
|
// User will receive another confirmation email
|
|
if (fetchError.data?.code === 'duplicate_parameter') {
|
|
return {
|
|
success: true,
|
|
message: 'Confirmation email sent'
|
|
}
|
|
}
|
|
|
|
console.error('Brevo API error:', fetchError.data || error)
|
|
|
|
throw createError({
|
|
statusCode: fetchError.statusCode || 500,
|
|
statusMessage: fetchError.data?.message || 'Failed to subscribe to newsletter'
|
|
})
|
|
}
|
|
})
|