diego-mascarenhas / emailer
Professional email marketing package with maximum deliverability.
Fund package maintenance!
diego-mascarenhas
Requires
- php: ^8.1
- illuminate/contracts: ^10.0||^11.0||^12.0
- spatie/laravel-package-tools: ^1.16
- tijsverkoyen/css-to-inline-styles: ^2.2
Requires (Dev)
- larastan/larastan: ^3.0
- laravel/pint: ^1.14
- nunomaduro/collision: ^8.8
- orchestra/testbench: ^10.0.0||^9.0.0
- pestphp/pest: ^4.0
- pestphp/pest-plugin-arch: ^4.0
- pestphp/pest-plugin-laravel: ^4.0
- phpstan/extension-installer: ^1.4
- phpstan/phpstan-deprecation-rules: ^2.0
- phpstan/phpstan-phpunit: ^2.0
- spatie/laravel-ray: ^1.35
Suggests
- mailgun/mailgun-php: Required for Mailgun email provider support
- sendgrid/sendgrid: Required for SendGrid email provider support
README
Professional email marketing package for Laravel with maximum deliverability, advanced tracking, and multi-provider support.
Features
✨ Multi-Provider Support: SMTP, Mailgun, SendGrid, MailBaby with automatic fallback
📊 Advanced Analytics: Open rates, click tracking, bounce tracking, and detailed statistics
⚡ Queue-Based Processing: Scalable email delivery with configurable delays
🎯 Team-Based Configuration: Per-team email settings and branding
📈 Real-time Tracking: Pixel tracking for opens and click tracking for links
🔄 Webhook Integration: Automatic status updates from email providers
🎨 Template Support: Rich HTML templates with variable replacement
📱 Responsive Design: Mobile-optimized email templates
🛡️ Spam Prevention: Built-in delays and best practices for deliverability
Installation
You can install the package via composer:
composer require idoneo/emailer
You can publish and run the migrations with:
php artisan vendor:publish --tag="emailer-migrations"
php artisan migrate
You can publish the config file with:
php artisan vendor:publish --tag="emailer-config"
This is the contents of the published config file:
return [ 'email_provider' => env('EMAILER_PROVIDER', 'smtp'), 'queue_name' => env('EMAILER_QUEUE', 'emailer'), 'delays' => [ 'base_minutes' => env('EMAILER_DELAY_BASE_MINUTES', 5), 'random_seconds' => env('EMAILER_DELAY_RANDOM_SECONDS', 120), ], // ... more configuration options ];
Basic Usage
Creating a Message Campaign
use idoneo\Emailer\Models\Message; use idoneo\Emailer\Models\MessageType; use idoneo\Emailer\Facades\Emailer; // Create a message type $messageType = MessageType::create([ 'name' => 'Newsletter', 'status' => 1 ]); // Create a message $message = Message::create([ 'name' => 'Welcome Newsletter', 'subject' => 'Welcome to our platform!', 'content' => '<h1>Welcome {{name}}!</h1><p>Thank you for joining us.</p>', 'type_id' => $messageType->id, 'team_id' => auth()->user()->currentTeam->id, 'status_id' => 1 ]); // Start the campaign Emailer::startCampaign($message);
Sending Test Emails
// Send a test email Emailer::sendTest($message, 'test@example.com', 'Test User');
Getting Campaign Statistics
$stats = Emailer::getCampaignStats($message); echo "Total sent: " . $stats['sent']; echo "Open rate: " . $stats['open_rate'] . "%"; echo "Click rate: " . $stats['click_rate'] . "%";
Configuration
Environment Variables
Add these variables to your .env
file:
# Email Provider Configuration EMAILER_PROVIDER=smtp # smtp|mailgun|sendgrid|mailbaby EMAILER_FALLBACK_TO_SMTP=true # Fallback to SMTP if provider fails # Queue Configuration EMAILER_QUEUE=emailer # Queue name for email jobs # Delay Configuration (Anti-spam) EMAILER_DELAY_BASE_MINUTES=5 # Minutes between emails EMAILER_DELAY_RANDOM_SECONDS=120 # Random seconds added # Default Email Settings EMAILER_FROM_ADDRESS=noreply@example.com EMAILER_FROM_NAME="Your Company" EMAILER_REPLY_TO_ADDRESS=support@example.com # Tracking EMAILER_TRACKING_ENABLED=true EMAILER_OPEN_TRACKING=true EMAILER_CLICK_TRACKING=true # Provider-specific settings MAILGUN_DOMAIN=mg.example.com MAILGUN_SECRET=key-xxxxx SENDGRID_API_KEY=SG.xxxxx MAILBABY_API_KEY=xxxxx MAILBABY_API_URL=https://api.mailbaby.net
Team-Based Configuration
The package supports team-based email configuration. Each team can have its own SMTP settings:
// In your Team model, implement these methods: public function hasOutgoingEmailConfig(): bool { return $this->getSetting('mail_host') !== null; } public function getOutgoingEmailConfig(): array { return [ 'host' => $this->getSetting('mail_host'), 'port' => $this->getSetting('mail_port', 587), 'username' => $this->getSetting('mail_username'), 'password' => $this->getSetting('mail_password'), 'encryption' => $this->getSetting('mail_encryption', 'tls'), 'from_address' => $this->getSetting('mail_from_address'), 'from_name' => $this->getSetting('mail_from_name'), ]; }
Commands
Send Pending Messages
Process pending message deliveries:
# Send all pending messages php artisan emailer:send-pending # Limit the number of messages processed php artisan emailer:send-pending --limit=50 # Send for specific team only php artisan emailer:send-pending --team=123 # Dry run (show what would be sent) php artisan emailer:send-pending --dry-run
Email Tracking
The package includes comprehensive tracking features:
Open Tracking
Automatically tracks when recipients open emails using invisible tracking pixels.
Click Tracking
Tracks clicks on links within emails by automatically replacing URLs with tracked versions.
Webhook Support
Receives real-time updates from email providers:
- Mailgun:
/emailer/webhook/mailgun
- SendGrid:
/emailer/webhook/sendgrid
- MailBaby:
/emailer/webhook/mailbaby
Advanced Usage
Custom Email Providers
Extend the package to support additional email providers:
// In your SendMessageCampaignJob extension protected function sendViaCustomProvider() { // Implement your custom provider logic }
Template Variables
The package supports template variables that are automatically replaced:
$message = Message::create([ 'content' => '<h1>Hello {{name}}!</h1><p>Your email is {{email}}</p>', // ... ]);
Available variables:
{{name}}
- Contact name{{email}}
- Contact email- Add custom variables by extending the
getHtmlForContact()
method
Model Relationships
The package assumes certain relationships exist in your application:
// Your Team model should have: public function messages() { return $this->hasMany(\idoneo\Emailer\Models\Message::class); } // Your Contact model should have: public function messageDeliveries() { return $this->hasMany(\idoneo\Emailer\Models\MessageDelivery::class); } // Your Category model should have: public function messages() { return $this->hasMany(\idoneo\Emailer\Models\Message::class); }
Performance
Queue Workers
Make sure you have queue workers running to process email jobs:
php artisan queue:work --queue=emailer
Database Indexing
The package includes optimized database indexes for performance. For large volumes, consider:
- Partitioning delivery tables by date
- Archiving old delivery records
- Using read replicas for analytics queries
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Security Vulnerabilities
Please review our security policy on how to report security vulnerabilities.
Credits
License
The MIT License (MIT). Please see License File for more information.