<?php
declare(strict_types=1);
namespace Hitso\Bundle\CommonBundle\Helper\Mailer;
use Hitso\Bundle\BlocksBundle\Block\Factory;
use Hitso\Bundle\CommonBundle\Event\MailEvent;
use Hitso\Bundle\CommonBundle\Helper\Templating\TemplatingHelperInterface;
use Hitso\Bundle\CommonBundle\Service\System\Configurator\MailerConfigurator;
use Swift_Mailer as Mailer;
use Swift_Message as Message;
use Swift_SmtpTransport;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Validator\ValidatorInterface;
class MailerHelper implements MailerHelperInterface
{
/**
* @var MailerConfigurator
*/
protected $configurator;
/**
* @var TemplatingHelperInterface
*/
protected $templatingHelper;
/**
* @var ValidatorInterface
*/
protected $validator;
/**
* @var array
*/
protected $options = [];
/**
* @var EventDispatcherInterface
*/
protected $eventDispatcher;
/**
* @var Factory
*/
protected $blockFactory;
/**
* @var bool
*/
protected $debug;
public function __construct(
MailerConfigurator $configurator,
TemplatingHelperInterface $templatingHelper,
ValidatorInterface $validator,
EventDispatcherInterface $eventDispatcher,
Factory $blockFactory,
bool $debug = false
) {
$this->configurator = $configurator;
$this->templatingHelper = $templatingHelper;
$this->validator = $validator;
$this->eventDispatcher = $eventDispatcher;
$this->blockFactory = $blockFactory;
$this->debug = $debug;
}
public function sendEmail(array $options): int
{
$resolver = new OptionsResolver();
$this->configureOptions($resolver);
$this->options = $resolver->resolve($options);
$mailer = $this->createMailer();
$message = $this->createMessage();
$this->eventDispatcher->dispatch('mail.pre_send', new MailEvent($mailer, $message, 0));
$status = 0;
try {
$status = $mailer->send($message);
} catch (\Exception $e) {
if ($this->debug) {
throw $e;
}
}
$this->eventDispatcher->dispatch('mail.post_send', new MailEvent($mailer, $message, $status));
return $status;
}
private function createMessage(): Message
{
$message = new Message();
$message->setFrom($this->configurator->getParameter('from_email'));
$message->setTo($this->options['recipient']);
$message->setReplyTo($this->options['reply_to']);
if (!empty($this->options['bcc'])) {
$message->setBcc($this->options['bcc']);
}
$this->setBody($message, $this->options['block'], $this->options['parameters']);
foreach ($this->options['attachments'] as $file) {
$message->attach($this->createAttachment($file));
}
foreach ($this->options['dynamic_attachments'] as $dynamicAttachment) {
$message->attach($this->createDynamicAttachment($dynamicAttachment));
}
return $message;
}
private function createDynamicAttachment(array $dynamicAttachment): \Swift_Mime_Attachment
{
return new \Swift_Attachment($dynamicAttachment['data'], $dynamicAttachment['name'], $dynamicAttachment['type']);
}
private function createAttachment(string $path): \Swift_Mime_Attachment
{
return \Swift_Attachment::fromPath($path);
}
private function setBody(Message $message, string $blockName, array $parameters = [])
{
$parameters['message'] = $message;
$block = $this->blockFactory->getBlock($blockName);
$subject = $block->getSubject();
$content = $this->templatingHelper->renderFromString($block->getContent(), $parameters);
$textContent = $this->templatingHelper->renderFromString($block->getTextContent(), $parameters);
$body = $this->templatingHelper->render($this->options['template'], [
'content' => $content,
'subject' => $subject,
'parameters' => $parameters,
]);
$message->setBody($body, 'text/html');
if (!empty($textContent)) {
$message->addPart($textContent, 'text/plain');
}
$message->setSubject($subject);
}
private function configureOptions(OptionsResolver $resolver)
{
$resolver->setRequired([
'recipient',
'bcc',
'reply_to',
'block',
'template',
'parameters',
'attachments',
'dynamic_attachments',
]);
$resolver->setNormalizer('bcc', function (Options $options, $value) {
if (empty($value)) {
return $this->configurator->getParameter('bcc') ?? [];
}
return $value;
});
$resolver->setNormalizer('reply_to', function (Options $options, $value) {
if (empty($value)) {
return $this->configurator->getParameter('from_email') ?? [];
}
return $value;
});
$resolver->setDefault('bcc', '');
$resolver->setDefault('reply_to', '');
$resolver->setDefault('attachments', []);
$resolver->setDefault('dynamic_attachments', []);
$resolver->setAllowedTypes('recipient', ['string', 'array']);
$resolver->setAllowedTypes('bcc', ['string', 'array']);
$resolver->setAllowedTypes('reply_to', ['string', 'array']);
$resolver->setAllowedTypes('block', ['string']);
$resolver->setAllowedTypes('template', ['string']);
$resolver->setAllowedTypes('parameters', ['array']);
$resolver->setAllowedTypes('attachments', ['array']);
$resolver->setAllowedTypes('dynamic_attachments', ['array']);
}
private function createMailer(): Mailer
{
$configuration = $this->configurator->getParameters();
$encryption = empty($configuration['encryption']) ? false : $configuration['encryption'];
$transport = new Swift_SmtpTransport(
$configuration['host'],
isset($configuration['port']) ? $configuration['port'] : 25,
$encryption
);
$transport->setUsername($configuration['user']);
$transport->setPassword($configuration['pass']);
$transport->setStreamOptions([
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true,
],
]);
$mailer = new Mailer($transport);
if (isset($configuration['debug']) && true === (bool)$configuration['debug']) {
$logger = new \Swift_Plugins_Loggers_EchoLogger();
$mailer->registerPlugin(new \Swift_Plugins_LoggerPlugin($logger));
}
return $mailer;
}
}