Send emails with Symfony
In this quickstart, you'll learn how to send transactional emails from your Symfony 6 or 7 app with Sidemail. You'll set up the SDK, send your first email, and see examples for common use cases like welcome emails, password resets, and scheduled reports.
Before you start
- Create a Sidemail account → get your API key
- Add a sending domain → set up your domain for sending
1. Install
composer require sidemail/sidemail
2. Add your API key
Add your Sidemail API key to .env:
SIDEMAIL_API_KEY=your-api-key
3. Configure the service
Register the Sidemail client as a service in config/services.yaml. The SDK reads SIDEMAIL_API_KEY automatically from env.
# config/services.yaml
services:
# ... other services
Sidemail\Sidemail:
autowire: true
4. Send a welcome email with Symfony
Inject Sidemail\Sidemail into your controller (e.g. src/Controller/RegistrationController.php).
namespace App\Controller;
use Sidemail\Sidemail;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
class RegistrationController extends AbstractController
{
#[Route('/register', methods: ['POST'])]
public function register(Sidemail $sidemail): Response
{
// ... create user ...
$sidemail->sendEmail([
'toAddress' => '[email protected]',
'fromAddress' => '[email protected]',
'fromName' => 'Your App',
'templateName' => 'Welcome',
'templateProps' => ['firstName' => 'Alex'],
]);
return new Response('User registered!');
}
}
5. Send a password reset email with Symfony
// src/Controller/SecurityController.php
use Sidemail\Sidemail;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
class SecurityController extends AbstractController
{
#[Route('/reset-password', methods: ['POST'])]
public function requestReset(Request $request, Sidemail $sidemail): Response
{
// In a real app, use Symfony Forms for validation, find user, generate token ...
$email = $request->request->get('email');
$token = 'secure-password-reset-token';
$sidemail->sendEmail([
'toAddress' => $email,
'fromAddress' => '[email protected]',
'fromName' => 'Your App',
'templateName' => 'Password Reset',
'templateProps' => [
'actionUrl' => 'https://myapp.com/reset/' . $token,
],
]);
return new Response('Reset link sent!');
}
}
6. Send a weekly report (Cron Task) with Symfony
Create a console command to send emails on a schedule.
// src/Command/SendWeeklyReportCommand.php
namespace App\Command;
use Sidemail\Sidemail;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
#[AsCommand(name: 'app:send-weekly-report')]
class SendWeeklyReportCommand extends Command
{
public function __construct(
private Sidemail $sidemail
) {
parent::__construct();
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
// In a real app, you would calculate this from the database
$newSignups = 150;
$chartData = [100, 200, 300, 400, 200, 300, 200, 500];
$this->sidemail->sendEmail([
'toAddress' => '[email protected]',
'fromAddress' => '[email protected]',
'fromName' => 'My App',
'templateName' => 'Weekly Report',
'templateProps' => [
'signups' => $newSignups,
'chart' => $chartData,
],
]);
return Command::SUCCESS;
}
}
You can now run this command manually or schedule it with cron:
# Run every Monday at 8:00 AM
0 8 * * 1 bin/console app:send-weekly-report
7. Send email via Event Subscriber with Symfony
Decouple email sending from your controllers by using an event subscriber.
// src/EventSubscriber/UserRegisteredSubscriber.php
namespace App\EventSubscriber;
use App\Event\UserRegisteredEvent;
use Sidemail\Sidemail;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class UserRegisteredSubscriber implements EventSubscriberInterface
{
public function __construct(
private Sidemail $sidemail
) {}
public static function getSubscribedEvents(): array
{
return [
UserRegisteredEvent::class => 'onUserRegistered',
];
}
public function onUserRegistered(UserRegisteredEvent $event): void
{
$this->sidemail->sendEmail([
'toAddress' => $event->getUser()->getEmail(),
'fromAddress' => '[email protected]',
'fromName' => 'My App',
'templateName' => 'Welcome',
]);
}
}
8. Send HTML email (with Twig)
Use $this->renderView() to generate HTML from a Twig template.
// src/Controller/InvoiceController.php
public function sendInvoice(Sidemail $sidemail): Response
{
$html = $this->renderView('emails/invoice.html.twig', [
'amount' => 99,
]);
$sidemail->sendEmail([
'toAddress' => '[email protected]',
'fromAddress' => '[email protected]',
'fromName' => 'Your App',
'subject' => 'Your Invoice',
'html' => $html,
]);
return new Response('Invoice sent!');
}
9. Send Markdown email
Store your markdown content in a file (e.g. templates/emails/welcome.md) and load it.
$markdown = file_get_contents($this->getParameter('kernel.project_dir') . '/templates/emails/welcome.md');
$this->sidemail->sendEmail([
'toAddress' => '[email protected]',
'fromAddress' => '[email protected]',
'fromName' => 'Your App',
'subject' => 'Testing markdown emails 😊',
'markdown' => $markdown,
'templateProps' => [
'name' => 'John',
'link' => 'https://example.com',
],
]);
10. Send plain text email
$this->sidemail->sendEmail([
'toAddress' => '[email protected]',
'fromAddress' => '[email protected]',
'fromName' => 'Your App',
'subject' => 'Hello',
'text' => 'Hello! 👋',
]);
11. Schedule email
Send email later. Set scheduledAt to an ISO date string.
$this->sidemail->sendEmail([
'toAddress' => '[email protected]',
'fromAddress' => '[email protected]',
'fromName' => 'Your App',
'templateName' => 'Welcome',
'templateProps' => ['firstName' => 'Alex'],
'scheduledAt' => (new \DateTimeImmutable('+1 hour'))->format(\DateTimeInterface::ATOM),
]);
12. Send with attachment
Use the Sidemail::fileToAttachment helper to attach files.
use Sidemail\Sidemail;
$pdfData = file_get_contents($this->getParameter('kernel.project_dir') . '/var/invoice.pdf');
$attachment = Sidemail::fileToAttachment('invoice.pdf', $pdfData);
$this->sidemail->sendEmail([
'toAddress' => '[email protected]',
'fromAddress' => '[email protected]',
'fromName' => 'Your App',
'subject' => 'Your invoice',
'text' => 'See attached.',
'attachments' => [$attachment],
]);
13. Handle errors
use Sidemail\SidemailException;
use Psr\Log\LoggerInterface;
class EmailController extends AbstractController
{
public function send(Sidemail $sidemail, LoggerInterface $logger): Response
{
try {
$sidemail->sendEmail([/* ... */]);
} catch (SidemailException $e) {
$logger->error('Sidemail error', [
'message' => $e->getMessage(),
'httpStatus' => $e->getHttpStatus(),
'errorCode' => $e->getErrorCode(),
]);
return new Response('Error sending email', 500);
}
return new Response('Email sent!');
}
}