A powerful, feature-rich mail package for the MonkeysLegion PHP framework, providing robust email functionality with DKIM signing, queue support, rate limiting, and elegant template rendering.
What's Inside
This comprehensive mail package includes everything you need for professional email handling:
Getting Started
Quick Installation: Automated setup with scaffolding
Configuration: Environment variables and driver setup
First Email: Send your first email in minutes
Core Email Features
Multiple Transports: SMTP, Sendmail, Mailgun, and Null drivers
Direct Sending: Immediate email delivery
Queue System: Background email processing with Redis
Rate Limiting: Prevent spam and control sending limits
Security & Authentication
DKIM Signing: Digital signatures for email authentication
SPF/DMARC Ready: Compatible with modern email security
Raw Key Support: Simplified DKIM key management
Template System
Mailable Classes: Object-oriented email composition
ML View Engine: Powerful template rendering
Email Components: Reusable UI components
Dynamic Content: Data binding and conditional rendering
Advanced Features
CLI Commands: Command-line email management
Queue Management: Job retry, failure handling
Logging: Comprehensive PSR-3 compatible logging
Events: Email lifecycle tracking
Developer Tools
Make Commands: Generate mail classes instantly
Testing Tools: Test email sending without queues
Debug Mode: Detailed logging and error reporting
1 Quick Start
1.1 Installation
# Install Monkeys Legion App
composer create-project --stability=dev monkeyscloud/monkeyslegion-skeleton my-app "dev-main"
# Install Mail package
composer require monkeyscloud/monkeyslegion-mail
# Publish configuration and scaffolding
php ml mail:install1.2 Basic Configuration
Add these variables to your .env file:
# Basic SMTP Configuration
MAIL_DRIVER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME=your-email@gmail.com
MAIL_PASSWORD=your-app-password
MAIL_ENCRYPTION=tls
# OR Mailgun Configuration
MAILGUN_API_KEY=YOUR_MAILGUN_API_KEY
MAILGUN_DOMAIN=YOUR_MAILGUN_DOMAIN
# DKIM Configuration (Optional but Recommended)
MAIL_DKIM_PRIVATE_KEY=your-raw-private-key-without-headers
MAIL_DKIM_SELECTOR=default
MAIL_DKIM_DOMAIN=yourdomain.com
# Queue Configuration (Optional but required in queueing)
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
QUEUE_DEFAULT=emails
# A Global Configuration
MAIL_FROM_ADDRESS=your-email@gmail.com
MAIL_FROM_NAME="Your App Name"1.3 Test Your Setup
# Test email sending
php ml mail:test your-email@example.com2 Sending Emails
2.1 Direct Sending
<?php
use MonkeysLegion\Mail\Mailer;
// Get mailer instance
/** @var Mailer */
$mailer = ML_CONTAINER->get(Mailer::class);
// Send immediately
$mailer->send(
'user@example.com',
'Welcome to Our App',
'<h1>Welcome!</h1><p>Thanks for joining us.</p>',
'text/html'
);2.2 Queue-Based Sending
<?php
// Queue for background processing (required env redis vars)
$jobId = $mailer->queue(
'user@example.com',
'Welcome to Our App',
'<h1>Welcome!</h1><p>Thanks for joining us.</p>',
'text/html'
);
echo "Email queued with job ID: $jobId";2.3 Using Mailable Classes
# Generate a new mailable class
php ml make:mail WelcomeMail<?php
// Use the generated class
use App\Mail\WelcomeMail;
$mail = new WelcomeMail();
$mail->setTo('user@example.com')
->setViewData(['name' => 'John Doe'])
->send(); // or ->queue()3 Mailable Classes
Mailable classes provide an elegant, object-oriented way to compose emails with templates, data binding, and fluent configuration.
3.1 Creating a Mailable
# Generate a new mailable class
php ml make:mail OrderConfirmation3.2 Example Mailable Class
<?php
namespace App\Mail;
use MonkeysLegion\Mail\Mail\Mailable;
class OrderConfirmationMail extends Mailable
{
public function __construct(
private array $order,
private array $customer
) {
parent::__construct();
}
public function build(): self
{
return $this->view('emails.order-confirmation')
->subject('Order Confirmation #' . $this->order['id'])
->withData([
'order' => $this->order,
'customer' => $this->customer,
'total' => $this->order['total']
])
->attach('/path/to/invoice.pdf');
}
}3.3 Using Mailable Classes
<?php
// Create and send
$order = ['id' => 12345, 'total' => 99.99];
$customer = ['name' => 'John Doe', 'email' => 'john@example.com'];
$mail = new OrderConfirmationMail($order, $customer);
// Send immediately
$mail->setTo('john@example.com')->send();
// Or queue for background processing
$jobId = $mail->setTo('john@example.com')->queue();
// Configure dynamically
$mail->setTo('john@example.com')
->setSubject('Custom Subject')
->onQueue('high-priority')
->send();4 Mailable Features
4.1 Template Binding
<?php
public function build(): self
{
// emails.welcome => root/resources/views/emails/welcome.ml.php
return $this->view('emails.welcome', [
'user' => $this->user,
'loginUrl' => 'https://app.com/login'
]);
}4.2 Overridable Properties
<?php
class OrderConfirmationMail extends Mailable
{
// Queue configuration
protected ?string $queue = 'orders';
protected ?int $timeout = 120;
protected ?int $maxTries = 5;
// Content settings
protected string $contentType = 'text/html';
// Runtime methods also available
public function build(): self
{
return $this->view('emails.order')
->setTimeout(180) // Override timeout
->setMaxTries(3) // Override max tries
->setContentType('text/html') // Override content type
->addAttachment('/path/to/invoice.pdf');
}
}4.3 Available Configuration Methods
| Method | Description | Example |
|---|---|---|
setTimeout(int $timeout) | Set job timeout in seconds | ->setTimeout(120) |
setMaxTries(int $tries) | Set maximum retry attempts | ->setMaxTries(5) |
setContentType(string $type) | Set content type | ->setContentType('text/plain') |
addAttachment(string $path, ?string $name, ?string $mime) | Add file attachment | ->addAttachment('/path/file.pdf', 'Invoice.pdf') |
setAttachments(array $attachments) | Set all attachments | ->setAttachments($fileArray) |
4.4 Attachments
<?php
public function build(): self
{
return $this->view('emails.newsletter')
->addAttachment('/path/to/file.pdf', 'Newsletter.pdf')
->setAttachments([
'/path/to/direct-file.pdf', // simple string path or URL
'https://example.com/file.pdf', // URL as string
['path' => '/path/file1.pdf', 'name' => 'File1.pdf'],
['path' => '/path/file2.pdf', 'mime_type' => 'application/pdf'],
['path' => 'https://example.com/file3.pdf', 'name' => 'File3.pdf', 'mime_type' => 'application/pdf']
]);
}4.5 Conditional Logic
<?php
public function build(): self
{
return $this->view('emails.notification')
->when($this->user->isPremium(), function($mail) {
$mail->addAttachment('/path/to/premium-guide.pdf');
})
->unless($this->user->hasSeenWelcome(), function($mail) {
$mail->withData(['showWelcome' => true]);
});
}5 Queue System
The queue system allows you to send emails in the background, improving application performance and providing retry capabilities.
5.1 Example Queue Workflow
<?php
// In your application
$jobId = $mailer->queue(
'user@example.com',
'Newsletter',
$htmlContent,
'text/html',
[], // attachments
'newsletters' // specific queue
);
// Start worker (separate process)
// php ml mail:work newsletters5.1 Queue Monitoring
# Monitor queue status
php ml mail:list
# Check for failed jobs
php ml mail:failed
# Get queue statistics
redis-cli llen queue:emails # Pending jobs
redis-cli llen queue:failed # Failed jobs6 CLI Commands
The mail package includes powerful CLI commands for testing, queue management, code generation, and maintenance.
6.1 Email Testing
# Test email sending (bypasses queue)
php ml mail:test user@example.com7 Installation & Setup
# Install Mail package scaffolding
php ml mail:install
# This command will:
# - Publish configuration files
# - Create email template examples
# - Add environment variables to .env
# - Configure config/app.mlc8 DKIM Key Generation
# Generate DKIM private and public key files in the specified directory
php ml make:dkim-pkey <directory>
# Example:
php ml make:dkim-pkey storage/keys9 Queue Management
# Start processing queued emails
php ml mail:work
# Work on specific queue
php ml mail:work high-priority
# List pending jobs in default queue
php ml mail:list
# List pending jobs in specific queue
php ml mail:list newsletters
# List failed jobs
php ml mail:failed
# Retry specific failed job
php ml mail:retry job_12345
# Retry all failed jobs
php ml mail:retry --all
# Clear pending jobs from default queue
php ml mail:clear
# Clear pending jobs from specific queue
php ml mail:clear newsletters
# Delete all failed jobs
php ml mail:flush
# Delete ALL jobs (pending + failed)
php ml mail:purgeCommand Summary
| Command | Description | Example |
|---|---|---|
mail:test <email> | Send test email | mail:test user@example.com |
make:mail <name> | Generate Mailable class | make:mail WelcomeMail |
mail:install | Install package scaffolding | mail:install |
make:dkim-pkey <dir> | Generate DKIM keys | make:dkim-pkey storage/keys |
mail:work [queue] | Process queued jobs | mail:work high-priority |
mail:list [queue] | List pending jobs | mail:list newsletters |
mail:failed | List failed jobs | mail:failed |
mail:retry <id|--all> | Retry failed job(s) | mail:retry --all |
mail:clear [queue] | Clear pending jobs | mail:clear |
mail:flush | Delete failed jobs | mail:flush |
mail:purge | Delete all jobs | mail:purge |
10 DKIM Email Signing
DKIM (DomainKeys Identified Mail) adds digital signatures to your emails, improving deliverability and preventing spoofing.
10.1 Setting Up DKIM
1. Generate DKIM Keys
<?php
use MonkeysLegion\Mail\Security\DkimSigner;
// Generate a new key pair
$keys = DkimSigner::generateKeys(2048);
echo "Private Key:\n" . $keys['private'] . "\n\n";
echo "Public Key:\n" . $keys['public'];2. Configure Environment
# Use raw private key without BEGIN/END headers
MAIL_DKIM_PRIVATE_KEY=MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAMODcNBCB7...
MAIL_DKIM_SELECTOR=default
MAIL_DKIM_DOMAIN=yourdomain.com3. Add DNS Record
Create a TXT record in your DNS:
Name: default._domainkey.yourdomain.com
Value: v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDA4...4. Verify DKIM
# Test DKIM signing
php ml mail:test test@gmail.com11 Configuration
Driver Configuration
SMTP Driver
<?php
'smtp' => [
'host' => $_ENV['MAIL_HOST'] ?? 'smtp.mailtrap.io',
'port' => $_ENV['MAIL_PORT'] ?? 587,
'encryption' => $_ENV['MAIL_ENCRYPTION'] ?? 'tls', // tls / ssl / null
'username' => $_ENV['MAIL_USERNAME'] ?? '',
'password' => $_ENV['MAIL_PASSWORD'] ?? '',
'timeout' => $_ENV['MAIL_TIMEOUT'] ?? 30,
'from' => [
'address' => $_ENV['MAIL_FROM_ADDRESS'] ?? 'noreply@yourapp.com',
'name' => $_ENV['MAIL_FROM_NAME'] ?? 'My App'
],
'dkim_private_key' => $_ENV['MAIL_DKIM_PRIVATE_KEY'] ?? '',
'dkim_selector' => $_ENV['MAIL_DKIM_SELECTOR'] ?? 'default',
'dkim_domain' => $_ENV['MAIL_DKIM_DOMAIN'] ?? '',
],Mailgun Driver
<?php
'mailgun' => [
'api_key' => $_ENV['MAILGUN_API_KEY'] ?? '',
'domain' => $_ENV['MAILGUN_DOMAIN'] ?? '',
'from' => [
'address' => $_ENV['MAIL_FROM_ADDRESS'] ?? 'noreply@yourdomain.com',
'name' => $_ENV['MAIL_FROM_NAME'] ?? 'Your App',
],
// Optional tracking options (used by addOptionalParameters)
'tracking' => [
'clicks' => filter_var($_ENV['MAILGUN_TRACK_CLICKS'] ?? true, FILTER_VALIDATE_BOOLEAN),
'opens' => filter_var($_ENV['MAILGUN_TRACK_OPENS'] ?? true, FILTER_VALIDATE_BOOLEAN),
],
// Optional delivery time in RFC2822 or ISO 8601 format
'delivery_time' => $_ENV['MAILGUN_DELIVERY_TIME'] ?? null,
// Optional array of tags (Mailgun supports up to 3 tags per message)
'tags' => explode(',', $_ENV['MAILGUN_TAGS'] ?? ''), // e.g. "welcome,new-user"
// Optional custom variables to include with the message
'variables' => [
// Dynamically assign or leave empty if not used
],
// Mailgun region (us or eu)
'region' => $_ENV['MAILGUN_REGION'] ?? 'us',
// Optional timeouts
'timeout' => ($_ENV['MAILGUN_TIMEOUT'] ?? 30),
'connect_timeout' => ($_ENV['MAILGUN_CONNECT_TIMEOUT'] ?? 10),
// DKIM signing as SMTP configuration
],Null Driver
<?php
'null' => [
'from' => [
'address' => $_ENV['MAIL_FROM_ADDRESS'] ?? 'noreply@yourdomain.com',
'name' => $_ENV['MAIL_FROM_NAME'] ?? 'Your App'
]
]Sendmail Driver
<?php
'sendmail' => [
'path' => $_ENV['MAIL_SENDMAIL_PATH'] ?? '/usr/sbin/sendmail',
'from' => [
'address' => $_ENV['MAIL_FROM_ADDRESS'] ?? 'noreply@yourdomain.com',
'name' => $_ENV['MAIL_FROM_NAME'] ?? 'Your App'
],
// DKIM signing as SMTP configuration
],Rate Limiting
Configure rate limiting in config/rate_limiter.php:
<?php
return [
'key' => 'mail', // Unique identifier
'limit' => 100, // Max emails per window
'seconds' => 60, // Time window (seconds)
'storage_path' => '/mail', // Storage location
];12 Rate Limiting
Prevent spam and control email sending rates with built-in rate limiting.
12.1 Available Methods
<?php
use MonkeysLegion\Mail\RateLimiter\RateLimiter;
// Create rate limiter with config values
$rateLimiter = new RateLimiter('user_123', 100, 3600);
// Check remaining quota
$remaining = $rateLimiter->remaining(); // e.g., 85
// Get reset time
$resetTime = $rateLimiter->resetTime(); // seconds until reset
// Get configuration
$config = $rateLimiter->getConfig();
// Reset limit (admin function)
$rateLimiter->reset();
// Clean old records (scheduled task)
$stats = RateLimiter::cleanupAll('/tmp');12.2 Scheduled Cleanup
Add to your cron jobs:
# Clean up old rate limit records every hour
0 * * * * php /path/to/cleanup-rate-limits.php<?php
// cleanup-rate-limits.php
use MonkeysLegion\Mail\RateLimiter\RateLimiter;
$results = RateLimiter::cleanupAll('/tmp');
echo "Cleaned up " . $results['cleaned'] . " files\n";13 Logging
Comprehensive logging helps you monitor email delivery and debug issues. Logging behavior is controlled by your application mode in the .env file.
13.1 Configuration
# Application Mode (controls logging behavior)
APP_ENV=production # production, development, testing
# Debug Mode (enables detailed SMTP/DKIM logging)
MAIL_DEBUG=false # Set to true for debugging13.2 Log Levels by Environment
Production Mode (APP_ENV=prod)
INFO: Successful operations, performance metrics
WARNING: Rate limits, retry attempts
ERROR: Failed operations, configuration issues
CRITICAL: System failures requiring immediate attention
Development Mode (APP_ENV=dev)
DEBUG: Detailed SMTP communication, DKIM signing process
INFO: All successful operations with timing data
WARNING: Non-critical issues and suggestions
ERROR: Failed operations with full stack traces
Testing Mode (APP_ENV=test)
ERROR: Only failures and critical issues
INFO: Test-specific events and assertions
13.3 Log Examples
# Successful send (Production)
[Log TimeStamp] app.INFO Email sent successfully {
"to": "user@example.com",
"subject": "Welcome",
"duration_ms": 1250,
"driver": "SmtpTransport"
}
# DKIM signing (Development)
[Log TimeStamp] app.DEBUG DKIM signature generated {
"domain": "yourdomain.com",
"selector": "default",
"signature_length": 344,
"headers_signed": ["From", "To", "Subject", "Date", "Message-ID"]
}
# Queue processing (All modes)
[Log TimeStamp] app.INFO Job processed successfully {
"job_id": "job_64f8a2b1c3d4e",
"duration_ms": 890,
"memory_usage_mb": 15.2,
"queue": "emails"
}
# Rate limiting (Production)
[Log TimeStamp] app.WARNING Rate limit exceeded {
"key": "user_123",
"limit": 100,
"window": 3600,
"remaining_reset_time": 1845
}
# SMTP Debug (Development only)
[Log TimeStamp] app.DEBUG SMTP command sent {
"command": "MAIL FROM:<sender@example.com>",
"response_code": 250,
"response": "2.1.0 Ok"
}13.4 Custom Logging
<?php
use MonkeysLegion\Mail\Logger\Logger;
$logger = ML_CONTAINER->get(Logger::class);
// Log custom events
$logger->log("Custom email campaign started", [
'campaign_id' => 'summer2024',
'recipient_count' => 1000,
'estimated_duration' => '5 minutes'
]);14 Advanced Usage
14.1 Multiple Drivers
<?php
// Switch drivers at runtime
$mailer->useSmtp(['host' => 'smtp.mailgun.org']);
$mailer->send($to, $subject, $content);
$mailer->useSendmail();
$mailer->send($to, $subject, $content);
$mailer->useNull();
$mailer->send($to, $subject, $content);14.2 Bulk Email Processing
<?php
// Queue multiple emails efficiently
$recipients = ['user1@example.com', 'user2@example.com', 'user3@example.com'];
foreach ($recipients as $recipient) {
$mail = new NewsletterMail($content);
$mail->setTo($recipient)
->onQueue('newsletters')
->queue();
}
// Process with dedicated worker
// php ml mail:work newslettersaLicense
MIT © 2025 MonkeysCloud