symfony/clickatell-notifier
Symfony Notifier bridge for Clickatell SMS. Configure with a clickatell:// DSN using your access token and optional sender (from). Enables sending notifications via Clickatell through Symfony’s notifier transport system.
Install Dependencies:
composer require symfony/clickatell-notifier symfony/http-client
(Note: Laravel’s native Http facade can replace symfony/http-client if preferred.)
Configure DSN in .env:
CLICKATELL_DSN=clickatell://ACCESS_TOKEN@default?from=YOUR_SENDER_ID
ACCESS_TOKEN with your Clickatell API key.from is the sender ID (e.g., YourApp).Create a Laravel Service Provider:
// app/Providers/ClickatellNotifierProvider.php
use Symfony\Component\Notifier\Clickatell\ClickatellTransport;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Illuminate\Support\ServiceProvider;
class ClickatellNotifierProvider extends ServiceProvider
{
public function register()
{
$this->app->singleton('clickatell.transport', function ($app) {
$dsn = env('CLICKATELL_DSN');
$httpClient = $app->make(HttpClientInterface::class); // or use Laravel's Http
return new ClickatellTransport($dsn, $httpClient);
});
}
}
Register the provider in config/app.php.
First Use Case: Send an SMS
use Symfony\Component\Notifier\Message\SmsMessage;
use Symfony\Component\Notifier\NotifierInterface;
$notifier = new class implements NotifierInterface {
public function __construct(private $transport) {}
public function send(SmsMessage $message) {
return $this->transport->send($message);
}
};
$transport = app('clickatell.transport');
$notifier = new $notifier($transport);
$notifier->send(
new SmsMessage('Hello from Laravel!', '1234567890')
);
CLICKATELL_DSN in .env (critical for connectivity).Http facade, wrap it in a Symfony\Contracts\HttpClient\HttpClientInterface adapter.Define a Message:
use Symfony\Component\Notifier\Message\SmsMessage;
$message = new SmsMessage(
'Your OTP is: 123456', // Body
'1234567890', // Recipient (string or array for bulk)
'YOUR_SENDER_ID' // Optional: Override DSN's 'from'
);
Send via Transport:
$transport = app('clickatell.transport');
$result = $transport->send($message);
TransportResult with status (e.g., TransportResult::SUCCESS).Handle Async Delivery (Optional): Use Laravel Queues to defer sending:
use Illuminate\Support\Facades\Bus;
Bus::dispatch(function () use ($message) {
$transport->send($message);
});
Extend Symfony’s TransportResult to trigger Laravel events:
// app/Providers/ClickatellNotifierProvider.php
public function boot()
{
$this->app->afterResolving('clickatell.transport', function ($transport) {
$transport->on('sent', function ($result) {
event(new SmsSent($result->getMessage()));
});
$transport->on('failed', function ($result) {
event(new SmsFailed($result->getMessage(), $result->getFailure()));
});
});
}
Send to multiple recipients:
$message = new SmsMessage('Hello!', ['1234567890', '9876543210']);
$transport->send($message);
Pass Clickatell-specific options via SmsMessage:
$message = new SmsMessage('Hello', '1234567890');
$message->options()->set('priority', 'high'); // Clickatell-specific
Use Laravel’s ShouldQueue for failed messages:
class SendSmsJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable;
public function handle()
{
try {
$transport->send($this->message);
} catch (\Exception $e) {
$this->release(60); // Retry after 1 minute
throw $e;
}
}
}
Use Clickatell’s message templates:
$message = new SmsMessage(
'Your {code} is valid for 5 minutes.',
'1234567890',
null, // No sender override
['code' => '123456'] // Template variables
);
Configure Clickatell to send delivery reports to a Laravel endpoint:
Route::post('/clickatell/webhook', function (Request $request) {
// Parse Clickatell's webhook payload
// Update DB or trigger events
});
(Note: Requires manual setup in Clickatell dashboard.)
Combine with other notifiers (e.g., email) for multi-channel delivery:
use Symfony\Component\Notifier\Notifier;
$notifier = new Notifier([
app('clickatell.transport'),
new MailTransport($mailer),
]);
$notifier->send($message); // Tries SMS first, falls back to email
DSN Format Sensitivity:
clickatell://ACCESS_TOKEN@default?from=FROM is case-sensitive..env validation or a helper method:
function validateClickatellDsn(string $dsn): void {
if (!preg_match('/^clickatell:\/\/[^@]+@[^?]+(\?from=[^&]+)?$/', $dsn)) {
throw new \InvalidArgumentException('Invalid Clickatell DSN format.');
}
}
Recipient Format:
SmsMessage constructor with a string:
// Works:
new SmsMessage('Hi', '1234567890');
// Fails (throws exception):
new SmsMessage('Hi', ['1234567890']); // Only works for bulk
Async Delivery Quirks:
Messenger; Laravel Queues require manual retry logic.ShouldQueue with custom retry logic (as shown above).Rate Limiting:
$transport->setMaxRetries(3);
$transport->setRetryDelay(1000); // 1 second
Sender ID Restrictions:
from parameter.Enable HTTP Logging:
$httpClient = HttpClient::create([
'headers' => ['User-Agent' => 'Laravel/Clickatell'],
'debug' => true, // Logs requests/responses
]);
Inspect TransportResult:
$result = $transport->send($message);
if ($result->isSuccess()) {
// Success!
} else {
\Log::error('SMS failed:', [
How can I help you explore Laravel packages today?