nette/mail
Lightweight PHP library for composing and sending email. Build MIME messages with attachments and embedded content, handle headers and encodings, and deliver via SMTP or PHP mail. Integrates easily into apps and frameworks.
composer require nette/mail
config/mail.php (extend Laravel’s default):
'mailers' => [
'nette' => [
'transport' => 'smtp',
'host' => env('MAIL_HOST'),
'port' => env('MAIL_PORT'),
'username' => env('MAIL_USERNAME'),
'password' => env('MAIL_PASSWORD'),
'encryption' => env('MAIL_ENCRYPTION'),
'dkim' => [
'domain' => env('MAIL_DKIM_DOMAIN'),
'selector' => env('MAIL_DKIM_SELECTOR'),
'privateKey' => env('MAIL_DKIM_PRIVATE_KEY'),
],
'debugger' => env('APP_DEBUG'), // Enables Tracy Bar integration
],
],
AppServiceProvider:
public function register()
{
$this->app->singleton(\Nette\Mail\IMailer::class, function ($app) {
$config = config('mail.mailers.nette');
return new \Nette\Mail\SmtpMailer($config);
});
}
use Nette\Mail\Message;
use Nette\Mail\IMailer;
class SendTestEmail implements ShouldQueue
{
public function handle(IMailer $mailer)
{
$message = new Message();
$message->setFrom('noreply@example.com')
->addTo('dev@example.com')
->setSubject('Test Email')
->setHtmlBody('<h1>Hello from Nette Mail!</h1>');
$mailer->send($message);
}
}
Interceptor to redirect emails to dev@example.com (configured via mail.redirect in DI).mail.headers: true in config to ensure signing works.debugger: true for Tracy Bar integration (visible in Laravel’s /debugbar if using barryvdh/laravel-debugbar).Laravel Mailable Integration:
Extend Laravel’s Mailable to leverage Nette’s features:
use Nette\Mail\Message as NetteMessage;
use Nette\Mail\IMailer;
class NetteMailable extends Mailable
{
public function build()
{
$message = new NetteMessage();
$message->setFrom(config('mail.from.address'))
->addTo($this->recipient)
->setSubject($this->subject);
// HTML + Plaintext (automatically generated from HTML)
$message->setHtmlBody($this->htmlContent)
->setTextBody($this->textContent ?? $message->buildText());
// Attachments
if ($this->attachment) {
$message->addAttachment($this->attachment, 'filename.pdf');
}
// Inline CSS (for Outlook compatibility)
$message->setHtmlBody((new \Nette\Mail\HtmlComposer())
->inlineCss($message->getHtmlBody())
->getHtml());
return $message;
}
public function send(IMailer $mailer)
{
$mailer->send($this->build());
}
}
Key Methods:
| Method | Use Case | Example |
|---|---|---|
setHtmlBody() |
HTML content with embedded images | setHtmlBody('<img src="cid:image1">') |
addInlinePart() |
Embed images/videos | $message->addInlinePart($image, 'image1') |
addAttachment() |
Files (PDFs, ZIPs) | addAttachment('file.pdf') |
HtmlComposer::inlineCss() |
Fix Outlook rendering | $composer->inlineCss($html) |
HtmlComposer::embedImages() |
Convert src="path/to/image" to CID |
$composer->embedImages(public_path()) |
| Transport | Laravel Equivalent | When to Use | Config Example |
|---|---|---|---|
SmtpMailer |
Mail::send() |
Production (Gmail, SendGrid, etc.) | host: smtp.gmail.com |
SendmailMailer |
mail() function |
Shared hosting (no SMTP access) | command: /usr/sbin/sendmail -t |
FallbackMailer |
Hybrid fallback | Dev/staging with multiple backends | mailers: [smtp, sendmail] |
Example: Hybrid Transport:
// config/mail.php
'mailers' => [
'hybrid' => [
'transport' => 'fallback',
'primary' => 'smtp',
'fallback' => 'sendmail',
'smtp' => [...],
'sendmail' => [...],
],
],
Interceptor for Dev:
// config/services.php
'mail.redirect' => env('APP_DEBUG') ? 'dev@example.com' : null,
X-Original-To headers.Tracy Bar Integration:
Enable in config/mail.php:
'debugger' => env('APP_DEBUG'),
barryvdh/laravel-debugbar).Local Testing:
Use Mail::fake() with a custom mailer:
Mail::fake();
$mailer = app(\Nette\Mail\IMailer::class);
$mailer->send($message);
// Assert
Mail::assertSent(NetteMailable::class);
Configure DKIM in config/mail.php:
'dkim' => [
'domain' => 'example.com',
'selector' => 'mail',
'privateKey' => file_get_contents(storage_path('dkim_private.key')),
'passPhrase' => env('DKIM_PASSPHRASE'),
],
Verify DKIM:
DKIM-Signature: v=1; a=rsa-sha256; ...
Authentication-Results: spf=pass (sender IP is 1.2.3.4) ...
Outlook-Compatible Emails:
use Nette\Mail\HtmlComposer;
$composer = new HtmlComposer();
$html = $composer
->inlineCss($rawHtml) // Converts `<style>` to inline styles
->embedImages(public_path()) // Converts `src="image.jpg"` to CID
->getHtml();
Common Pitfalls:
!important in CSS (use style attributes instead).bgcolor, width, and align attributes for Outlook 2013/2016.| Issue | Solution | Example Fix |
|---|---|---|
| Images not embedding | Spaces/parentheses in src paths |
Use $composer->embedImages(base_path()) |
| CSS inlining fails | Complex selectors (e.g., :hover) |
Simplify CSS or use CssInliner |
| DKIM validation fails | Incorrect domain or selector |
Verify with openssl dkim -v |
| Large base64 URIs crash | Regex backtracking limit exceeded | Upgrade to v4.1.1+ (fixed in #79) |
| Attachments not sending | File paths with special chars | Use addAttachment($file, 'encoded-filename.pdf') |
| Sendmail fails silently | Missing mail() function |
Check extension=php_mail.so in php.ini |
$message->setRawBody($mailer->getRawMessage($message));
$mailer->onSend[]
How can I help you explore Laravel packages today?