/** * @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; } }
$arPosting = $postingDb->fetch(); if ($arPosting) { $ID = intval($arPosting['MAILING_CHAIN_ID']); } } $statClickList = array(); $statResult = array('all' => 0, 'all_print' => 0, 'delivered' => 0, 'error' => 0, 'not_send' => 0, 'read' => 0, 'click' => 0, 'unsub' => 0); if ($ID > 0) { $postingDb = \Bitrix\Sender\PostingTable::getList(array('select' => array('ID', 'DATE_CREATE', 'DATE_SENT', 'STATUS', 'MAILING_CHAIN_REITERATE' => 'MAILING_CHAIN.REITERATE', 'SUBJECT' => 'MAILING_CHAIN.SUBJECT', 'COUNT_SEND_ALL', 'COUNT_SEND_NONE', 'COUNT_SEND_ERROR', 'COUNT_SEND_SUCCESS', 'COUNT_SEND_DENY', 'COUNT_READ', 'COUNT_CLICK', 'COUNT_UNSUB'), 'filter' => array('MAILING_CHAIN_ID' => $ID, '!DATE_SENT' => null), 'order' => array('DATE_SENT' => 'DESC', 'DATE_CREATE' => 'DESC'), 'limit' => 1)); $arPosting = $postingDb->fetch(); // get reiterate postings statistic $arPostingReiterateList = array(); if (!empty($arPosting) && $arPosting['MAILING_CHAIN_REITERATE'] == 'Y') { $defaultDate = new \Bitrix\Main\Type\DateTime(); $postingReiterateList = array(); $postingReiterateDb = \Bitrix\Sender\PostingTable::getList(array('select' => array('ID', 'DATE_SENT', 'COUNT_SEND_ALL', 'COUNT_READ', 'COUNT_CLICK', 'COUNT_UNSUB'), 'filter' => array('MAILING_CHAIN_ID' => $ID, '!STATUS' => \Bitrix\Sender\PostingTable::STATUS_NEW), 'order' => array('DATE_SENT' => 'DESC', 'ID' => 'DESC'), 'limit' => 50)); while ($postingReiterate = $postingReiterateDb->fetch()) { $postingReiterate['CNT'] = $postingReiterate['COUNT_SEND_ALL']; $postingReiterateList[$postingReiterate['ID']] = $postingReiterate; } foreach ($postingReiterateList as $arPostingReiterate) { if (empty($arPostingReiterate['DATE_SENT'])) { $arPostingReiterate['DATE_SENT'] = $defaultDate; } $cntDivider = $arPostingReiterate['CNT'] > 0 ? $arPostingReiterate['CNT'] : 1; $cntDivider = $cntDivider / 100; $defaultDateTimeStamp = $arPostingReiterate['DATE_SENT']->getTimestamp(); $arPostingReiterateList[$defaultDateTimeStamp] = array('date' => $arPostingReiterate['DATE_SENT']->format("d/m"), 'sent' => $arPostingReiterate['CNT'], 'read' => $arPostingReiterate['COUNT_READ'], 'click' => $arPostingReiterate['COUNT_CLICK'], 'unsub' => $arPostingReiterate['COUNT_UNSUB'], 'sent_prsnt' => '100', 'read_prsnt' => round($arPostingReiterate['COUNT_READ'] / $cntDivider, 2), 'click_prsnt' => round($arPostingReiterate['COUNT_CLICK'] / $cntDivider, 2), 'unsub_prsnt' => round($arPostingReiterate['COUNT_UNSUB'] / $cntDivider, 2)); } if (!empty($arPostingReiterateList)) { if (count($arPostingReiterateList) < 2) {
/** * @return string * @throws \Bitrix\Main\ArgumentException */ public static function checkPeriod($isAgentExec = true) { $isAgentExecInSetting = \COption::GetOptionString("sender", "reiterate_method") !== 'cron'; if ($isAgentExec && !$isAgentExecInSetting || !$isAgentExec && $isAgentExecInSetting) { return ""; } $dateTodayPhp = new \DateTime(); $datetimeToday = Type\DateTime::createFromPhp(clone $dateTodayPhp); $dateToday = clone $dateTodayPhp; $dateToday = Type\Date::createFromPhp($dateToday->setTime(0, 0, 0)); $dateTomorrow = clone $dateTodayPhp; $dateTomorrow = Type\Date::createFromPhp($dateTomorrow->setTime(0, 0, 0))->add('1 DAY'); $arDateFilter = array($dateToday, $dateTomorrow); $chainDb = MailingChainTable::getList(array('select' => array('ID', 'LAST_EXECUTED', 'POSTING_ID', 'DAYS_OF_MONTH', 'DAYS_OF_WEEK', 'TIMES_OF_DAY'), 'filter' => array('=REITERATE' => 'Y', '=MAILING.ACTIVE' => 'Y', 'STATUS' => MailingChainTable::STATUS_WAIT))); while ($arMailingChain = $chainDb->fetch()) { $lastExecuted = $arMailingChain['LAST_EXECUTED']; /* @var \Bitrix\Main\Type\DateTime $lastExecuted*/ if ($lastExecuted && $lastExecuted->getTimestamp() >= $dateToday->getTimestamp()) { continue; } $timeOfExecute = static::getDateExecute($dateTodayPhp, $arMailingChain["DAYS_OF_MONTH"], $arMailingChain["DAYS_OF_WEEK"], $arMailingChain["TIMES_OF_DAY"]); if ($timeOfExecute) { $arUpdateMailChain = array('LAST_EXECUTED' => $datetimeToday); $postingDb = PostingTable::getList(array('select' => array('ID'), 'filter' => array('=MAILING_CHAIN_ID' => $arMailingChain['ID'], '><DATE_CREATE' => $arDateFilter))); $arPosting = $postingDb->fetch(); if (!$arPosting) { $postingId = MailingChainTable::initPosting($arMailingChain['ID']); } else { $postingId = $arPosting['ID']; $arUpdateMailChain['POSTING_ID'] = $postingId; PostingTable::initGroupRecipients($postingId); } if ($postingId) { $arUpdateMailChain['STATUS'] = MailingChainTable::STATUS_SEND; $arUpdateMailChain['AUTO_SEND_TIME'] = Type\DateTime::createFromPhp($timeOfExecute); } MailingChainTable::update(array('ID' => $arMailingChain['ID']), $arUpdateMailChain); } } return static::getAgentNamePeriod(); }
$bVarsFromForm = true; } } //Edit/Add part ClearVars(); $str_SORT = 100; $str_ACTIVE = "Y"; $str_VISIBLE = "Y"; $arMailngChainAttachment = array(); if ($ID > 0) { $rubric = new CDBResult(\Bitrix\Sender\MailingChainTable::getList(array('select' => array('*'), 'filter' => array('ID' => $ID)))); if (!$rubric->ExtractFields("str_")) { $ID = 0; } if ($ID > 0) { $postingDb = \Bitrix\Sender\PostingTable::getList(array('select' => array('*'), 'filter' => array('ID' => $ID, '!DATE_SENT' => null), 'order' => array('DATE_SENT' => 'DESC'), 'limit' => 1)); $arPosting = $postingDb->fetch(); $str_DATE_SENT = $arPosting['DATE_SENT']; $attachmentFileDb = \Bitrix\Sender\MailingAttachmentTable::getList(array('select' => array('FILE_ID'), 'filter' => array('CHAIN_ID' => $ID))); while ($ar = $attachmentFileDb->fetch()) { if ($arFileFetch = CFile::GetFileArray($ar['FILE_ID'])) { $arMailngChainAttachment[] = $arFileFetch; } } } } if ($bVarsFromForm) { $DB->InitTableVarsForEdit("b_sender_mailing_chain", "", "str_"); } \CJSCore::Init(array("sender_admin")); $APPLICATION->SetTitle($ID > 0 ? GetMessage("sender_chain_edit_title_edit") . $ID : GetMessage("sender_chain_edit_title_add"));
$APPLICATION->AuthForm(GetMessage("ACCESS_DENIED")); } $sTableID = "tbl_sender_posting_recipient"; $oSort = new CAdminSorting($sTableID, "ID", "desc"); $lAdmin = new CAdminList($sTableID, $oSort); $MAILING_ID = intval($_REQUEST['MAILING_ID']); $ID = intval($_REQUEST['ID']); if ($find_mailing_chain_id > 0) { $ID = $find_mailing_chain_id; } if ($find_click_show_url != 'Y') { $find_click_show_url = 'N'; } $showClickUrl = $find_click_show_url; if ($ID <= 0) { $postingDb = \Bitrix\Sender\PostingTable::getList(array('select' => array('MAILING_CHAIN_ID'), 'filter' => array('MAILING_ID' => $MAILING_ID), 'order' => array('DATE_SENT' => 'DESC', 'DATE_CREATE' => 'DESC'))); $arPosting = $postingDb->fetch(); if ($arPosting) { $ID = intval($arPosting['MAILING_CHAIN_ID']); } } function CheckFilter() { global $FilterArr, $lAdmin; foreach ($FilterArr as $f) { global ${$f}; } return count($lAdmin->arFilterErrors) == 0; } $FilterArr = array("find_email", "find_name", "find_mailing", "find_mailing_chain_id", "find_sent", "find_read", "find_click", "find_unsub"); $lAdmin->InitFilter($FilterArr);
$arPosting = $postingDb->fetch(); $arPostingReiterateList = array(); if (!empty($arPosting) && $arPosting['MAILING_CHAIN_REITERATE'] == 'Y') { $defaultDate = new \Bitrix\Main\Type\DateTime(); $postingReiterateDb = \Bitrix\Sender\PostingTable::getList(array( 'select' => array( 'ID', 'DATE_SENT', 'CNT', 'READ_CNT', 'CLICK_CNT', 'UNSUB_CNT' ), 'filter' => array( 'MAILING_CHAIN_ID' => $ID, '!STATUS' => \Bitrix\Sender\PostingTable::STATUS_NEW, 'POSTING_RECIPIENT.STATUS' => \Bitrix\Sender\PostingRecipientTable::SEND_RESULT_SUCCESS ), 'runtime' => array( new \Bitrix\Main\Entity\ExpressionField('CNT', 'COUNT(DISTINCT %s)', 'POSTING_RECIPIENT.ID'), new \Bitrix\Main\Entity\ExpressionField('READ_CNT', 'COUNT(DISTINCT %s)', 'POSTING_RECIPIENT.POSTING_READ.RECIPIENT_ID'), new \Bitrix\Main\Entity\ExpressionField('CLICK_CNT', 'COUNT(DISTINCT %s)', 'POSTING_RECIPIENT.POSTING_CLICK.RECIPIENT_ID'), new \Bitrix\Main\Entity\ExpressionField('UNSUB_CNT', 'COUNT(DISTINCT %s)', 'POSTING_RECIPIENT.POSTING_UNSUB.RECIPIENT_ID') ), 'order' => array('DATE_SENT' => 'DESC', 'ID' => 'DESC'), 'limit' => 50, )); while($arPostingReiterate = $postingReiterateDb->fetch()) { //echo $arPostingReiterate['POSTING_DATE_SENT'].'<br>'; if(empty($arPostingReiterate['DATE_SENT'])) $arPostingReiterate['DATE_SENT'] = $defaultDate;
} } $mailing = null; if ($MAILING_ID > 0) { $mailingDb = \Bitrix\Sender\MailingTable::getList(array('filter' => array('ID' => $MAILING_ID, 'IS_TRIGGER' => 'Y'))); if (!($mailing = $mailingDb->fetch())) { $MAILING_ID = 0; } } $statList = array(); if ($MAILING_ID > 0) { $i = 1; $chainList = \Bitrix\Sender\MailingTable::getChain($MAILING_ID); foreach ($chainList as $chain) { $stat = array('NAME' => GetMessage("sender_stat_trig_letter") . $i++, 'SUBJECT' => $chain['SUBJECT'], 'CNT' => array('SENT_SUCCESS' => 0, 'SENT_ERROR' => 0, 'READ' => 0, 'CLICK' => 0, 'UNSUB' => 0, 'GOAL' => 0, 'START' => 0)); $statRawDb = \Bitrix\Sender\PostingTable::getList(array('select' => array('CNT', 'READ_CNT', 'CLICK_CNT', 'UNSUB_CNT'), 'filter' => array('=MAILING_CHAIN_ID' => $chain['ID']), 'runtime' => array(new \Bitrix\Main\Entity\ExpressionField('CNT', 'SUM(%s)', 'COUNT_SEND_SUCCESS'), new \Bitrix\Main\Entity\ExpressionField('READ_CNT', 'SUM(%s)', 'COUNT_READ'), new \Bitrix\Main\Entity\ExpressionField('CLICK_CNT', 'SUM(%s)', 'COUNT_CLICK'), new \Bitrix\Main\Entity\ExpressionField('UNSUB_CNT', 'SUM(%s)', 'COUNT_UNSUB')))); while ($statRaw = $statRawDb->fetch()) { $stat['CNT']['SENT_SUCCESS'] += $statRaw['CNT']; $stat['CNT']['READ'] += $statRaw['READ_CNT']; $stat['CNT']['CLICK'] += $statRaw['CLICK_CNT']; $stat['CNT']['UNSUB'] += $statRaw['UNSUB_CNT']; $stat['CNT']['START'] += $statRaw['CNT']; } $statRawDb = \Bitrix\Sender\PostingRecipientTable::getList(array('select' => array('ID'), 'filter' => array('=POSTING.MAILING_CHAIN_ID' => $chain['ID'], '=STATUS' => array(\Bitrix\Sender\PostingRecipientTable::SEND_RESULT_SUCCESS, \Bitrix\Sender\PostingRecipientTable::SEND_RESULT_DENY), '!DATE_DENY' => null))); $stat['CNT']['GOAL'] = $statRawDb->getSelectedRowsCount(); $statList['CHAIN'][] = $stat; } } if (!empty($statList)) { foreach ($statList['CHAIN'] as $chain) { foreach ($chain['CNT'] as $k => $v) {