Looking to hire Laravel developers? Try LaraJobs

laravel maintained by mailsenpai

Description
Laravel mail transport for SMTP Senpai by MailSenpai (EU SMTP relay and email API)
Author
Last update
2026/10/10 13:39 (dev-main)
License
Downloads
1

Comments
comments powered by Disqus

SMTP Senpai for Laravel

Laravel mail transport for SMTP Senpai by MailSenpai, the EU-hosted SMTP relay and transactional email API. Built on mailsenpai/symfony-mailer, so it works with every Laravel mail feature (Mailables, notifications, queues, Mail::raw).

Docs: https://en.mailsenpai.com/smtp-api/ · Product: https://en.mailsenpai.com/smtp-senpai/ · All integrations: https://en.mailsenpai.com/integrations/ Source code and issues: https://gitlab.com/smtp-senpai/laravel

Installation

composer require mailsenpai/laravel

Requires PHP 8.2+ and Laravel 12 or 13. The service provider is auto-discovered.

Configuration

.env:

MAIL_MAILER=smtpsenpai
MAILSENPAI_API_KEY=msp_your_key
MAIL_FROM_ADDRESS=orders@yourdomain.com   # on a domain verified in your account
MAIL_FROM_NAME="Your shop"

That's it: the package adds a smtpsenpai mailer to config/mail.php if you have not defined one. To define it yourself (for example to use several keys):

// config/mail.php
'mailers' => [
    'smtpsenpai' => [
        'transport' => 'smtpsenpai',
        // optional: 'key' => env('MAILSENPAI_API_KEY'),
    ],
],

The key is read from the mailer options, then config/mailsenpai.php (MAILSENPAI_API_KEY), then config/services.php ('mailsenpai' => ['key' => ...]). Publish the config file with:

php artisan vendor:publish --tag=mailsenpai-config

SMTP instead of the API

The API (HTTPS) is recommended: it also works where outgoing SMTP ports are blocked. To use the relay over SMTP (relay.mailsenpai.com, port 2525, STARTTLS required):

MAILSENPAI_MODE=smtp
MAILSENPAI_SMTP_USERNAME=r1234@yourdomain.com
MAILSENPAI_SMTP_PASSWORD=...

or per mailer: ['transport' => 'smtpsenpai', 'mode' => 'smtp', 'username' => ..., 'password' => ...].

Sending

Mail::to('customer@example.com')->send(new OrderShipped($order));

Supported: HTML and text, attachments, Reply-To, custom X-... headers (other headers are dropped by the API), Laravel tags and metadata (sent as X-Tag and X-Metadata-<key>). Add an Idempotency-Key header to a message to make sure it is never sent twice within 24 hours, even if a queued job is retried:

public function headers(): Headers
{
    return new Headers(text: ['Idempotency-Key' => 'order-shipped-'.$this->order->id]);
}

Good to know: every recipient (To, Cc and Bcc) receives an individual copy, so Cc addresses are not visible to the other recipients (use SMTP mode if you need a visible Cc). Up to 50 recipients and 10 attachments (10 MB in total) per email. Recipients on your suppression list are skipped and logged as a warning.

Webhooks

Set the webhook in the customer area (or through the API) and put the whsec_... secret in .env:

MAILSENPAI_WEBHOOK_SECRET=whsec_...

Protect your route with the signature middleware:

use MailSenpai\Laravel\Http\Middleware\VerifyWebhookSignature;

Route::post('/webhooks/mailsenpai', function (Request $request) {
    $event = $request->json()->all();   // {id, type, created_at, data: {email, reason, message_id, ...}}
    if ($event['type'] === 'bounce') {
        // ...
    }
    return response()->noContent();
})->middleware(VerifyWebhookSignature::class);

Put the route in routes/api.php, or exclude it from CSRF protection in bootstrap/app.php: $middleware->validateCsrfTokens(except: ['webhooks/mailsenpai']);

Invalid or expired signatures (more than 5 minutes) get a 403. MailSenpai\Laravel\WebhookSignature::isValid() is available if you prefer to check it yourself.

Tests

composer install
vendor/bin/phpunit

License

MIT, © MailSenpai.