import { z } from 'zod'
const contactSchema = z.object({
name: z.string().min(1).max(100),
email: z.string().email(),
message: z.string().min(10).max(5000)
})
export default defineEventHandler(async (event) => {
const config = useRuntimeConfig()
// Validate request body
const body = await readBody(event)
const result = contactSchema.safeParse(body)
if (!result.success) {
throw createError({
statusCode: 400,
statusMessage: 'Invalid form data',
data: result.error.flatten()
})
}
const { name, email, message } = result.data
// Check if API key is configured
if (!config.brevoApiKey || config.brevoApiKey === 'NOT_SET') {
console.error('BREVO_API_KEY is not configured')
throw createError({
statusCode: 500,
statusMessage: 'Email service is not configured'
})
}
try {
// Build HTML email content
const htmlContent = `
Nachricht
${escapeHtml(message)}
`.trim()
// Send email via Brevo SMTP API
const response = await $fetch<{ messageId?: string }>('https://api.brevo.com/v3/smtp/email', {
method: 'POST',
headers: {
'api-key': config.brevoApiKey,
'Content-Type': 'application/json'
},
body: {
sender: {
name: config.brevoSenderName,
email: config.brevoSenderEmail
},
to: [
{
email: config.brevoContactEmail,
name: 'GremiumHub Team'
}
],
replyTo: {
email,
name
},
subject: `Kontaktanfrage von ${name}`,
htmlContent
}
})
return {
success: true,
messageId: response.messageId
}
} catch (error: unknown) {
const fetchError = error as { statusCode?: number; data?: { code?: string; message?: string } }
console.error('Brevo SMTP API error:', fetchError.data || error)
throw createError({
statusCode: fetchError.statusCode || 500,
statusMessage: fetchError.data?.message || 'Failed to send message'
})
}
})
// Helper function to escape HTML special characters
function escapeHtml(text: string): string {
const htmlEntities: Record = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
}
return text.replace(/[&<>"']/g, (char) => htmlEntities[char] ?? char)
}