Skip to content

Email System Documentation

Overview

The email system in this application has been centralized to provide a consistent, maintainable approach to email template management and variable replacement. This document explains how the system works and how to use it.

Architecture

Core Components

  1. EmailVariable Enum (app/Enums/EmailVariable.php)
  2. Defines all available template variables
  3. Provides variable resolution logic
  4. Organizes variables by category
  5. Includes descriptions for documentation

  6. EmailService (app/Services/EmailService.php)

  7. Centralized email processing service
  8. Handles template variable replacement
  9. Provides template validation
  10. Offers preview functionality

  11. Email Templates (Database-driven)

  12. Stored in email_templates table
  13. Managed through admin panel (/dashboard/email-templates)
  14. Support HTML content with template variables

Available Template Variables

Variables are organized into the following categories:

Site & Company

  • {site_name} - The name of your site
  • {site_url} - The base URL of your site
  • {company_name} - Your company name
  • {support_email} - Support email address
  • {support_url} - Support page URL

User Information

  • {user_name} - The recipient's name
  • {user_email} - The recipient's email address
  • {user_id} - The recipient's user ID

Authentication & URLs

  • {login_url} - Link to login page
  • {user_activation_url} - Email confirmation/activation link
  • {reset_url} - Password reset link
  • {dashboard_url} - Link to user dashboard

Affiliate & Marketing

  • {affiliate_url} - Registration URL with affiliate code
  • {affiliate_code} - User's affiliate code
  • {referral_url} - User's referral link

Plans & Pricing

  • {plan_name} - Subscription plan name
  • {plan_price} - Plan price with currency
  • {plan_currency} - Currency code (USD, EUR, etc.)
  • {plan_frequency} - Billing frequency (monthly, yearly, etc.)
  • {plan_credits} - Credits included in plan

Payments & Transactions

  • {transaction_id} - Payment transaction ID
  • {payment_method} - Payment method used
  • {payment_date} - Date of payment
  • {invoice_url} - Link to invoice
  • {receipt_url} - Link to receipt

Subscriptions

  • {subscription_status} - Current subscription status
  • {subscription_expires} - Subscription expiration date
  • {subscription_renews} - Next renewal date
  • {cancel_subscription_url} - Link to cancel subscription

Teams & Collaboration

  • {team_name} - Team name
  • {team_invite_url} - Team invitation acceptance link
  • {team_role} - User's role in team
  • {inviter_name} - Name of person who sent invitation

Date & Time

  • {current_year} - Current year
  • {current_date} - Current date
  • {current_time} - Current time
  • {unsubscribe_url} - Link to unsubscribe from emails
  • {privacy_policy_url} - Link to privacy policy
  • {terms_url} - Link to terms of service

Usage

In Blade Templates

All email blade templates now use the centralized EmailService:

@php
    use App\Services\EmailService;

    $processedTemplate = EmailService::processTemplate(
        $template,
        $user,
        ['plan' => $plan] // Optional context
    );
@endphp

{!! $processedTemplate->content !!}

In PHP Code

Processing a Template

use App\Services\EmailService;

// Get template
$template = EmailTemplates::where('slug', 'payment-successful')->first();

// Process with user and context
$processed = EmailService::processTemplate($template, $user, [
    'plan' => $plan,
    'transaction_id' => 'TXN-123',
    'payment_method' => 'Credit Card'
]);

// Use processed content
$content = $processed->content;
$subject = $processed->subject;

Replacing Variables in Custom Content

use App\Services\EmailService;

$content = "Hello {user_name}, welcome to {site_name}!";
$processed = EmailService::replaceVariables($content, $user);

Getting Variables for Specific Email Type

use App\Services\EmailService;

// Get variables applicable for payment emails
$variables = EmailService::getVariablesForType('payment');

// Get variables for team emails
$variables = EmailService::getVariablesForType('team');

Validating Template Content

use App\Services\EmailService;

$validation = EmailService::validateTemplate($template->content);

if (!$validation['valid']) {
    // Show warnings
    foreach ($validation['unknown_variables'] as $unknown) {
        echo "Unknown variable: $unknown\n";
    }

    // Show suggestions
    foreach ($validation['suggestions'] as $suggestion) {
        echo "$suggestion\n";
    }
}

Preview Template with Sample Data

use App\Services\EmailService;

$preview = EmailService::previewTemplate($template, 'payment');

Email Template Management

Admin Panel

Access email templates through the admin panel at /dashboard/email-templates.

Features: - Create custom email templates - Edit system templates (content and subject only) - Preview templates - See all available variables organized by category - Hover over variables to see descriptions

Template Slugs

System templates use specific slugs: - subscription-successful - Recurring subscription confirmation - payment-successful - One-time payment confirmation - confirmation - Account confirmation - password-reset - Password reset - user-invite - User invitation - team-invite - Team invitation

Creating New Templates

  1. Go to /dashboard/email-templates
  2. Click "Create New Template"
  3. Fill in:
  4. Title
  5. Subject (supports variables)
  6. Content (HTML with variables)
  7. Use variables from the list shown below the editor
  8. Save

Migration from Old System

The old system used manual str_replace() arrays in blade templates. This had several issues:

Problems with Old System:

  • Variables scattered across multiple files
  • Missing variables (e.g., {login_url} was in SQL but never replaced)
  • Hard to maintain and extend
  • No validation or documentation
  • Inconsistent variable support across templates

Benefits of New System:

  • ✅ Centralized variable management
  • ✅ All variables defined in one place (EmailVariable enum)
  • ✅ Automatic variable resolution
  • ✅ Built-in validation
  • ✅ Self-documenting (hover tooltips in admin)
  • ✅ Easy to extend (add new variables in enum)
  • ✅ Type-safe with PHP 8.1 enums
  • ✅ Fixes missing variable bugs

Adding New Variables

To add a new template variable:

  1. Add to EmailVariable Enum
// In app/Enums/EmailVariable.php

// Add new case
case NEW_VARIABLE = '{new_variable}';

// Add to label() method
self::NEW_VARIABLE => 'New Variable Label',

// Add to description() method
self::NEW_VARIABLE => 'Description of what this variable does',

// Add to category() method
self::NEW_VARIABLE => 'Category Name',

// Add to resolve() method
self::NEW_VARIABLE => $context['new_value'] ?? 'default_value',
  1. Use in Templates

The new variable will automatically appear in the admin UI and be available in all email templates.

Email Sending Locations

Emails are sent from the following locations:

Jobs (Queued)

  • SendConfirmationEmail - Account confirmation
  • SendInviteEmail - User invitations
  • SendPasswordResetEmail - Password reset
  • SendPaymentConfirmationEmail - Payment/subscription confirmation
  • SendTeamInviteEmail - Team invitations
  • SendEmail - Bulk emails from admin
  • ProcessCoSellEmailSequences - CoSell partnership sequences

Payment Gateways

All payment gateways dispatch SendPaymentConfirmationEmail job: - Stripe - PayPal - Iyzico - Paystack - Coingate - 2Checkout - RevenueCat - Free (trial activations)

Controllers

  • MailController - Password reset requests
  • EmailTemplatesController - Admin bulk sending
  • UserController - User invitations
  • TeamController - Team invitations
  • AuthenticatedSessionController - OTP login emails

Event Listeners (Marketplace)

  • Compliance notifications
  • Ready-to-submit notifications

Troubleshooting

Variable Not Showing Value

  1. Check if variable is defined in EmailVariable enum
  2. Verify context is being passed correctly
  3. Check user object has required properties
  4. Look for errors in logs (storage/logs/laravel.log)

Template Not Found

  1. Verify slug matches exactly
  2. Check database has template with that slug
  3. Use EmailService::getTemplate() with fallback

Preview Not Working

Use the preview feature in EmailService:

$preview = EmailService::previewTemplate($template, 'payment');
echo $preview;

Best Practices

  1. Always use EmailService for variable replacement
  2. Don't hard-code URLs - use variables like {site_url}
  3. Test emails before deploying to production
  4. Use meaningful variable names when adding new ones
  5. Document new variables in enum descriptions
  6. Group related variables in appropriate categories
  7. Validate templates before saving
  8. Use preview to test template rendering

Security Considerations

  • Template content is rendered with {!! !!} (unescaped)
  • Only admins can edit templates
  • User-provided data in variables is not sanitized
  • Be cautious with user-generated content in emails
  • Variables are resolved server-side, not client-side

Performance Notes

  • Templates are cached by Laravel
  • Variable resolution is fast (simple string replacement)
  • Jobs are queued for async sending
  • Payment emails use WithoutOverlapping middleware
  • Email sending doesn't block user requests

Future Enhancements

Possible improvements: - Email template versioning - A/B testing for email content - Email analytics (open rates, click rates) - Template inheritance/layouts - Conditional content in templates - Rich text editor for non-technical users - Email template gallery/marketplace

Support

For issues or questions: - Check logs in storage/logs/laravel.log - Review this documentation - Check EmailVariable enum for available variables - Use EmailService::validateTemplate() to check templates