inspectornetwork / mailmanaged
Laravel mail transport for MailManaged: send a website's administrative email to recipients verified on the platform.
Package info
bitbucket.org/inspectornetwork/mailmanaged-connector
pkg:composer/inspectornetwork/mailmanaged
Requires
- php: ^8.2
- illuminate/mail: ^11.0|^12.0|^13.0
- illuminate/support: ^11.0|^12.0|^13.0
- symfony/http-client: ^7.0|^8.0
- symfony/mailer: ^7.0|^8.0
Requires (Dev)
- laravel/pint: ^1.0
- orchestra/testbench: ^9.0|^10.0|^11.0
- pestphp/pest: ^3.0|^4.0|^5.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is not auto-updated.
Last update: 2026-09-20 14:57:45 UTC
README
A Laravel mail transport for MailManaged. Your application sends the content of an administrative email (a contact-form submission, an alert, an order notice) and MailManaged delivers it to the people your website has verified on the platform.
Recipients live in MailManaged, not in your code. Whatever address a form submits or a bug injects, mail only ever goes to your verified recipients: the transport never sends the To, Cc or Bcc addresses, the sender, or any other header to the platform.
Requires PHP 8.2+ and Laravel 11, 12 or 13.
Install
composer require inspectornetwork/mailmanaged
Create a site token on your website's page in the MailManaged dashboard and add it to .env:
MAILMANAGED_TOKEN=your-site-token
The token is a server-side secret. Never expose it to browser JavaScript.
Send
The package registers a mailer named mailmanaged. Use it for administrative messages:
use Illuminate\Support\Facades\Mail;
Mail::mailer('mailmanaged')->raw('A new enquiry arrived.', function ($message) {
$message->subject('New enquiry')->replyTo('visitor@example.com');
});
No to() is needed, and any you add is ignored. Mailables and notifications work the same way
(->mailer('mailmanaged')). If everything your site sends is administrative, make it the
default instead with MAIL_MAILER=mailmanaged.
What is sent: the subject, the text and/or HTML body, and one reply-to address. Attachments are not supported and are refused with an exception rather than dropped silently.
Recipient groups
Messages go to your website's default route unless you pick a group (for example contact,
billing, alerts) that you created in the dashboard:
MAILMANAGED_GROUP=contact
$message->getHeaders()->addTextHeader('X-MailManaged-Group', 'billing'); // per message
An unknown or empty group is an error; it never falls back to everyone.
Retries and idempotency
Every request carries an idempotency key. Repeating the same key with the same content within 24 hours returns the original result without sending again or using more of your allowance. The transport generates a key per send, but a retried queued job builds a new message and so gets a new key. For anything you retry, set a stable key yourself:
$message->getHeaders()->addTextHeader('X-MailManaged-Idempotency-Key', 'contact-form-'.$submission->id);
Keys are 8 to 128 characters.
Errors
A message the platform does not accept throws InspectorNetwork\MailManaged\MailManagedException
(a Symfony TransportException, so Laravel handles it like any failed send):
try {
Mail::mailer('mailmanaged')->send(new ContactFormSubmitted($submission));
} catch (MailManagedException $e) {
$e->status; // HTTP status, or 0 if the platform could not be reached
$e->retryAfter; // seconds to wait, for rate and usage limits
$e->isRetryable(); // true for 0, 429 and 5xx
}
| Status | Meaning | Retry? |
|---|---|---|
0 | Platform unreachable or timed out. The message may have been accepted; retry with the same key. | yes |
401 / 403 | Invalid token, website not verified, or a security hold shown in your dashboard | no |
402 | No active subscription, or the website is paused | no |
409 | Idempotency key reused with different content | no |
422 | Invalid message, unknown group, or no deliverable recipients | no |
429 | Rate or usage limit; wait retryAfter seconds | yes |
5xx | Platform error | yes |
Configuration
.env is usually enough. To publish the config file:
php artisan vendor:publish --tag=mailmanaged-config
| Key | Env | Default |
|---|---|---|
token | MAILMANAGED_TOKEN | none (required) |
endpoint | MAILMANAGED_ENDPOINT | https://mailmanaged.com/api/v1/messages |
group | MAILMANAGED_GROUP | the website's default route |
timeout | MAILMANAGED_TIMEOUT | 15 seconds |
The endpoint must be HTTPS (plain HTTP is accepted only for localhost and 127.0.0.1), and
redirects are never followed, so the token cannot be forwarded to another host.
One application serving several websites can define extra mailers, each with its own token:
// config/mail.php
'mailers' => [
'second-site' => ['transport' => 'mailmanaged', 'token' => env('SECOND_SITE_TOKEN'), 'group' => 'alerts'],
],
Development
composer install
composer test
composer lint
Tests use Orchestra Testbench and a mock HTTP client; nothing is sent. Bump
MailManagedTransport::VERSION and CHANGELOG.md with each release, then tag it (v1.0.0).
License
MIT.