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¶
1. Email Verification (Link-based)¶
- Template:
emails/verification-email.tsx - Function:
sendVerificationEmail()insrc/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
3. NextAuth Magic Link¶
- Provider: Custom
BrevoEmailProviderinsrc/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()insrc/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()insrc/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):
Required Variables (wrangler.jsonc):
Local Development (.dev.vars):
Testing¶
Unit Tests¶
Tests are located in src/lib/brevo-email.test.ts and src/lib/nextauth/custom-email-provider.test.ts.
Manual Testing Checklist¶
- Email Verification - Register new user, check inbox for link
- Code Verification - Request code, verify 6-digit format
- Magic Link - Sign in with email, click link
- Password Reset - Request reset, verify link works
- Booking Notification - Create booking, check confirmation email
- 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.
Related Files¶
Core Logic¶
src/lib/brevo-email.ts- Email servicesrc/lib/nextauth/custom-email-provider.ts- NextAuth integrationsrc/lib/actions/auth/email/send-mail.ts- Auth emailssrc/lib/actions/booking/email/send-mail.ts- Booking emailssrc/lib/actions/auth/reset/request-password-reset.ts- Password reset
Templates¶
emails/verification-email.tsxemails/code-verification-email.tsxemails/reset-password-email.tsxemails/booking-email.tsxemails/booking-confirmed-email.tsxemails/base-styles.ts- Shared styles
Tests¶
src/lib/brevo-email.test.tssrc/lib/nextauth/custom-email-provider.test.ts
Troubleshooting¶
Email Not Received¶
- Check Brevo dashboard for send status
- Verify
EMAIL_FROMis verified in Brevo - Check spam/junk folders
- 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