zeevx/laravel-sendbyte-transport

A SendByte mail transport for Laravel - send mail through https://sendbyte.africa with Laravel's native mail system

Maintainers

Package info

github.com/zeevx/laravel-sendbyte-transport

pkg:composer/zeevx/laravel-sendbyte-transport

Transparency log

Statistics

Installs: 35

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.0.2 2026-08-16 20:22 UTC

This package is auto-updated.

Last update: 2026-08-16 20:22:48 UTC


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

Latest Version on Packagist Total Downloads License

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.

Sending from a different domain

MAIL_FROM_ADDRESS applies to every mailer. When SendByte handles only part of your mail, or the domain you verified with SendByte is not the one the rest of your app sends from, give the mailer its own from block. Laravel reads a mailer's from in preference to the global one, so your other mailers are unaffected:

'sendbyte' => [
    'transport' => 'sendbyte',
    'key' => env('SENDBYTE_API_KEY'),
    'from' => [
        'address' => env('SENDBYTE_FROM_ADDRESS', env('MAIL_FROM_ADDRESS')),
        'name' => env('SENDBYTE_FROM_NAME', env('MAIL_FROM_NAME')),
    ],
],

Sending from an address whose domain is not verified fails with domain_not_verified, naming the domain it saw. That domain comes from the from address, so check which one applies to the mailer you are sending through.

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-ID cannot 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.