Sendery
Sendery

Framework Integrations

Symfony integration

Send transactional email with Sendery templates through Symfony Mailer.

Install
composer require sendery/symfony:^0.1
Source code

Requirements

Symfony Mailer 7.4 and PHP 8.3+ with the cURL extension.

Register the transport

Publish a welcome template with name and action_url variables, and create a project API key. Add the factory to config/services.yaml.

YAML
# config/services.yaml — add to your existing services section.
services:
  Sendery\Symfony\SenderyTransportFactory:
    tags: ['mailer.transport_factory']

Set the API key

Set MAILER_DSN in .env.local or your hosting provider’s secret settings.

.env.local
MAILER_DSN=sendery://[email protected]

Configure Mailer

Use the DSN in your existing Mailer configuration.

YAML
# config/packages/mailer.yaml
framework:
  mailer:
    dsn: '%env(MAILER_DSN)%'

Send an email

Inject MailerInterface and send a TemplateEmail. Symfony requires from() for validation; Sendery uses the sender configured on your project. Use one recipient. HTML emails, attachments, and cc or bcc recipients are not supported.

PHP
use Sendery\Symfony\TemplateEmail;
use Symfony\Component\Mailer\MailerInterface;

final class WelcomeEmails
{
    public function __construct(private MailerInterface $mailer) {}

    public function send(string $address, string $name): void
    {
        $email = (new TemplateEmail())
            ->from('[email protected]')
            ->to($address)
            ->template('welcome', [
                'name' => $name,
                'action_url' => 'https://example.com/start',
            ]);

        $this->mailer->send($email);
    }
}

Send with Messenger

With Symfony Messenger and your chosen transport installed, set MESSENGER_TRANSPORT_DSN and route mail to async. Run php bin/console messenger:consume async. The same queued TemplateEmail keeps its key and variables on retries.

YAML
# config/packages/messenger.yaml
framework:
  messenger:
    transports:
      async: '%env(MESSENGER_TRANSPORT_DSN)%'
    routing:
      'Symfony\Component\Mailer\Messenger\SendEmailMessage': async

Handle failures

API failures throw TransportException with a Sendery\ApiException as the previous exception. Inspect its status and errorCode. The transport makes one attempt; configure Messenger to retry temporary failures and avoid retrying validation or billing errors.