⚠️ Documentation Under Review: This documentation is currently being updated and verified against the actual implementation. Some information may be incorrect or incomplete. Please verify all code examples against the actual source code before use.
The Neuron CMS provides an email system built on PHPMailer, supporting SMTP, Sendmail, and PHP mail() transports. The system features template-based email composition and test mode for development.
The email system consists of the following classes:
Neuron\Util\Email): Basic email class with simple methods for adding recipients and attachmentsNeuron\Cms\Services\Email\Sender): CMS-specific email service providing template rendering and PHPMailer integrationEmail configuration is defined in the email: section of config/neuron.yaml.
email:
driver: smtp # smtp, sendmail, or mail
from_address: [email protected]
from_name: Your Application Name
test_mode: false # Enable for development
email:
driver: smtp
host: smtp.gmail.com
port: 587
encryption: tls # or ssl for port 465
username: [email protected]
password: your-app-password
from_address: [email protected]
from_name: Your Application
Note: Gmail requires an App Password when 2FA is enabled.
email:
driver: smtp
host: smtp.sendgrid.net
port: 587
encryption: tls
username: apikey
password: SG.your-sendgrid-api-key
from_address: [email protected]
from_name: Your Application
email:
driver: smtp
host: email-smtp.us-east-1.amazonaws.com
port: 587
encryption: tls
username: your-ses-smtp-username
password: your-ses-smtp-password
from_address: [email protected]
from_name: Your Application
email:
driver: smtp
host: smtp.mailgun.org
port: 587
encryption: tls
username: [email protected]
password: your-mailgun-smtp-password
from_address: [email protected]
from_name: Your Application
email:
driver: smtp
host: smtp.office365.com
port: 587
encryption: tls
username: [email protected]
password: your-password
from_address: [email protected]
from_name: Your Name
email:
driver: sendmail
from_address: [email protected]
from_name: Your Application
email:
driver: mail
from_address: [email protected]
from_name: Your Application
Note: PHP mail() is not recommended for production due to reliability and deliverability issues.
Enable test mode during development to log emails instead of sending:
email:
driver: smtp
host: smtp.gmail.com
port: 587
encryption: tls
username: [email protected]
password: your-app-password
from_address: [email protected]
from_name: Your Application
test_mode: true # Emails logged instead of sent
When test mode is enabled:
The CMS provides pre-built email templates located in resources/views/emails/:
resources/views/emails/
├── email-verification.php # Email verification
├── password-reset.php # Password reset
└── welcome.php # Welcome email
Template: emails/welcome
Usage Example:
use Neuron\Cms\Services\Email\Sender;
$sender = new Sender( $settingManager, $basePath );
$sender->to( '[email protected]' )
->subject( 'Welcome!' )
->template( 'emails/welcome', [
'name' => 'John Doe',
'username' => 'johndoe',
'email' => '[email protected]',
'site_name' => 'Your Application'
] )
->send();
Template: emails/password-reset
Usage Example:
$sender->to( $user->getEmail() )
->subject( 'Password Reset Request' )
->template( 'emails/password-reset', [
'name' => $user->getName(),
'reset_url' => "https://example.com/reset-password?token={$token}",
'expiry_time' => '1 hour',
'site_name' => 'Your Application'
])
->send();
Template: emails/email-verification
Usage Example:
$sender->to( $user->getEmail() )
->subject( 'Verify Your Email' )
->template( 'emails/email-verification', [
'name' => $user->getName(),
'verification_url' => "https://example.com/verify?token={$token}",
'site_name' => 'Your Application'
])
->send();
Templates are PHP files that use extracted variables:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title><?= htmlspecialchars( $subject ?? 'Email' ) ?></title>
<style>
body { font-family: Arial, sans-serif; }
.container { max-width: 600px; margin: 0 auto; }
</style>
</head>
<body>
<div class="container">
<h1>Welcome, <?= htmlspecialchars( $name ) ?>!</h1>
<p>Thank you for registering.</p>
</div>
</body>
</html>
resources/views/emails/$sender->template( 'emails/your-template', $variables )->send();
The Sender service provides template support and PHPMailer integration:
use Neuron\Cms\Services\Email\Sender;
use Neuron\Data\Settings\SettingManager;
// Initialize sender
$sender = new Sender( $settingManager, $basePath );
// Simple email
$sender->to( '[email protected]' )
->subject( 'Test Email' )
->body( '<h1>Hello</h1><p>This is a test email.</p>' )
->send();
// Email with template
$sender->to( '[email protected]' )
->subject( 'Welcome!' )
->template( 'emails/welcome', [
'name' => 'John Doe',
'site_name' => 'Your App'
] )
->send();
// Single recipient
$sender->to( '[email protected]' );
$sender->to( '[email protected]', 'User Name' );
// CC recipients
$sender->cc( '[email protected]' );
$sender->cc( '[email protected]', 'Manager Name' );
// BCC recipients
$sender->bcc( '[email protected]' );
$sender->bcc( '[email protected]', 'Admin Name' );
Note: Methods can be chained but each call adds a recipient (doesn't replace).
// Set reply-to address
$sender->replyTo( '[email protected]' );
$sender->replyTo( '[email protected]', 'Support Team' );
// Set subject
$sender->subject( 'Your Order Confirmation' );
// HTML body
$sender->body( '<h1>Order Confirmed</h1><p>Thank you.</p>' );
// Plain text body
$sender->body( 'Order Confirmed\n\nThank you.', false );
// Use template
$sender->template( 'emails/welcome', ['name' => 'John'] );
// Add file attachment
$sender->attach( '/path/to/file.pdf' );
$sender->attach( '/path/to/file.pdf', 'Invoice.pdf' );
// Chain multiple attachments
$sender->attach( '/path/to/file1.pdf', 'Document1.pdf' )
->attach( '/path/to/file2.pdf', 'Document2.pdf' );
use Neuron\Cms\Services\Email\Sender;
use Neuron\Log\Log;
$sender = new Sender( $settingManager );
try
{
$result = $sender->to( '[email protected]' )
->cc( '[email protected]' )
->bcc( '[email protected]' )
->subject( 'Order #12345 Confirmation' )
->template( 'emails/welcome', [
'name' => 'John Doe',
'site_name' => 'Your Store'
] )
->attach( '/path/to/invoice.pdf', 'Invoice-12345.pdf' )
->send();
if( $result )
{
echo "Email sent successfully";
}
else
{
echo "Failed to send email";
}
}
catch( \Exception $e )
{
echo "Error: " . $e->getMessage();
}
The email system logs sent emails through the Neuron Log system.
Successful email sends are logged at INFO level:
[2025-11-27 10:30:15] Email sent to: [email protected]
Failed sends are logged at ERROR level:
[2025-11-27 10:30:15] Email send failed: Authentication failed
Test mode emails are logged:
[2025-11-27 10:30:15] TEST MODE - Email not sent
[2025-11-27 10:30:15] To: [email protected]
[2025-11-27 10:30:15] Subject: Welcome!
[2025-11-27 10:30:15] Body: Welcome to our platform...
Test mode allows email development without sending actual emails.
email:
test_mode: true
When test mode is enabled:
The framework also provides a basic Email class with minimal functionality:
use Neuron\Util\Email;
$email = new Email();
$email->addTo( '[email protected]' );
$email->addCC( '[email protected]' );
$email->addBCC( '[email protected]' );
$email->attachFile( '/path/to/file.pdf' );
$email->setFrom( '[email protected]' );
$email->setSubject( 'Test Subject' );
$email->setBody( 'Email body content' );
$email->setType( Email::EMAIL_HTML ); // or EMAIL_TEXT
// Note: This class doesn't have a send() method
// It's a data structure for email information
Note: The Sender class is recommended over the basic Email class as it provides actual sending functionality via PHPMailer.
Configure DNS records to improve deliverability:
TXT @ "v=spf1 include:_spf.google.com ~all"
Configure through your email provider's settings.
TXT _dmarc "v=DMARC1; p=quarantine; rua=mailto:[email protected]"
PHPMailer automatically sanitizes email addresses and headers to prevent injection attacks.
Never include in emails:
Instead:
Protect SMTP credentials:
Use environment variables:
// In config/neuron.yaml
email:
password: ${SMTP_PASSWORD}
Exclude from version control
Rotate credentials regularly
Symptom: Failed to send email with connection error
Solutions:
telnet smtp.gmail.com 587Solutions:
Solutions:
Symptom: RuntimeException: Email template not found
Solutions:
resources/views/emails/emails/template-name)Always use templates for consistent formatting:
// Good - uses template
$sender->template( 'emails/welcome', $variables );
// Avoid - inline HTML
$sender->body( '<html>...</html>' );
Always wrap email sending in try-catch:
try
{
$sender->to( $email )->template( 'emails/welcome', $vars )->send();
}
catch( \Exception $e )
{
Log::error( "Failed to send welcome email: " . $e->getMessage() );
// Don't block user flow due to email failure
}
Validate before sending:
if( !filter_var( $email, FILTER_VALIDATE_EMAIL ) )
{
throw new \InvalidArgumentException( "Invalid email: $email" );
}
Test templates across different email clients:
Prevent abuse with rate limiting:
// Example using cache
$key = "email_reset:{$userId}";
$attempts = $cache->get( $key, 0 );
if( $attempts >= 3 )
{
throw new \Exception( 'Too many attempts. Try again later.' );
}
$sender->send();
$cache->set( $key, $attempts + 1, 3600 ); // 1 hour
The current email implementation has these limitations:
For advanced email features, consider extending the Sender class or implementing a custom email service.