Skip to content

Commit

Permalink
Merge pull request #78 from sailthru/email_queuing
Browse files Browse the repository at this point in the history
Email queuing
  • Loading branch information
aingram committed Mar 30, 2021
2 parents 22c713b + 3cbded0 commit e9d7124
Show file tree
Hide file tree
Showing 15 changed files with 455 additions and 58 deletions.
20 changes: 14 additions & 6 deletions Helper/Settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ class Settings extends AbstractHelper
// const XML_CUSTOMER_ID = "magesail_"

// Lists
const XML_ONREGISTER_LIST_ENABLED = "magesail_lists/lists/enable_signup_list";
const XML_ONREGISTER_LIST_VALUE = "magesail_lists/lists/signup_list";
const XML_NEWSLETTER_LIST_ENABLED = "magesail_lists/lists/enable_newsletter";
const XML_NEWSLETTER_LIST_VALUE = "magesail_lists/lists/newsletter_list";
const XML_SELECT_CASE = "magesail_lists/names/select_case";
const XML_ONREGISTER_LIST_ENABLED = "magesail_lists/lists/enable_signup_list";
const XML_ONREGISTER_LIST_VALUE = "magesail_lists/lists/signup_list";
const XML_NEWSLETTER_LIST_ENABLED = "magesail_lists/lists/enable_newsletter";
const XML_NEWSLETTER_LIST_VALUE = "magesail_lists/lists/newsletter_list";
const XML_SELECT_CASE = "magesail_lists/names/select_case";

// Transactional Emails
const XML_ABANDONED_CART_ENABLED = "magesail_send/abandoned_cart/enabled";
Expand All @@ -42,9 +42,12 @@ class Settings extends AbstractHelper
const XML_TRANSACTIONALS_SENDER = "magesail_send/transactionals/from_sender";
const XML_ORDER_ENABLED = "magesail_send/transactionals/purchase_enabled";
const XML_ORDER_TEMPLATE = "magesail_send/transactionals/purchase_template";
const XML_TEMPLATES_CACHE_LIFETIME = "magesail_send/advanced/templates_cache_lifetime";
const XML_USE_EMAIL_QUEUE = "magesail_send/advanced/use_email_queue";
const LO_ABANDONED_CART_ENABLED = "1";

const XML_TEMPLATES_CACHE_LIFETIME = "magesail_send/transactionals/templates_cache_lifetime";
// Queue settings
const QUEUE_ATTEMPTS_COUNT = 3;

/** Path to the `transactionals` tab. */
const XML_TRANSACTIONALS_PATH = 'magesail_send/transactionals/';
Expand Down Expand Up @@ -163,6 +166,11 @@ public function getTemplatesCacheLifetime($storeId = null)
return $this->getSettingsVal(self::XML_TEMPLATES_CACHE_LIFETIME, $storeId);
}

public function getUseEmailQueue($storeId = null)
{
return $this->getSettingsVal(self::XML_USE_EMAIL_QUEUE, $storeId);
}

public function getSender($storeId = null)
{
return $this->getSettingsVal(self::XML_TRANSACTIONALS_SENDER, $storeId);
Expand Down
77 changes: 77 additions & 0 deletions Mail/Queue/EmailSendProcessor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php

namespace Sailthru\MageSail\Mail\Queue;

use Psr\Log\LoggerInterface;
use Sailthru\MageSail\Helper\Settings;
use Sailthru\MageSail\Mail\Transport\Sailthru as SailthruTransport;
use Sailthru\MageSail\Mail\Transport\SailthruFactory as SailthruTransportFactory;

class EmailSendProcessor
{
/**
* @var EmailSendPublisher
*/
protected $publisher;

/**
* @var LoggerInterface
*/
protected $logger;

/**
* @var Settings
*/
protected $settingsHelper;

/**
* @var SailthruTransportFactory
*/
protected $sailthruTransportFactory;

public function __construct(
EmailSendPublisher $publisher,
LoggerInterface $logger,
Settings $settingsHelper,
SailthruTransportFactory $sailthruTransportFactory
) {
$this->publisher = $publisher;
$this->logger = $logger;
$this->settingsHelper = $settingsHelper;
$this->sailthruTransportFactory = $sailthruTransportFactory;
}

/**
* Init and return transport
*
* @param array $data
*
* @return SailthruTransport
*/
public function getTransport(array $data)
{
return $this->sailthruTransportFactory->create(['data' => $data]);
}

/**
* Consumer handler of send Sailthru email
*
* @param string $messageData
*
* @return $this
*
* @throws \Exception
*/
public function execute($messageData)
{
$decodedData = json_decode($messageData, true);
try {
$this->getTransport($decodedData)->sendMessage();
} catch (\Throwable $t) {
$this->logger->critical($t->getMessage());
$this->publisher->execute($decodedData, ($decodedData['attempt'] ?? 0) + 1);
}

return $this;
}
}
85 changes: 85 additions & 0 deletions Mail/Queue/EmailSendPublisher.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?php

namespace Sailthru\MageSail\Mail\Queue;

use Magento\Framework\Amqp\Config as AmqpConfig;
use Magento\Framework\MessageQueue\PublisherInterface;
use Sailthru\MageSail\Helper\Settings as SettingsHelper;

class EmailSendPublisher
{
/**
* Topic names
*/
const TOPIC_NAME_DB = 'sailthru.email.send.db';
const TOPIC_NAME_AMQP = 'sailthru.email.send.amqp';

/**
* @var AmqpConfig
*/
protected $amqpConfig;

/**
* @var PublisherInterface
*/
protected $publisher;

/**
* EmailSendPublisher constructor.
*
* @param AmqpConfig $amqpConfig
* @param PublisherInterface $publisher
*/
public function __construct(
AmqpConfig $amqpConfig,
PublisherInterface $publisher
) {
$this->amqpConfig = $amqpConfig;
$this->publisher = $publisher;
}

/**
* Get topic name
*
* @return string
*/
public function getTopicName()
{
try {
return $this->isAmqpConfigured() ? self::TOPIC_NAME_AMQP : self::TOPIC_NAME_DB;
} catch (\LogicException $exception) {
return self::TOPIC_NAME_DB;
}
}

/**
* Check Amqp is configured.
*
* @return bool
*
* @throws \LogicException
*/
protected function isAmqpConfigured()
{
return $this->amqpConfig->getValue(AmqpConfig::HOST) ? true : false;
}

/**
* Add message to queue
*
* @param array $messageData
* @param int $attempt
*
* @return $this
*/
public function execute(array $messageData, int $attempt = 0)
{
if ($attempt >= SettingsHelper::QUEUE_ATTEMPTS_COUNT) {
return $this;
}
$messageData['attempt'] = $attempt;
$this->publisher->publish($this->getTopicName(), json_encode($messageData));

return $this;
}
}
97 changes: 51 additions & 46 deletions Mail/Transport.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
use Sailthru\MageSail\Helper\ClientManager;
use Sailthru\MageSail\Helper\Settings;
use Sailthru\MageSail\Helper\Templates as SailthruTemplates;
use Sailthru\MageSail\Mail\Transport\SailthruFactory as SailthruTransportFactory;
use Sailthru\MageSail\Mail\Queue\EmailSendPublisher;
use Zend\Mail\Message as ZendMessage;
use Zend\Mail\Address\AddressInterface;
use Zend\Mail\Header\HeaderInterface;
Expand All @@ -29,7 +31,13 @@ class Transport extends \Magento\Email\Model\Transport
/** @var StoreManagerInterface */
protected $storeManager;

/** @var RequestInterface */
/** @var SailthruTransportFactory */
protected $sailthruTransportFactory;

/** @var EmailSendPublisher */
protected $emailSendPublisher;

/** @var RequestInterface */
protected $request;

/** @var string */
Expand All @@ -44,7 +52,9 @@ class Transport extends \Magento\Email\Model\Transport
* @param ScopeConfigInterface $scopeConfig
* @param SailthruTemplates $sailthruTemplates
* @param StoreManagerInterface $storeManager
* @param RequestInterface $request
* @param SailthruTransportFactory $sailthruTransportFactory
* @param EmailSendPublisher $emailSendPublisher
* @param RequestInterface $request
* @param null|array
*/
public function __construct(
Expand All @@ -54,21 +64,26 @@ public function __construct(
ScopeConfigInterface $scopeConfig,
SailthruTemplates $sailthruTemplates,
StoreManagerInterface $storeManager,
SailthruTransportFactory $sailthruTransportFactory,
EmailSendPublisher $emailSendPublisher,
RequestInterface $request,
$parameters = null
) {
$this->clientManager = $clientManager;
$this->sailthruSettings = $sailthruSettings;
$this->sailthruTemplates = $sailthruTemplates;
$this->storeManager = $storeManager;
$this->sailthruTransportFactory = $sailthruTransportFactory;
$this->emailSendPublisher = $emailSendPublisher;
$this->request = $request;
parent::__construct($message, $scopeConfig, $parameters);
}

/**
* Send a mail using this transport
*
* @return void
* @return Transport
*
* @throws \Magento\Framework\Exception\MailException
*/
public function sendMessage()
Expand All @@ -84,61 +99,51 @@ public function sendMessage()
$template = $this->sailthruSettings->getTemplateName($templateData['identifier'], $storeId);

if ($this->sailthruSettings->getTransactionalsEnabled($storeId) && $template['name'] != 'disableSailthru') {
$this->sendViaAPI($templateData, $storeId);
} else {
parent::sendMessage();
$emailData = $this->getEmailData();
if ($this->sailthruSettings->getUseEmailQueue($storeId)) {
$this->emailSendPublisher->execute([
'template_data' => $templateData,
'email_data' => $emailData,
'store_id' => $storeId,
]);

return $this;
}
/** @var Transport\Sailthru $transport */
$transport = $this->sailthruTransportFactory->create([
'data' => [
'template_data' => $templateData,
'email_data' => $emailData,
'store_id' => $storeId,
],
]);
$transport->sendMessage();

return $this;
}

parent::sendMessage();
} catch (\Exception $e) {
throw new \Magento\Framework\Exception\MailException(new \Magento\Framework\Phrase($e->getMessage()), $e);
}

return $this;
}

/**
* To send `Magento Generic` or `Magento Specific` template.
* Get data for email
*
* @param array $templateData
* @param int|string|null $storeId
*
* @throws MailException
* @return array
*/
public function sendViaAPI($templateData, $storeId)
protected function getEmailData()
{
$client = $this->clientManager->getClient($storeId);
$message = ZendMessage::fromString($this->getMessage()->getRawMessage());
$vars = [
'subj' => $this->prepareSubject($message),
'content' => $this->getMessage()->getDecodedBodyText(),
];

try {
# Get template name
$template = $this->sailthruSettings->getTemplateName($templateData['identifier'], $storeId);
# Vars used in Sailthru Magento 1 extension and template file.
$vars += $this->sailthruSettings->getTemplateAdditionalVariables(
$template['orig_template_code'],
$templateData['variables']
);

$templateName = $template['name'];
if (!$this->sailthruTemplates->templateExists($templateName, $storeId)) {
$this->sailthruTemplates->saveTemplate($templateName, $this->sailthruSettings->getSender($storeId),
$storeId);
}

$params = [
'template' => $templateName,
'email' => $this->prepareRecipients($message),
'vars' => $vars,
];

$response = $client->apiPost('send', $params);
if (isset($response['error'])) {
$client->logger($response['errormsg']);
throw new MailException(__($response['errormsg']));
}
} catch (\Exception $e) {
throw new MailException(__("Couldn't send the mail {$e->getMessage()}"));
}
return [
'to' => $this->prepareRecipients($message),
'subject' => $this->prepareSubject($message),
'content' => $this->getMessage()->getDecodedBodyText()
];
}

/**
Expand Down
Loading

0 comments on commit e9d7124

Please sign in to comment.