$defaults */ public function __construct( private readonly MailerInterface $mailer, private readonly BodyRendererInterface $bodyRenderer, private readonly LoggerInterface $logger, private readonly array $defaults, ) { } /** * @param array $context * @param array $options */ public function createAndSendEmail(array $context, array $options): void { $config = $this->resolveConfig($options); $email = $this->create($context, $config); $recipients = (array) $config['to']; foreach ($recipients as $recipient) { $email->to($recipient); $this->send($email); } } /** * @param array $context * @param array $config */ public function create(array $context, array $config): TemplatedEmail { $email = (new TemplatedEmail()) ->from($config['from']) ->subject($config['subject']) ->htmlTemplate($config['template']) ->context($context) ; foreach ($config['attachments'] as $attachment) { /* @var EmailAttachmentInterface $attachment */ $attachment->attachTo($email); } $this->bodyRenderer->render($email); return $email; } public function send(TemplatedEmail $email): void { $recipients = array_map(fn (Address $address) => $address->toString(), $email->getTo()); try { $this->mailer->send($email); $this->logger->info('Send email', [ 'to' => $recipients, 'subject' => $email->getSubject(), ]); } catch (TransportExceptionInterface $e) { $this->logger->error('Email could not be sent', [ 'to' => $recipients, 'subject' => $email->getSubject(), 'error' => $e->getMessage(), ]); throw $e; } } /** * @param array $options * * @return array */ private function resolveConfig(array $options): array { $resolver = new OptionsResolver(); $resolver ->setDefaults([ 'from' => $this->defaults['from'], 'to' => $this->defaults['to'], 'subject_parameters' => [], 'attachments' => [], ]) ->setRequired([ 'template', 'subject', ]) ->setAllowedTypes('to', ['string', 'array']) ->setAllowedTypes('template', 'string') ->setAllowedTypes('subject', 'string') ->setAllowedTypes('attachments', 'array') ; return $resolver->resolve($options); } }