From d37cbc7cf2bca00c0150fe828048c9bda165d423 Mon Sep 17 00:00:00 2001 From: Benjamin Vison Date: Mon, 19 Jun 2017 09:12:12 -0400 Subject: [PATCH] Implemented the resend email feature and reorganized the way emails are stored. --- .idea/EmailBundle.iml | 10 - .idea/deployment.xml | 14 + .idea/workspace.xml | 183 +++++++------ Command/CheckCommand.php | 79 +++++- Command/ResendCommand.php | 45 ++++ DependencyInjection/NTIEmailExtension.php | 2 +- Entity/Email.php | 166 +++++++----- Entity/Email.php~ | 297 ---------------------- Entity/Smtp.php | 219 ++++++++++++++++ Form/SmtpType.php | 50 ++++ Repository/EmailRepository.php | 2 + Resources/config/services.yml | 15 +- Service/Mailer.php | 230 ++++++++++++++--- 13 files changed, 820 insertions(+), 492 deletions(-) create mode 100644 .idea/deployment.xml create mode 100644 Command/ResendCommand.php delete mode 100644 Entity/Email.php~ create mode 100644 Entity/Smtp.php create mode 100644 Form/SmtpType.php diff --git a/.idea/EmailBundle.iml b/.idea/EmailBundle.iml index b313593..c956989 100644 --- a/.idea/EmailBundle.iml +++ b/.idea/EmailBundle.iml @@ -4,15 +4,5 @@ - - - - - - - - - - \ No newline at end of file diff --git a/.idea/deployment.xml b/.idea/deployment.xml new file mode 100644 index 0000000..757729e --- /dev/null +++ b/.idea/deployment.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 10abbea..1b4a8b2 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -2,6 +2,15 @@ + + + + + + + + + \ No newline at end of file diff --git a/Command/CheckCommand.php b/Command/CheckCommand.php index bff5b6f..f058aee 100755 --- a/Command/CheckCommand.php +++ b/Command/CheckCommand.php @@ -2,12 +2,11 @@ namespace NTI\EmailBundle\Command; -use Doctrine\ORM\EntityManager; use NTI\EmailBundle\Entity\Email; +use NTI\EmailBundle\Entity\Smtp; +use Swift_Spool; use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; -use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; class CheckCommand extends ContainerAwareCommand @@ -22,8 +21,56 @@ protected function configure() protected function execute(InputInterface $input, OutputInterface $output) { - $spoolFolder = $this->getContainer()->getParameter('swiftmailer.spool.default.file.path'); $em = $this->getContainer()->get('doctrine')->getManager(); + + /** @var Smtp $smtp */ + $smtp = $em->getRepository('NTIEmailBundle:Smtp')->findOneBy(array("environment" => $this->getContainer()->getParameter('environment'))); + + if (!$smtp) { + if ($this->getContainer()->has('nti.logger')) { + $this->getContainer()->get('nti.logger')->logError("Unable to find an SMTP configuration for this environment."); + } + return false; + } + + + $spoolFolder = $this->getContainer()->getParameter('swiftmailer.spool.default.file.path'); + + // Send Emails + //create an instance of the spool object pointing to the right position in the filesystem + $spool = new \Swift_FileSpool($spoolFolder); + + //create a new instance of Swift_SpoolTransport that accept an argument as Swift_FileSpool + $transport = \Swift_SpoolTransport::newInstance($spool); + + //now create an instance of the transport you usually use with swiftmailer + //to send real-time email + $realTransport = \Swift_SmtpTransport::newInstance( + $smtp->getHost(), + $smtp->getPort(), + $smtp->getEncryption() + ) + ->setUsername($smtp->getUser()) + ->setPassword($smtp->getPassword()); + + /** @var \Swift_FileSpool $spool */ + $spool = $transport->getSpool(); + $spool->setMessageLimit(10); + $spool->setTimeLimit(100); + + $sent = 0; + + try { + $sent = $spool->flushQueue($realTransport); + } catch (\Exception $ex) { + if($this->getContainer()->has('nti.logger')){ + $this->getContainer()->get('nti.logger')->logException($ex); + } + } + + $output->writeln("Sent ".$sent." emails."); + + // Check email statuses $emails = $em->getRepository('NTIEmailBundle:Email')->findEmailsToCheck(); if(count($emails) <= 0) { @@ -34,15 +81,33 @@ protected function execute(InputInterface $input, OutputInterface $output) /** @var Email $email */ foreach($emails as $email) { - // Update last check date - $email->setLastCheck(new \DateTime()); - // Check if it is sending if(file_exists($spoolFolder."/".$email->getFilename().".sending")) { + $retry = new \DateTime(); + $retry->sub(new \DateInterval('PT1M')); + if($email->getLastCheck() < $retry) { + // Retry + if($email->getRetryCount() >= 5) { + $email->setLastCheck(new \DateTime()); + $email->setRetryCount(0); // Reset count + $email->setStatus(Email::STATUS_FAILURE); + continue; + } else { + @rename($spoolFolder."/".$email->getFilename().".sending", $spoolFolder."/".$email->getFilename()); + $count = $email->getRetryCount() ? $email->getRetryCount() : 1; + $email->setRetryCount($count + 1); + $email->setStatus(Email::STATUS_QUEUE); + continue; + } + } $email->setStatus(Email::STATUS_SENDING); continue; } + // Update last check date + $email->setLastCheck(new \DateTime()); + + // Check if it's creating, in this case, the mailer didn't get to create the // file inside the hash folder before the code reaches it, therefore we have to check // the hash folder so we can finish that process here diff --git a/Command/ResendCommand.php b/Command/ResendCommand.php new file mode 100644 index 0000000..40657fe --- /dev/null +++ b/Command/ResendCommand.php @@ -0,0 +1,45 @@ +setName('nti:email:resend') + ->setDescription("Resends an email by putting it in the spool folder again and changing the status to QUEUE") + ->addArgument("emailId", InputArgument::REQUIRED, "The Email Id to be resent") + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $id = $input->getArgument("emailId"); + if(!$id) { + $output->writeln("The Email ID is required."); + return; + } + + $em = $this->getContainer()->get('doctrine')->getManager(); + $email = $em->getRepository('NTIEmailBundle:Email')->find($id); + if(!$email) { + $output->writeln("The Email was not found."); + return; + } + + $smtpService = $this->getContainer()->get('nti.mailer'); + + $smtpService->resend($email); + $output->writeln("The Email was moved to the queue."); + } +} \ No newline at end of file diff --git a/DependencyInjection/NTIEmailExtension.php b/DependencyInjection/NTIEmailExtension.php index 305b5eb..655a470 100644 --- a/DependencyInjection/NTIEmailExtension.php +++ b/DependencyInjection/NTIEmailExtension.php @@ -18,7 +18,7 @@ class NTIEmailExtension extends Extension * {@inheritdoc} */ public function load(array $configs, ContainerBuilder $container) - { + { $configuration = new Configuration(); $config = $this->processConfiguration($configuration, $configs); diff --git a/Entity/Email.php b/Entity/Email.php index c4ab6b2..c5b37ff 100644 --- a/Entity/Email.php +++ b/Entity/Email.php @@ -2,7 +2,9 @@ namespace NTI\EmailBundle\Entity; +use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; +use NTIEmailBundle\Entity\EmailAttachment; /** * Email @@ -31,44 +33,44 @@ class Email /** * @var string * - * @ORM\Column(name="filename", type="string", length=255, nullable=true) + * @ORM\Column(name="filename", type="string", length=255) */ private $filename; /** * @var string * - * @ORM\Column(name="hash", type="string", length=255) + * @ORM\Column(name="path", type="text") */ - private $hash; + private $path; /** * @var string * - * @ORM\Column(name="path", type="string", length=255) + * @ORM\Column(name="message_from", type="string", length=255) */ - private $path; + private $messageFrom; /** * @var string * - * @ORM\Column(name="status", type="string", length=255) + * @ORM\Column(name="message_to", type="string", length=255) */ - private $status; + private $messageTo; /** * @var string * - * @ORM\Column(name="message_from", type="string", length=255) + * @ORM\Column(name="message_cc", type="string", length=255, nullable=true) */ - private $messageFrom; + private $messageCc; /** * @var string * - * @ORM\Column(name="message_to", type="string", length=255) + * @ORM\Column(name="message_bcc", type="string", length=255, nullable=true) */ - private $messageTo; + private $messageBcc; /** * @var string @@ -87,9 +89,16 @@ class Email /** * @var string * - * @ORM\Column(name="file_content", type="text") + * @ORM\Column(name="retry_count", type="integer", nullable=true) */ - private $fileContent; + private $retryCount; + + /** + * @var string + * + * @ORM\Column(name="status", type="string", length=255) + */ + private $status; /** * @var \DateTime @@ -105,6 +114,13 @@ class Email */ private $lastCheck; + /** + * @var array + * + * @ORM\Column(name="attachments", type="array", nullable=true); + */ + private $attachments; + public function __construct() { $this->status = self::STATUS_QUEUE; } @@ -119,37 +135,7 @@ public function getId() return $this->id; } - /** - * @return string - */ - public function getHash() - { - return $this->hash; - } - /** - * @param string $hash - */ - public function setHash($hash) - { - $this->hash = $hash; - } - - /** - * @return string - */ - public function getPath() - { - return $this->path; - } - - /** - * @param string $path - */ - public function setPath($path) - { - $this->path = $path; - } /** * Set messageFrom @@ -294,6 +280,24 @@ public function getFilename() return $this->filename; } + /** + * @return string + */ + public function getPath() + { + return $this->path; + } + + /** + * @param string $path + * @return Email + */ + public function setPath($path) + { + $this->path = $path; + return $this; + } + /** * Set status * @@ -319,27 +323,21 @@ public function getStatus() } /** - * Set fileContent - * - * @param string $fileContent - * - * @return Email + * @return string */ - public function setFileContent($fileContent) + public function getRetryCount() { - $this->fileContent = $fileContent; - - return $this; + return $this->retryCount; } /** - * Get fileContent - * - * @return string + * @param string $retryCount + * @return Email */ - public function getFileContent() + public function setRetryCount($retryCount) { - return $this->fileContent; + $this->retryCount = $retryCount; + return $this; } /** @@ -365,4 +363,58 @@ public function getLastCheck() { return $this->lastCheck; } + + /** + * @return string + */ + public function getMessageCc() + { + return $this->messageCc; + } + + /** + * @param string $messageCc + * @return Email + */ + public function setMessageCc($messageCc) + { + $this->messageCc = $messageCc; + return $this; + } + + /** + * @return string + */ + public function getMessageBcc() + { + return $this->messageBcc; + } + + /** + * @param string $messageBcc + * @return Email + */ + public function setMessageBcc($messageBcc) + { + $this->messageBcc = $messageBcc; + return $this; + } + + /** + * @return array + */ + public function getAttachments() + { + return $this->attachments; + } + + /** + * @param array $attachments + * @return Email + */ + public function setAttachments($attachments) + { + $this->attachments = $attachments; + return $this; + } } diff --git a/Entity/Email.php~ b/Entity/Email.php~ deleted file mode 100644 index 2c12c9d..0000000 --- a/Entity/Email.php~ +++ /dev/null @@ -1,297 +0,0 @@ -status = self::STATUS_QUEUE; - } - - /** - * Get id - * - * @return integer - */ - public function getId() - { - return $this->id; - } - - /** - * Set messageFrom - * - * @param string $messageFrom - * - * @return Email - */ - public function setMessageFrom($messageFrom) - { - $this->messageFrom = $messageFrom; - - return $this; - } - - /** - * Get messageFrom - * - * @return string - */ - public function getMessageFrom() - { - return $this->messageFrom; - } - - /** - * Set messageTo - * - * @param string $messageTo - * - * @return Email - */ - public function setMessageTo($messageTo) - { - $this->messageTo = $messageTo; - - return $this; - } - - /** - * Get messageTo - * - * @return string - */ - public function getMessageTo() - { - return $this->messageTo; - } - - /** - * Set messageSubject - * - * @param string $messageSubject - * - * @return Email - */ - public function setMessageSubject($messageSubject) - { - $this->messageSubject = $messageSubject; - - return $this; - } - - /** - * Get messageSubject - * - * @return string - */ - public function getMessageSubject() - { - return $this->messageSubject; - } - - /** - * Set messageBody - * - * @param string $messageBody - * - * @return Email - */ - public function setMessageBody($messageBody) - { - $this->messageBody = $messageBody; - - return $this; - } - - /** - * Get messageBody - * - * @return string - */ - public function getMessageBody() - { - return $this->messageBody; - } - - /** - * Set createdOn - * @ORM\PrePersist - * - * @return Email - */ - public function setCreatedOn() - { - $this->createdOn = new \DateTime(); - - return $this; - } - - /** - * Get createdOn - * - * @return \DateTime - */ - public function getCreatedOn() - { - return $this->createdOn; - } - - /** - * Set filename - * - * @param string $filename - * - * @return Email - */ - public function setFilename($filename) - { - $this->filename = $filename; - - return $this; - } - - /** - * Get filename - * - * @return string - */ - public function getFilename() - { - return $this->filename; - } - - /** - * Set status - * - * @param string $status - * - * @return Email - */ - public function setStatus($status) - { - $this->status = $status; - - return $this; - } - - /** - * Get status - * - * @return string - */ - public function getStatus() - { - return $this->status; - } - - /** - * Set fileContent - * - * @param string $fileContent - * - * @return Email - */ - public function setFileContent($fileContent) - { - $this->fileContent = $fileContent; - - return $this; - } - - /** - * Get fileContent - * - * @return string - */ - public function getFileContent() - { - return $this->fileContent; - } -} diff --git a/Entity/Smtp.php b/Entity/Smtp.php new file mode 100644 index 0000000..e0cff4d --- /dev/null +++ b/Entity/Smtp.php @@ -0,0 +1,219 @@ +enabled = true; + } + + /** + * @return integer + */ + public function getId() { + return $this->id; + } + + /** + * @return string + */ + public function getHost() + { + return $this->host; + } + + /** + * @param string $host + * @return Smtp + */ + public function setHost($host) + { + $this->host = $host; + return $this; + } + + /** + * @return string + */ + public function getPort() + { + return $this->port; + } + + /** + * @param string $port + * @return Smtp + */ + public function setPort($port) + { + $this->port = $port; + return $this; + } + + /** + * @return string + */ + public function getEncryption() + { + return $this->encryption; + } + + /** + * @param string $encryption + * @return Smtp + */ + public function setEncryption($encryption) + { + $this->encryption = $encryption; + return $this; + } + + /** + * @return string + */ + public function getTransport() + { + return $this->transport; + } + + /** + * @param string $transport + * @return Smtp + */ + public function setTransport($transport) + { + $this->transport = $transport; + return $this; + } + + /** + * @return string + */ + public function getUser() + { + return $this->user; + } + + /** + * @param string $user + * @return Smtp + */ + public function setUser($user) + { + $this->user = $user; + return $this; + } + + /** + * @return string + */ + public function getPassword() + { + return $this->password; + } + + /** + * @param string $password + * @return Smtp + */ + public function setPassword($password) + { + $this->password = $password; + return $this; + } + + /** + * @return string + */ + public function getEnvironment() + { + return $this->environment; + } + + /** + * @param string $environment + * @return Smtp + */ + public function setEnvironment($environment) + { + $this->environment = $environment; + return $this; + } + + +} diff --git a/Form/SmtpType.php b/Form/SmtpType.php new file mode 100644 index 0000000..19c1534 --- /dev/null +++ b/Form/SmtpType.php @@ -0,0 +1,50 @@ +add("host", TextType::class, array("label" => "Host")) + ->add("port", TextType::class, array("label" => "Port")) + ->add("encryption", TextType::class, array("label" => "Encryption")) + ->add("user", TextType::class, array("label" => "User")) + ->add("password", TextType::class, array("label" => "Password")) + ; + } + + /** + * {@inheritdoc} + */ + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults(array( + 'data_class' => 'NTI\EmailBundle\Entity\Smtp', + 'allow_extra_fields' => true, + 'csrf_protection' => false, + 'cascade_validation' => true, + )); + } + + /** + * {@inheritdoc} + */ + public function getBlockPrefix() + { + return 'nti_smtp_smtp'; + } + + +} diff --git a/Repository/EmailRepository.php b/Repository/EmailRepository.php index 836b44d..754b5f4 100644 --- a/Repository/EmailRepository.php +++ b/Repository/EmailRepository.php @@ -1,6 +1,7 @@ createQueryBuilder('e'); $qb->andWhere('e.status != :sent')->setParameter("sent", Email::STATUS_SENT); + $qb->andWhere('e.status != :failed')->setParameter("failed", Email::STATUS_FAILURE); $qb->addOrderBy('e.lastCheck', 'asc'); $qb->setMaxResults($limit); return $qb->getQuery()->getResult(); diff --git a/Resources/config/services.yml b/Resources/config/services.yml index 5e28b36..a2946c7 100644 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -1,7 +1,10 @@ services: -# nti_email.example: -# class: NTI\EmailBundle\Example -# arguments: ["@service_id", "plain_value", "%parameter%"] - nti.mailer: - class: NTI\EmailBundle\Service\Mailer - arguments: ["@service_container", "@templating"] + nti.mailer: + class: NTI\EmailBundle\Service\Mailer + arguments: ["@service_container", "@templating"] + nti.form.smtptype: + class: NTI\EmailBundle\Form\SmtpType + arguments: ["@doctrine.orm.entity_manager"] + tags: + - { name: form.type } + diff --git a/Service/Mailer.php b/Service/Mailer.php index bb3403b..a07b331 100644 --- a/Service/Mailer.php +++ b/Service/Mailer.php @@ -2,10 +2,13 @@ namespace NTI\EmailBundle\Service; +use NTI\EmailBundle\Entity\Email; +use NTI\EmailBundle\Entity\Smtp; +use Doctrine\ORM\EntityManagerInterface; use Swift_Message; use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface; use Symfony\Component\DependencyInjection\ContainerInterface; -use NTI\EmailBundle\Entity\Email; + class Mailer { @@ -29,21 +32,116 @@ public function __construct(ContainerInterface $container, EngineInterface $temp * @param $subject * @param $template * @param array $parameters - * @param null $attachment + * @param array $attachments + * @return bool + */ + public function sendFromTemplate($from, $to, $bcc, $subject, $template, $parameters = array(), $attachments = array()) { + $html = $this->templating->render($template, $parameters); + $body = $this->embedBase64Images($message, $html); + return $this->sendEmail($from, $to, $cc, $bcc, $subject, $body, $attachments); + } + + /** + * Send an email with a twig template + * + * @param $from + * @param $to + * @param $bcc + * @param $subject + * @param $html + * @param array $parameters + * @param array $attachments + * @return bool + */ + public function sendEmail($from, $to, $cc, $bcc, $subject, $html, $attachments = array()) { + return $this->processEmail($from, $to, $cc, $bcc, $subject, $html, $attachments); + } + + /** + * + * @param Email $email + * @return $this + */ + public function resend(Email $email) { + $this->processEmail( + $email->getMessageFrom(), + $email->getMessageTo(), + $email->getMessageCc(), + $email->getMessageBcc(), + $email->getMessageSubject(), + $email->getMessageBody(), + $email->getAttachments() + ); + return $this; + } + + /** + * Test the SMTP configuration + * + * @param Email $email + * @return $this + */ + public function testConfiguration(Smtp $smtp) { + if(!$smtp) { + return false; + } + + $realTransport = \Swift_SmtpTransport::newInstance( + $smtp->getHost(), + $smtp->getPort(), + $smtp->getEncryption() + ) + ->setUsername($smtp->getUser()) + ->setPassword($smtp->getPassword()); + + try { + $realTransport->start(); + return true; + } catch (\Exception $ex) { + if($this->container->has('nti.logger')) { + $this->container->get('nti.logger')->logException($ex); + } + return false; + } + } + + + /** + * Send an email with a twig template + * + * @param $from + * @param $to + * @param array $cc + * @param array $bcc + * @param $subject + * @param string $html + * @param array $attachments * @return bool */ - public function sendFromTemplate($from, $to, $bcc, $subject, $template, $parameters = array(), $attachment = null) { + private function processEmail($from, $to, $cc = array(), $bcc = array(), $subject, $html = "", $attachments = array()) { // If is a test environment prepend TEST - to the subject - if($this->container->hasParameter('environment') && $this->container->getParameter('environment') == "test") { + $environment = $this->container->getParameter('environment'); + + if($environment == "dev") { + $to = ($this->container->hasParameter('development_recipients')) ? $this->container->getParameter('development_recipients') : $to; + $cc = ($this->container->hasParameter('development_recipients')) ? array() : $cc; + $bcc = ($this->container->hasParameter('development_recipients')) ? array() : $bcc; + } + + if($this->container->hasParameter('environment') && $environment == "test") { $subject = "TEST - ".$subject; } /** @var Swift_Message $message */ + $message = \Swift_Message::newInstance("sendmail -bs") ->setSubject($subject) - ->setFrom($from) - ->setBody($this->templating->render($template, $parameters), 'text/html'); + ->setFrom($from); + + $body = $this->embedBase64Images($message, $html); + + $message->setBody($body, 'text/html'); $message->setContentType("text/html"); @@ -52,16 +150,36 @@ public function sendFromTemplate($from, $to, $bcc, $subject, $template, $paramet $to = $this->container->hasParameter('event_development_email') ? $this->container->getParameter('event_development_email') : $to; } - $message->setTo($to); + if(is_array($to)) { + foreach($to as $recipient) { + $message->addTo($recipient); + } + } else { + $message->setTo($to); + } if(is_array($bcc)) { foreach($bcc as $recipient) { $message->addBcc($recipient); } + } else { + $message->setBcc($bcc); } - if($attachment && file_exists($attachment)) { - $message->attach(\Swift_Attachment::fromPath($attachment)); + if(is_array($cc)) { + foreach($cc as $recipient) { + $message->addCc($recipient); + } + } else { + $message->setCc($cc); + } + + if(is_array($attachments)) { + foreach($attachments as $attachment) { + if(file_exists($attachment) && is_readable($attachment)) { + $message->attach(\Swift_Attachment::fromPath($attachment)); + } + } } if($this->container->hasParameter("app.mailer.master_bcc")) { @@ -69,16 +187,29 @@ public function sendFromTemplate($from, $to, $bcc, $subject, $template, $paramet } try { + /** @var EntityManagerInterface $em */ + $em = $this->container->get('doctrine')->getManager(); + + /** @var Smtp $smtp */ + $smtp = $em->getRepository('NTIEmailBundle:Smtp')->findOneBy(array("environment" => $environment)); + + if (!$smtp) { + if ($this->container->has('nti.logger')) { + $this->container->get('nti.logger')->logError("Unable to find an SMTP configuration for this environment."); + } + return false; + } - /** @var \Swift_Mailer $mailer */ - $mailer = $this->container->get('mailer'); // Create a new temporary spool $hash = md5(uniqid(time())); - /** @var \Swift_Transport_SpoolTransport $transport */ - $transport = $mailer->getTransport(); $tempSpoolPath = $this->container->getParameter('swiftmailer.spool.default.file.path')."/".$hash."/"; $tempSpool = new \Swift_FileSpool($tempSpoolPath); + + /** @var \Swift_Mailer $mailer */ + $mailer = \Swift_Mailer::newInstance(\Swift_SpoolTransport::newInstance($tempSpool)); + + $transport = $mailer->getTransport(); $transport->setSpool($tempSpool); // Send the email to generate the file @@ -119,18 +250,15 @@ public function sendFromTemplate($from, $to, $bcc, $subject, $template, $paramet $recipients = (is_array($message->getTo())) ? join(', ', array_keys($message->getTo())) : $message->getTo(); $email->setFilename($filename); $email->setPath($this->container->getParameter('swiftmailer.spool.default.file.path')."/"); - $email->setHash($hash); $email->setMessageFrom($from); $email->setMessageTo($recipients); $email->setMessageSubject($message->getSubject()); $email->setMessageBody($message->getBody()); - if(!$filename == null) { - $email->setFileContent(base64_encode(file_get_contents($tempSpoolPath."/".$filename))); - } else { + $email->setAttachments($attachments); + if($filename == null) { $email->setStatus(Email::STATUS_FAILURE); } - $em->persist($email); $em->flush(); @@ -146,35 +274,57 @@ public function sendFromTemplate($from, $to, $bcc, $subject, $template, $paramet } } return false; - } - /** - * Adds the file to the spool folder so that the - * cron job resends it again. - * - * @param Email $email - * @return $this + * @param Swift_Message $message + * @param $body + * @return mixed */ - public function resend(Email $email) { - $path = $this->container->getParameter('swiftmailer.spool.default.file.path'); - if(!fwrite(fopen($path."/".$email->getFilename(), "w+"), base64_decode($email->getFileContent()))) { - if($this->container->has('nti.logger')) { - $this->container->get('nti.logger')->logError("An error occurred creating the email file in the spool for resending."); + private function embedBase64Images(Swift_Message $message, $body) + { + // Temporary directory to save the images + $tempDir = $this->container->getParameter('kernel.root_dir')."/../web/tmp"; + if(!file_exists($tempDir)) { + if(!mkdir($tempDir, 0777, true)) { + throw new FileNotFoundException("Unable to create temporary directory for images."); } } - $email->setStatus(Email::STATUS_QUEUE); - $em = $this->container->get('doctrine')->getManager(); - try { - $em->flush(); - } catch (\Exception $ex) { - if($this->container->has('nti.logger')) { - $this->container->get('nti.logger')->logException($ex); - $this->container->get('nti.logger')->logError("An error occurred changing the status for resending..."); + + $arrSrc = array(); + if (!empty($body)) + { + preg_match_all('/]+>/i', stripcslashes($body), $imgTags); + + //All img tags + for ($i=0; $i < count($imgTags[0]); $i++) + { + preg_match('/src="([^"]+)/i', $imgTags[0][$i], $withSrc); + + //Remove src + $withoutSrc = str_ireplace('src="', '', $withSrc[0]); + $srcContent = $withoutSrc; // Save the previous content to replace with the cid + + //data:image/png;base64, + if (strpos($withoutSrc, ";base64,")) + { + //data:image/png;base64,..... + list($type, $data) = explode(";base64,", $withoutSrc); + //data:image/png + list($part, $ext) = explode("/", $type); + //Paste in temp file + $withoutSrc = $tempDir."/".uniqid("temp_").".".$ext; + @file_put_contents($withoutSrc, base64_decode($data)); + $cid = $message->embed((\Swift_Image::fromPath($withoutSrc))); + $body = str_replace($srcContent, $cid, $body); + } + + //Set to array + $arrSrc[] = $withoutSrc; } } - - return $this; + return $body; } + + } \ No newline at end of file