Docs

Mail

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:install

1.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.com

2 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 OrderConfirmation

3.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

 
 
MethodDescriptionExample
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 newsletters

5.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 jobs

6 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.com

7 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.mlc

8 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/keys

9 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:purge

Command Summary

 
 
CommandDescriptionExample
mail:test <email>Send test emailmail:test user@example.com
make:mail <name>Generate Mailable classmake:mail WelcomeMail
mail:installInstall package scaffoldingmail:install
make:dkim-pkey <dir>Generate DKIM keysmake:dkim-pkey storage/keys
mail:work [queue]Process queued jobsmail:work high-priority
mail:list [queue]List pending jobsmail:list newsletters
mail:failedList failed jobsmail:failed
mail:retry <id|--all>Retry failed job(s)mail:retry --all
mail:clear [queue]Clear pending jobsmail:clear
mail:flushDelete failed jobsmail:flush
mail:purgeDelete all jobsmail: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.com

3. 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.com

11 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 debugging

13.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 newslettersa

License

MIT © 2025 MonkeysCloud