Skip to content

Email System (Brevo Integration)

Last Updated: October 27, 2025
Current Implementation: Brevo HTTP API

Overview

The Kinguru platform uses Brevo (formerly Sendinblue) HTTP API for all transactional emails. The system sends 5 distinct email types across authentication, booking, and password management.

Why Brevo?

  • Cloudflare Compatible - HTTP API works seamlessly with Workers (no TCP/SMTP issues)
  • Better Deliverability - Managed sender reputation with built-in SPF/DKIM
  • Enhanced Tracking - Open rates, click tracking, bounce management, webhooks
  • Cost Effective - Free tier: 300 emails/day (sufficient for current volume)
  • Developer Experience - Clear error messages, template management UI

Email Types

Authentication Emails

  • Template: emails/verification-email.tsx
  • Function: sendVerificationEmail() in src/lib/actions/auth/email/send-mail.ts
  • Triggers: User signup, company signup, quick signup
  • Features: Rate limiting (5-min cooldown), locale-aware URLs
  • Tags: authentication, email-verification

2. Email Verification (Code-based)

  • Template: emails/code-verification-email.tsx
  • Function: sendVerificationEmail({ isCode: true })
  • Features: 6-digit code, 30-minute expiration
  • Tags: authentication, code-verification
  • Provider: Custom BrevoEmailProvider in src/lib/nextauth/custom-email-provider.ts
  • Purpose: "Sign in with Email" functionality
  • Features: 24-hour expiration, HTML + text templates
  • Tags: nextauth, magic-link

Password Management

4. Password Reset

  • Template: emails/reset-password-email.tsx
  • Function: sendResetMail() in src/lib/actions/auth/reset/request-password-reset.ts
  • Features: UUID token, 1-hour expiration, auto-cleanup
  • Tags: authentication, password-reset

Booking Notifications

5. Booking Notification

  • Template: emails/booking-email.tsx
  • Function: sendBookingEmail() in src/lib/actions/booking/email/send-mail.ts
  • Trigger: Payment intent created
  • Features: Time slots, pricing, donation info, locale-aware
  • Tags: booking, reservation, locale (en/pl)

6. Booking Confirmation

  • Template: emails/booking-confirmed-email.tsx
  • Function: sendBookingConfirmationEmail()
  • Trigger: Stripe payment confirmed
  • Tags: booking, confirmation, locale

Implementation

Core Email Service

File: src/lib/brevo-email.ts

import * as brevo from "@getbrevo/brevo";

export interface BrevoEmailOptions {
  to: string;
  toName?: string;
  subject: string;
  htmlContent: string;
  textContent?: string;
  from?: string;
  fromName?: string;
  tags?: string[];
}

export async function sendEmail(options: BrevoEmailOptions): 
  Promise<{ ok: true; messageId: string } | { ok: false; error: string }>

Email Templates

All templates use @react-email/components for structure: - Location: emails/ directory - Rendering: @react-email/render converts React → HTML - Features: Internationalization via next-intl, responsive design, shared styles - Outputs: HTML + plain text versions

Environment Configuration

Required Secrets (Cloudflare/GitHub):

BREVO_API_KEY          # Brevo API v3 key

Required Variables (wrangler.jsonc):

{
  "vars": {
    "EMAIL_FROM": "noreply@eventify.today",
    "EMAIL_FROM_NAME": "Eventify"
  }
}

Local Development (.dev.vars):

BREVO_API_KEY=xkeysib-your-api-key-here
EMAIL_FROM=noreply@eventify.today
EMAIL_FROM_NAME=Eventify

Testing

Unit Tests

Tests are located in src/lib/brevo-email.test.ts and src/lib/nextauth/custom-email-provider.test.ts.

npm run test

Manual Testing Checklist

  1. Email Verification - Register new user, check inbox for link
  2. Code Verification - Request code, verify 6-digit format
  3. Magic Link - Sign in with email, click link
  4. Password Reset - Request reset, verify link works
  5. Booking Notification - Create booking, check confirmation email
  6. Booking Confirmation - Complete payment, verify final email

Monitoring

  • Brevo Dashboard: https://app.brevo.com
  • Check: Delivery rates, bounce rates, open rates (if tracking enabled)
  • Logs: Winston logger (search for "brevo-email")

Email Volume

Estimated Daily Volume: - Email Verification: 50-100 - Code Verification: 10-20 - Magic Links: 20-30 - Password Resets: 5-10 - Booking Notifications: 30-50 - Booking Confirmations: 25-45 - Total: ~140-255/day

Brevo Free Tier: 300 emails/day ✅

Error Handling

All email functions follow these patterns:

Pattern 1: Fire-and-Forget (Booking emails)

// Logs errors but doesn't block user flow
try {
  await sendEmail(...);
} catch (e) {
  logger.error(e);
}

Pattern 2: Status Return (Auth emails)

// Returns success/failure to user
const result = await sendEmail(...);
if (!result.ok) {
  return { ok: false, message: t("unknown_error") };
}

Pattern 3: Rate-Limited (Verification emails)

// Checks last send timestamp
if (lastSent && now - lastSent < 5 minutes) {
  return { ok: false, message: t("rate_limit") };
}

Dependencies

{
  "dependencies": {
    "@getbrevo/brevo": "^2.2.0",
    "@react-email/components": "^0.0.25",
    "@react-email/render": "^1.0.1"
  }
}

Note: Nodemailer was removed in the Brevo migration.

Core Logic

  • src/lib/brevo-email.ts - Email service
  • src/lib/nextauth/custom-email-provider.ts - NextAuth integration
  • src/lib/actions/auth/email/send-mail.ts - Auth emails
  • src/lib/actions/booking/email/send-mail.ts - Booking emails
  • src/lib/actions/auth/reset/request-password-reset.ts - Password reset

Templates

  • emails/verification-email.tsx
  • emails/code-verification-email.tsx
  • emails/reset-password-email.tsx
  • emails/booking-email.tsx
  • emails/booking-confirmed-email.tsx
  • emails/base-styles.ts - Shared styles

Tests

  • src/lib/brevo-email.test.ts
  • src/lib/nextauth/custom-email-provider.test.ts

Troubleshooting

Email Not Received

  1. Check Brevo dashboard for send status
  2. Verify EMAIL_FROM is verified in Brevo
  3. Check spam/junk folders
  4. Review server logs for errors

API Key Issues

# Set secret in Cloudflare
wrangler secret put BREVO_API_KEY

# Verify .dev.vars for local development
cat .dev.vars

Rate Limiting

  • Brevo free tier: 300 emails/day
  • Check current usage in Brevo dashboard
  • Upgrade plan if needed

Template Rendering Errors

  • Ensure @react-email/* packages are up to date
  • Check template syntax for errors
  • Test render function independently