zeevx / laravel-sendbyte-transport
A SendByte mail transport for Laravel - send mail through https://sendbyte.africa with Laravel's native mail system
Package info
github.com/zeevx/laravel-sendbyte-transport
pkg:composer/zeevx/laravel-sendbyte-transport
Requires
- php: ^8.1
- ext-json: *
- guzzlehttp/guzzle: ^7.5
- illuminate/http: ^9.0|^10.0|^11.0|^12.0|^13.0
- illuminate/mail: ^9.0|^10.0|^11.0|^12.0|^13.0
- illuminate/support: ^9.0|^10.0|^11.0|^12.0|^13.0
- symfony/mailer: ^6.2|^7.0
- symfony/mime: ^6.2|^7.0
Requires (Dev)
- laravel/pint: ^1.0
- orchestra/testbench: ^7.0|^8.0|^9.0|^10.0|^11.0
- pestphp/pest: ^1.23|^2.0|^3.0
README
A SendByte mail transport for Laravel. Set MAIL_MAILER=sendbyte and your existing Mailables, Notifications, and Mail:: calls deliver through SendByte's transactional email API, no code changes required.
Full SendByte documentation: docs.sendbyte.africa
Requirements
- PHP 8.1 through 8.4
- Laravel 9 through 13
Installation
composer require zeevx/laravel-sendbyte-transport
Add a sendbyte mailer to config/mail.php:
'mailers' => [ // ... 'sendbyte' => [ 'transport' => 'sendbyte', 'key' => env('SENDBYTE_API_KEY'), ], ],
Then point your .env at it:
MAIL_MAILER=sendbyte SENDBYTE_API_KEY=sk_live_your_key MAIL_FROM_ADDRESS=receipts@yourdomain.com MAIL_FROM_NAME="Your App"
If you prefer keeping credentials with your other third-party services, omit key from the mailer and set it in config/services.php instead:
'sendbyte' => [ 'key' => env('SENDBYTE_API_KEY'), ],
The mailer accepts two optional settings:
'sendbyte' => [ 'transport' => 'sendbyte', 'key' => env('SENDBYTE_API_KEY'), 'base_url' => env('SENDBYTE_BASE_URL', 'https://api.sendbyte.africa'), 'timeout' => 30, ],
Your sending domain must be verified in your SendByte dashboard before live sends. Use an sk_test_ sandbox key to exercise the full pipeline without delivering to real inboxes.
Usage
Send mail exactly as you always do:
Mail::to($user)->send(new OrderShipped($order)); $user->notify(new InvoicePaid($invoice));
Everything a Mailable carries maps onto SendByte's send API: HTML and plain-text bodies, cc, bcc, reply-to, attachments (base64-encoded, up to 10), and custom headers.
Tags
Laravel's message tags become SendByte tags (up to 10), filterable in the dashboard and the List Emails endpoint:
use Illuminate\Mail\Mailables\Envelope; public function envelope(): Envelope { return new Envelope( subject: 'Your receipt', tags: ['receipt', 'payment'], ); }
Message metadata is delivered as X-Metadata-* headers.
Idempotent sends
SendByte deduplicates sends that share an idempotency key within 24 hours. Set one per message via the X-SendByte-Idempotency-Key header; the transport hoists it into the API's idempotency_key field:
public function headers(): Headers { return new Headers(text: [ 'X-SendByte-Idempotency-Key' => 'order-4421-receipt', ]); }
Message IDs
SendByte assigns the final Message-ID at delivery. The transport records the API's email id (em_...) as the sent message id, so you can correlate sends with dashboard entries and webhook events:
$sent = Mail::to($user)->send(new OrderShipped($order)); $sent->getMessageId(); // "em_01j..."
Failures
A rejected send (unverified domain, suppressed recipient, rate limit, validation error) throws a Symfony\Component\Mailer\Exception\TransportException whose message includes SendByte's error detail.
Limits
Imposed by the SendByte API:
- Maximum 50 recipients per message
- Maximum 10 attachments and 10 tags per message
Message-IDcannot be overridden; SendByte assigns it at delivery
Testing your integration
The transport sends through Laravel's HTTP client, so Http::fake() works, and Mail::fake() behaves as usual since the transport is never invoked.
Run the package test suite (powered by Pest):
composer test
composer lint
Security
If you discover any security-related issues, please email adamsohiani@gmail.com instead of using the issue tracker.
Credits
License
The MIT License (MIT). Please see the License File for more information.