Skip to content

feat(email): implement robust email recipient forwarding and centralized configuration#23

Merged
JacksonR64 merged 4 commits intomainfrom
feat/fix-email-recipient-forwarding
Jun 19, 2025
Merged

feat(email): implement robust email recipient forwarding and centralized configuration#23
JacksonR64 merged 4 commits intomainfrom
feat/fix-email-recipient-forwarding

Conversation

@JacksonR64
Copy link
Copy Markdown
Owner

Summary

This PR fixes email recipient forwarding issues and implements a centralized, maintainable email configuration system for LocalLoop.

Key Changes

🔧 Email Recipient Forwarding Fix

  • Fixed production issue: Emails were incorrectly forwarding to personal email instead of actual users
  • Robust environment detection: Uses dual check (OVERRIDE_EMAILS_TO_DEV=true AND local development)
  • Production-safe: Emails always go to intended recipients in production, even if NODE_ENV is misconfigured
  • Developer control: Explicit OVERRIDE_EMAILS_TO_DEV environment variable for testing control

🏗️ Centralized Email Configuration

  • Single source of truth: Created lib/config/email-addresses.ts for all email addresses
  • Professional subdomain structure:
    • noreply@localloopevents.xyz - System/automated emails
    • hello@localloopevents.xyz - Customer contact
    • support@localloopevents.xyz - Customer support
    • organizer@localloopevents.xyz - Event organizer fallbacks
  • Easy maintenance: Change domain in one place to update entire application

🌐 Custom Domain Integration

  • Verified domain: Set up localloopevents.xyz with Resend DNS verification
  • Free email sending: No longer restricted to verified personal email
  • Consistent branding: All emails use professional custom domain
  • Updated app configuration: Production URL points to new domain

Files Modified

Core Configuration

  • lib/config/email-addresses.ts - New centralized email configuration
  • lib/email-service.ts - Updated to use centralized config and robust recipient logic
  • lib/emails/send-ticket-confirmation.ts - Updated recipient forwarding logic
  • .env.local - Added OVERRIDE_EMAILS_TO_DEV control variable

Email Templates & Contact

  • app/contact/page.tsx - Uses centralized contact email
  • lib/emails/welcome-email.tsx - Uses centralized support email
  • Various email templates updated for consistency

API Routes

  • app/api/rsvps/route.ts - Uses centralized organizer email
  • app/api/rsvps/[id]/route.ts - Uses centralized organizer email
  • app/api/events/reminders/route.ts - Uses centralized organizer email
  • app/api/events/cancellation/route.ts - Uses centralized organizer email
  • app/api/auth/google/callback/route.ts - Uses dynamic user email generation

Configuration

  • next.config.ts - Updated production URL to custom domain

Test Results

  • ✅ All unit tests passing (93/93)
  • ✅ TypeScript compilation successful
  • ✅ Email sending verified with custom domain
  • ✅ Recipient forwarding working correctly in development

Breaking Changes

None - all changes are backwards compatible.

Environment Variables Required

Development (.env.local)

RESEND_FROM_EMAIL=noreply@localloopevents.xyz
OVERRIDE_EMAILS_TO_DEV=false  # Set to true for local testing

Production (Vercel)

RESEND_FROM_EMAIL=noreply@localloopevents.xyz  
OVERRIDE_EMAILS_TO_DEV=false

Benefits

  1. 🎯 Fixes Production Issue: Emails now go to actual users, not redirected to developer email
  2. 🏗️ Maintainable Architecture: Single config file for all email addresses
  3. 🌐 Professional Branding: Consistent custom domain across all communications
  4. 🔒 Production Safe: Robust environment detection prevents accidental email redirection
  5. ⚡ Developer Friendly: Easy testing with explicit override controls

Testing Instructions

  1. Set OVERRIDE_EMAILS_TO_DEV=false in development
  2. Purchase a ticket with any email address
  3. Verify email is sent to the purchaser's email (not developer email)
  4. Check Resend dashboard for successful delivery from custom domain

🤖 Generated with Claude Code

JacksonR64 and others added 4 commits June 19, 2025 05:59
- Replace simple NODE_ENV check with more reliable environment detection
- Add OVERRIDE_EMAILS_TO_DEV environment variable for explicit control
- Use dual check: OVERRIDE_EMAILS_TO_DEV=true AND local development
- Prevent email redirection in production even if NODE_ENV is misconfigured
- Update both email-service.ts and send-ticket-confirmation.ts

This ensures emails always go to the intended recipient in production
while maintaining the ability to override for local development testing.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Update RESEND_FROM_EMAIL to use custom domain noreply@localloopevents.xyz
- Update NEXT_PUBLIC_APP_URL to use new production domain
- Remove email override for proper user email delivery
- Clean up test scripts

This enables free email sending to any recipient using verified domain.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Update contact page email: hello@localloop.events → hello@localloopevents.xyz
- Update all support emails: support@localloop.app → support@localloopevents.xyz
- Update system emails: noreply@localloop.app → noreply@localloopevents.xyz
- Update organizer emails: organizer@localloop.app → organizer@localloopevents.xyz
- Update from email configuration to use hello@localloopevents.xyz
- Update email templates, API routes, and documentation
- Ensure consistent branding across all email communications

This provides a professional, consistent email experience using the
verified custom domain.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
…bility

- Create centralized email configuration in lib/config/email-addresses.ts
- Define all email addresses as constants with proper subdomain structure:
  * SYSTEM_FROM: noreply@localloopevents.xyz (for automated emails)
  * CONTACT: hello@localloopevents.xyz (for customer contact)
  * SUPPORT: support@localloopevents.xyz (for support inquiries)
  * ORGANIZER: organizer@localloopevents.xyz (for event organizers)
- Restore RESEND_FROM_EMAIL to noreply@localloopevents.xyz for system messages
- Update all files to import and use centralized EMAIL_ADDRESSES:
  * Contact page now uses EMAIL_ADDRESSES.CONTACT
  * Email service uses EMAIL_ADDRESSES for all email types
  * Email templates use centralized support addresses
  * API routes use EMAIL_ADDRESSES.ORGANIZER and generateUserEmail()
- Maintain proper subdomain separation:
  * noreply@ for system/automated emails
  * hello@ for customer contact
  * support@ for customer support
  * organizer@ for event organizer fallbacks

This provides a single source of truth for all email addresses, making
domain changes and email management much easier to maintain.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel bot commented Jun 19, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
local-loop ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 19, 2025 10:18am

@github-actions
Copy link
Copy Markdown

🚀 PR Quick Check Results

Check Status
Quick Check ✅ success
Unit Tests ✅ success
Smoke Test ✅ success

🎉 All quick checks passed! Your PR is ready for full CI pipeline.

This is a quick check for immediate feedback. Full testing will run in the main CI pipeline.

@JacksonR64 JacksonR64 merged commit b1a46e1 into main Jun 19, 2025
16 checks passed
@JacksonR64 JacksonR64 deleted the feat/fix-email-recipient-forwarding branch June 19, 2025 11:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant