symfony/microsoft-teams-notifier
Symfony Notifier bridge for Microsoft Teams Incoming Webhooks. Configure via MICROSOFT_TEAMS_DSN and send ChatMessage notifications, with support for MessageCard options like sections, facts, and interactive actions/inputs.
Install the Package Add to your Laravel project via Composer:
composer require symfony/notifier symfony/microsoft-teams-notifier
Note: Laravel doesn’t natively use Symfony’s Notifier, so you’ll need to integrate it via a service provider or manually.
Configure the DSN
Set the MICROSOFT_TEAMS_DSN environment variable in .env:
MICROSOFT_TEAMS_DSN=microsoftteams://default/WEBHOOK_PATH
Replace WEBHOOK_PATH with your Teams Incoming Webhook URL (format: webhookb2/{uuid}@{uuid}/IncomingWebhook/{id}/{uuid}).
First Use Case: Send a Simple Alert Create a service to send a basic message:
use Symfony\Component\Notifier\NotifierInterface;
use Symfony\Component\Notifier\Message\ChatMessage;
class TeamsNotifierService {
public function __construct(private NotifierInterface $notifier) {}
public function sendAlert(string $message): void {
$chatMessage = (new ChatMessage($message))->transport('microsoftteams');
$this->notifier->send($chatMessage);
}
}
Register the service in AppServiceProvider:
public function register(): void {
$this->app->singleton(NotifierInterface::class, function ($app) {
return new NotifierInterface([], []); // Simplified; use Symfony's Notifier in practice
});
$this->app->singleton(TeamsNotifierService::class);
}
Trigger the Alert Call the service from a controller, command, or event listener:
$this->teamsNotifier->sendAlert('Deployment failed in staging!');
Where to Look First:
MicrosoftTeamsTransport (for advanced customization).Use ChatMessage for simple notifications (e.g., CI/CD failures, alerts):
$message = (new ChatMessage('Server down!'))
->transport('microsoftteams')
->priority(ChatMessage::PRIORITY_HIGH);
$notifier->send($message);
Build interactive messages with sections, facts, and actions:
$options = (new MicrosoftTeamsOptions())
->title('Incident Alert')
->text('High severity: Database connection lost.')
->themeColor('#FF0000')
->section((new Section())
->title('Affected Services')
->fact((new Fact())->name('API')->value('⚠️ Degraded'))
->fact((new Fact())->name('Dashboard')->value('✅ Operational'))
)
->action((new ActionCard())
->action((new HttpPostAction())
->name('Acknowledge')
->target('/api/incidents/acknowledge')
)
);
$message = (new ChatMessage(''))->options($options);
$notifier->send($message);
Use Laravel’s blade or string replacement for dynamic messages:
$message = (new ChatMessage("User {user} created account {accountId}"))
->transport('microsoftteams')
->context(['user' => 'john_doe', 'accountId' => '12345']);
Note: Requires custom transport extension to parse context.
Wrap the notifier in a retry logic (e.g., using Laravel’s retry helper):
use Illuminate\Support\Facades\Retry;
Retry::times(3)->attempt(function () use ($notifier, $message) {
$notifier->send($message);
});
Extend the service to support multiple transports (Teams + Slack + Email):
class MultiChannelNotifier {
public function __construct(
private TeamsNotifierService $teams,
private SlackNotifierService $slack,
private EmailNotifierService $email
) {}
public function sendCrossChannel(string $message): void {
$this->teams->sendAlert($message);
$this->slack->sendAlert($message);
$this->email->sendAlert($message);
}
}
Trigger Teams alerts from GitHub Actions or Laravel Forge:
# GitHub Actions example
- name: Notify Teams on Failure
if: failure()
run: |
php artisan teams:alert "Build failed: ${{ github.run_number }}"
Register a custom Artisan command for teams:alert.
Listen to Laravel events (e.g., JobFailed, ModelCreated) and dispatch Teams messages:
use Illuminate\Queue\Events\JobFailed;
Event::listen(JobFailed::class, function (JobFailed $event) {
$message = "Job [{$event->job}] failed on {$event->connection}.";
$this->teamsNotifier->sendAlert($message);
});
Use Laravel’s scheduler to send periodic updates:
// app/Console/Kernel.php
protected function schedule(Schedule $schedule): void {
$schedule->call(function () {
$this->teamsNotifier->sendAlert('Daily digest: 5 new tickets created.');
})->dailyAt('9:00');
}
Laravel-Specific Setup Since Laravel doesn’t use Symfony’s Notifier by default, create a facade or wrapper:
// app/Facades/TeamsNotifier.php
public static function alert(string $message): void {
$notifier = app(NotifierInterface::class);
$notifier->send((new ChatMessage($message))->transport('microsoftteams'));
}
Queue Notifications Offload notifications to a queue (e.g., Redis) for reliability:
// Dispatch to queue
TeamsNotification::dispatch($message)->delay(now()->addSeconds(5));
Create a TeamsNotification job class.
Logging Log failed notifications for debugging:
try {
$notifier->send($message);
} catch (\Exception $e) {
Log::error("Teams notification failed: " . $e->getMessage());
}
Testing
Mock the NotifierInterface in tests:
$notifier = Mockery::mock(NotifierInterface::class);
$notifier->shouldReceive('send')->once();
$this->app->instance(NotifierInterface::class, $notifier);
DSN Format Errors
webhookb2/ prefix) causes silent failures.private function validateDsn(string $dsn): void {
if (!str_starts_with($dsn, 'microsoftteams://')) {
throw new \InvalidArgumentException('Invalid DSN format.');
}
}
MessageCard Size Limits
MessageCard payloads (>6KB) may be truncated or rejected by Teams.Rate Limiting
Missing Symfony Dependencies
NotifierInterface and ChatMessage.symfony/notifier and create a minimal wrapper:
// app/Services/SymfonyNotifier.php
use Symfony\Component\Notifier\Notifier;
use Symfony\Component\Notifier\Transport\TransportInterface;
class SymfonyNotifier {
public function __construct(private Notifier $notifier) {}
public function sendChatMessage(string $message, TransportInterface $transport): void {
$this->notifier->send((new ChatMessage($message))->transport($transport));
}
}
Interactive Actions Not Working
HttpPostAction targets may fail if the endpoint isn’t HTTPS or lacks proper CORS.How can I help you explore Laravel packages today?