55 */
66namespace Magento \Sales \Model ;
77
8+ use Magento \Framework \App \Config \ScopeConfigInterface ;
89use Magento \Framework \App \Config \ValueFactory ;
910use Magento \Framework \App \Config \ValueInterface ;
1011use Magento \Framework \App \ObjectManager ;
1112use Magento \Sales \Model \Order \Email \Container \IdentityInterface ;
13+ use Magento \Sales \Model \Order \Email \Sender ;
1214use Magento \Sales \Model \ResourceModel \Collection \AbstractCollection ;
15+ use Magento \Sales \Model \ResourceModel \EntityAbstract ;
16+ use Magento \Store \Model \StoreManagerInterface ;
1317
1418/**
1519 * Sales emails sending
1923 */
2024class EmailSenderHandler
2125{
26+ /**
27+ * Configuration path for defining asynchronous email sending attempts
28+ */
29+ public const XML_PATH_ASYNC_SENDING_ATTEMPTS = 'sales_email/general/async_sending_attempts ' ;
30+
2231 /**
2332 * Email sender model.
2433 *
25- * @var \Magento\Sales\Model\Order\Email\ Sender
34+ * @var Sender
2635 */
2736 protected $ emailSender ;
2837
2938 /**
3039 * Entity resource model.
3140 *
32- * @var \Magento\Sales\Model\ResourceModel\ EntityAbstract
41+ * @var EntityAbstract
3342 */
3443 protected $ entityResource ;
3544
@@ -43,7 +52,7 @@ class EmailSenderHandler
4352 /**
4453 * Global configuration storage.
4554 *
46- * @var \Magento\Framework\App\Config\ ScopeConfigInterface
55+ * @var ScopeConfigInterface
4756 */
4857 protected $ globalConfig ;
4958
@@ -53,7 +62,7 @@ class EmailSenderHandler
5362 private $ identityContainer ;
5463
5564 /**
56- * @var \Magento\Store\Model\ StoreManagerInterface
65+ * @var StoreManagerInterface
5766 */
5867 private $ storeManager ;
5968
@@ -70,24 +79,24 @@ class EmailSenderHandler
7079 private $ modifyStartFromDate ;
7180
7281 /**
73- * @param \Magento\Sales\Model\Order\Email\ Sender $emailSender
74- * @param \Magento\Sales\Model\ResourceModel\ EntityAbstract $entityResource
82+ * @param Sender $emailSender
83+ * @param EntityAbstract $entityResource
7584 * @param AbstractCollection $entityCollection
76- * @param \Magento\Framework\App\Config\ ScopeConfigInterface $globalConfig
85+ * @param ScopeConfigInterface $globalConfig
7786 * @param IdentityInterface|null $identityContainer
78- * @param \Magento\Store\Model\ StoreManagerInterface|null $storeManager
87+ * @param StoreManagerInterface|null $storeManager
7988 * @param ValueFactory|null $configValueFactory
8089 * @param string|null $modifyStartFromDate
8190 */
8291 public function __construct (
83- \ Magento \ Sales \ Model \ Order \ Email \ Sender $ emailSender ,
84- \ Magento \ Sales \ Model \ ResourceModel \ EntityAbstract $ entityResource ,
92+ Sender $ emailSender ,
93+ EntityAbstract $ entityResource ,
8594 AbstractCollection $ entityCollection ,
86- \ Magento \ Framework \ App \ Config \ ScopeConfigInterface $ globalConfig ,
95+ ScopeConfigInterface $ globalConfig ,
8796 IdentityInterface $ identityContainer = null ,
88- \ Magento \ Store \ Model \ StoreManagerInterface $ storeManager = null ,
97+ StoreManagerInterface $ storeManager = null ,
8998 ?ValueFactory $ configValueFactory = null ,
90- ?string $ modifyStartFromDate = null
99+ ?string $ modifyStartFromDate = null ,
91100 ) {
92101 $ this ->emailSender = $ emailSender ;
93102 $ this ->entityResource = $ entityResource ;
@@ -97,21 +106,28 @@ public function __construct(
97106 $ this ->identityContainer = $ identityContainer ?: ObjectManager::getInstance ()
98107 ->get (\Magento \Sales \Model \Order \Email \Container \NullIdentity::class);
99108 $ this ->storeManager = $ storeManager ?: ObjectManager::getInstance ()
100- ->get (\ Magento \ Store \ Model \ StoreManagerInterface::class);
109+ ->get (StoreManagerInterface::class);
101110
102111 $ this ->configValueFactory = $ configValueFactory ?: ObjectManager::getInstance ()->get (ValueFactory::class);
103112 $ this ->modifyStartFromDate = $ modifyStartFromDate ?: $ this ->modifyStartFromDate ;
104113 }
105114
106115 /**
107116 * Handles asynchronous email sending
117+ *
108118 * @return void
109119 */
110120 public function sendEmails ()
111121 {
112122 if ($ this ->globalConfig ->getValue ('sales_email/general/async_sending ' )) {
113123 $ this ->entityCollection ->addFieldToFilter ('send_email ' , ['eq ' => 1 ]);
114- $ this ->entityCollection ->addFieldToFilter ('email_sent ' , ['null ' => true ]);
124+ $ this ->entityCollection ->addFieldToFilter (
125+ 'email_sent ' ,
126+ [
127+ ['null ' => true ],
128+ ['lteq ' => -1 ]
129+ ]
130+ );
115131 $ this ->filterCollectionByStartFromDate ($ this ->entityCollection );
116132 $ this ->entityCollection ->setPageSize (
117133 $ this ->globalConfig ->getValue ('sales_email/general/sending_limit ' )
@@ -120,6 +136,8 @@ public function sendEmails()
120136 /** @var \Magento\Store\Api\Data\StoreInterface[] $stores */
121137 $ stores = $ this ->getStores (clone $ this ->entityCollection );
122138
139+ $ maxSendAttempts = $ this ->globalConfig ->getValue (self ::XML_PATH_ASYNC_SENDING_ATTEMPTS );
140+
123141 /** @var \Magento\Store\Model\Store $store */
124142 foreach ($ stores as $ store ) {
125143 $ this ->identityContainer ->setStore ($ store );
@@ -131,12 +149,19 @@ public function sendEmails()
131149
132150 /** @var \Magento\Sales\Model\AbstractModel $item */
133151 foreach ($ entityCollection ->getItems () as $ item ) {
134- if ($ this ->emailSender ->send ($ item , true )) {
135- $ this ->entityResource ->saveAttribute (
136- $ item ->setEmailSent (true ),
137- 'email_sent '
138- );
152+ $ sendAttempts = $ item ->getEmailSent () ?? -$ maxSendAttempts ;
153+ $ isEmailSent = $ this ->emailSender ->send ($ item , true );
154+
155+ if ($ isEmailSent ) {
156+ $ sendAttempts = 1 ;
157+ } else {
158+ $ sendAttempts ++;
139159 }
160+
161+ $ this ->entityResource ->saveAttribute (
162+ $ item ->setEmailSent ($ sendAttempts ),
163+ 'email_sent '
164+ );
140165 }
141166 }
142167 }
@@ -157,7 +182,7 @@ private function getStores(
157182 $ entityCollection ->addAttributeToSelect ('store_id ' )->getSelect ()->group ('store_id ' );
158183 /** @var \Magento\Sales\Model\EntityInterface $item */
159184 foreach ($ entityCollection ->getItems () as $ item ) {
160- /** @var \Magento\Store\Model\ StoreManagerInterface $store */
185+ /** @var StoreManagerInterface $store */
161186 $ store = $ this ->storeManager ->getStore ($ item ->getStoreId ());
162187 $ stores [$ item ->getStoreId ()] = $ store ;
163188 }
0 commit comments