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¶
- EmailVariable Enum (
app/Enums/EmailVariable.php) - Defines all available template variables
- Provides variable resolution logic
- Organizes variables by category
-
Includes descriptions for documentation
-
EmailService (
app/Services/EmailService.php) - Centralized email processing service
- Handles template variable replacement
- Provides template validation
-
Offers preview functionality
-
Email Templates (Database-driven)
- Stored in
email_templatestable - Managed through admin panel (
/dashboard/email-templates) - 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
Legal & Preferences¶
{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¶
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¶
- Go to
/dashboard/email-templates - Click "Create New Template"
- Fill in:
- Title
- Subject (supports variables)
- Content (HTML with variables)
- Use variables from the list shown below the editor
- 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 (
EmailVariableenum) - ✅ 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:
- 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',
- 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 confirmationSendInviteEmail- User invitationsSendPasswordResetEmail- Password resetSendPaymentConfirmationEmail- Payment/subscription confirmationSendTeamInviteEmail- Team invitationsSendEmail- Bulk emails from adminProcessCoSellEmailSequences- 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 requestsEmailTemplatesController- Admin bulk sendingUserController- User invitationsTeamController- Team invitationsAuthenticatedSessionController- OTP login emails
Event Listeners (Marketplace)¶
- Compliance notifications
- Ready-to-submit notifications
Troubleshooting¶
Variable Not Showing Value¶
- Check if variable is defined in
EmailVariableenum - Verify context is being passed correctly
- Check user object has required properties
- Look for errors in logs (
storage/logs/laravel.log)
Template Not Found¶
- Verify slug matches exactly
- Check database has template with that slug
- Use
EmailService::getTemplate()with fallback
Preview Not Working¶
Use the preview feature in EmailService:
Best Practices¶
- Always use EmailService for variable replacement
- Don't hard-code URLs - use variables like
{site_url} - Test emails before deploying to production
- Use meaningful variable names when adding new ones
- Document new variables in enum descriptions
- Group related variables in appropriate categories
- Validate templates before saving
- 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
WithoutOverlappingmiddleware - 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