/** * @param $id * @param int $timeout * @param int $maxMailCount * @return bool|string * @throws \Bitrix\Main\ArgumentException * @throws \Bitrix\Main\DB\Exception * @throws \Bitrix\Main\Db\SqlQueryException * @throws \Exception */ public static function send($id, $timeout = 0, $maxMailCount = 0) { $start_time = getmicrotime(); @set_time_limit(0); static::$emailSentPerIteration = 0; $postingDb = PostingTable::getList(array('select' => array('ID', 'STATUS', 'MAILING_ID', 'MAILING_CHAIN_ID', 'MAILING_CHAIN_REITERATE' => 'MAILING_CHAIN.REITERATE', 'MAILING_CHAIN_IS_TRIGGER' => 'MAILING_CHAIN.IS_TRIGGER'), 'filter' => array('ID' => $id, 'MAILING.ACTIVE' => 'Y', 'MAILING_CHAIN.STATUS' => MailingChainTable::STATUS_SEND))); $postingData = $postingDb->fetch(); // posting not found if (!$postingData) { return static::SEND_RESULT_ERROR; } // if posting in new status, then import recipients from groups and set right status for sending $isInitGroupRecipients = false; $isChangeStatusToPart = false; if ($postingData["STATUS"] == PostingTable::STATUS_NEW) { $isInitGroupRecipients = true; $isChangeStatusToPart = true; } if ($postingData["STATUS"] != PostingTable::STATUS_PART && $postingData["MAILING_CHAIN_IS_TRIGGER"] == 'Y') { $isInitGroupRecipients = false; $isChangeStatusToPart = true; } if ($isInitGroupRecipients) { PostingTable::initGroupRecipients($postingData['ID']); } if ($isChangeStatusToPart) { PostingTable::update(array('ID' => $postingData['ID']), array('STATUS' => PostingTable::STATUS_PART)); $postingData["STATUS"] = PostingTable::STATUS_PART; } // posting not in right status if ($postingData["STATUS"] != PostingTable::STATUS_PART) { return static::SEND_RESULT_ERROR; } // lock posting for exclude double parallel sending if (static::lockPosting($id) === false) { throw new \Bitrix\Main\DB\Exception(Loc::getMessage('SENDER_POSTING_MANAGER_ERR_LOCK')); } // select all recipients of posting, only not processed $recipientDataDb = PostingRecipientTable::getList(array('filter' => array('POSTING_ID' => $postingData['ID'], 'STATUS' => PostingRecipientTable::SEND_RESULT_NONE), 'limit' => $maxMailCount)); while ($recipientData = $recipientDataDb->fetch()) { // create name from email $recipientEmail = $recipientData["EMAIL"]; if (empty($recipientData["NAME"])) { $recipientEmailParts = explode('@', $recipientEmail); $recipientName = $recipientEmailParts[0]; } else { $recipientName = $recipientData["NAME"]; } // prepare params for send $sendParams = array('FIELDS' => array('EMAIL_TO' => $recipientEmail, 'NAME' => $recipientName, 'USER_ID' => $recipientData["USER_ID"], 'SENDER_CHAIN_CODE' => 'sender_chain_item_' . $postingData["MAILING_CHAIN_ID"], 'UNSUBSCRIBE_LINK' => Subscription::getLinkUnsub(array('MAILING_ID' => $postingData['MAILING_ID'], 'EMAIL' => $recipientEmail, 'RECIPIENT_ID' => $recipientData["ID"]))), 'TRACK_READ' => array('MODULE_ID' => "sender", 'FIELDS' => array('RECIPIENT_ID' => $recipientData["ID"])), 'TRACK_CLICK' => array('MODULE_ID' => "sender", 'FIELDS' => array('RECIPIENT_ID' => $recipientData["ID"]), 'URL_PARAMS' => array('bx_sender_conversion_id' => $recipientData["ID"]))); if (is_array($recipientData['FIELDS']) && count($recipientData) > 0) { $sendParams['FIELDS'] = $sendParams['FIELDS'] + $recipientData['FIELDS']; } // set sending result to recipient $mailSendResult = static::sendInternal($postingData['MAILING_CHAIN_ID'], $sendParams); PostingRecipientTable::update(array('ID' => $recipientData["ID"]), array('STATUS' => $mailSendResult, 'DATE_SENT' => new Type\DateTime())); // send event $eventData = array('SEND_RESULT' => $mailSendResult == PostingRecipientTable::SEND_RESULT_SUCCESS, 'RECIPIENT' => $recipientData, 'POSTING' => $postingData); $event = new Event('sender', 'OnAfterPostingSendRecipient', array($eventData)); $event->send(); // limit executing script by time if ($timeout > 0 && getmicrotime() - $start_time >= $timeout) { break; } // increment sending statistic static::$emailSentPerIteration++; } //set status and delivered and error emails $statusList = PostingTable::getRecipientCountByStatus($id); if (!array_key_exists(PostingRecipientTable::SEND_RESULT_NONE, $statusList)) { if (array_key_exists(PostingRecipientTable::SEND_RESULT_ERROR, $statusList)) { $STATUS = PostingTable::STATUS_SENT_WITH_ERRORS; } else { $STATUS = PostingTable::STATUS_SENT; } $DATE = new Type\DateTime(); } else { $STATUS = PostingTable::STATUS_PART; $DATE = null; } // unlock posting for exclude double parallel sending static::unlockPosting($id); // update status of posting PostingTable::update(array('ID' => $id), array('STATUS' => $STATUS, 'DATE_SENT' => $DATE)); // return status to continue or end of sending if ($STATUS == PostingTable::STATUS_PART) { return static::SEND_RESULT_CONTINUE; } else { return static::SEND_RESULT_SENT; } }