optime/jangomail
Laravel/PHP integration for the JangoMail email API. Send transactional and marketing email, manage lists and subscribers, and use JangoMail as a mail transport or via a simple client wrapper in your Optime applications.
Before installing, treat this as a risk assessment first: optime/jangomail has 1 star, 0 dependents, and a near-zero health score. The repo name (JangoMailBundle) also hints it may have originated as a Symfony bundle rather than a native Laravel package. Confirm the package actually supports your Laravel version before committing — check composer.json constraints in the repo and skim the service provider for Illuminate\Support\ServiceProvider compatibility. If it doesn't, skip to "Gotchas" for the recommended alternative.
Assuming it installs cleanly:
composer require optime/jangomail
composer.json for extra.laravel.providers; if absent, add the provider manually to config/app.php.php artisan vendor:publish --provider="Optime\JangoMail\JangoMailServiceProvider"
JANGOMAIL_USERNAME / JANGOMAIL_PASSWORD (JangoMail uses account credentials, not just a bearer token). Confirm exact keys against the published config file — do not guess.dd() the return value so you can see the actual client response before wiring it into a Mailable.If step 3 does not exist, the integration is hardcoded and you'll need to read the driver/transport class directly to know what it expects.
Wrap it — don't call it directly. Even in a small app, isolate the package behind your own service so you can swap it later (the low maintenance score makes this a real concern):
namespace App\Services;
use Optime\JangoMail\Facades\JangoMail; // verify facade name
class Mailer
{
public function send(string $to, string $subject, string $html): void
{
JangoMail::send([
'to' => $to,
'subject' => $subject,
'body' => $html,
]);
}
}
Queue it. JangoMail is a remote API; never call it synchronously in a request. Wrap the service call in a queued Job so a slow/failed API doesn't block the response:
class SendTransactionalEmail implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function __construct(public array $payload) {}
public function handle(Mailer $mailer): void
{
$mailer->send($this->payload['to'], $this->payload['subject'], $this->payload['body']);
}
}
Keep templates outside the package. JangoMail supports server-side templates; don't couple Blade views to the package. Pass either rendered HTML or a template ID so you retain control.
Integration tip — bridge into Laravel Mail. The cleanest long-term pattern is a custom Transport that delegates to this package, so Mail::to()->send(new ReceiptMail) continues to work and your Mailable classes stay framework-native. This is an extension point worth implementing if the package exposes a usable transport/driver interface; if it only exposes a static facade, keep your Mailer wrapper as the seam.
Config-driven multi-account. If you send on behalf of multiple tenants, put credentials in config/jangomail.php (not just .env) and resolve the account per tenant — do not hardcode.
composer.json and vendor-review the send method before production.$tries and backoff() to the job; remote ESP APIs throttle. Don't rely on the package to retry.Mail via a JangoMail SMTP config in config/mail.php (MAIL_MAILER=smtp, JangoMail host/port/credentials), or Http::withBasicAuth(...)->post(...) directly against the JangoMail API. Both are more maintainable than a one-star wrapper and don't require a fork.Mailer wrapper or a custom transport) is your escape hatch. Keep it framework-native so removing the package is a one-file change.How can I help you explore Laravel packages today?