* @since Version 1.1 * * * EXAMPLE: * $mm = new cMail(); * $mm->addMail('burkkanc@gmail.com', cMail::MAIL_8_AUCTION_PICKUP_REMINDER, $this->langId, array('Prod-name' => 'XXXLS-10992'), true, 3); * */ class cMail { private cMailModule $module; CONST PWD = 'pwd'; CONST PORT = 'port'; CONST LOGIN = 'login'; CONST SERVER = 'server'; CONST SENDER = 'SENDER'; CONST ENCRYPTION = 'encryption'; CONST REWRITE_SENDER_NAME_TO = 'RW_NAME'; CONST SEND_READ_REC_TO = 'readReceiptTo'; CONST MAIL_SERVER_DEFAULT = '1'; const CC_SHOP_OWNER = 'cc_shop_owner'; // TODO: šo jāuzseto pareizu /* MAIL SERVER CONSTANTS */ static array $SERVER_CFG = [ self::MAIL_SERVER_DEFAULT => [ self::LOGIN => 'info@elixirvault.lv', self::PWD => 'dkq2fecDqy8J43m!@', self::PORT => 465, self::ENCRYPTION => 'ssl', self::SERVER => 'smtppro.zoho.eu', self::SENDER => 'info@elixirvault.lv', self::SEND_READ_REC_TO => 'info@elixirvault.lv', self::REWRITE_SENDER_NAME_TO => 'ELIXIR VAULT', ], ]; const MAIL_REQUEST_KEY = 'ELIXIRVAULT-A94A8FE5CCB19BA61C4C0873D391E987982FBBD3'; CONST MAIL_REQUEST_PROCESS_ID = 'elixirvault_mailer'; CONST MAIL_TRACKING_STR = '[%TRACKING_IMG%]'; CONST EHLO_SERVER = 'www.elixirvault.lv'; // Send hello message to check server availability // Main mail templates const MAIL_1_ACCOUNT_ACTIVATION = 'Mail 1'; // User account activation (User registration complete email) const MAIL_2_PASSWORD_RECOVERY = 'Mail 2'; // Password recovery email const MAIL_3_SUBSCRIPTION_MAIL = 'Mail 3'; // Newsletter mail const MAIL_4_SYSTEM_NOTICES_MAIL = 'Mail 4'; // System notices mail const MAIL_5_ORDER_CONFIRMATION = 'Mail 5'; // Order confirmation mail const MAIL_6_ORDER_RECEIPT = 'Mail 6'; // Order receipt mail const MAIL_16_SYSTEM_NEW_MAILS = 'Mail 16'; // System news public function __construct() { include_once 'cMail.classModule.php'; $this->module = new cMailModule(); } /** * Function to insert new mail into ned table * * @category LIB mail * @author Mareks Keišs * @param string $to - mail owner * @param string|bool $toCC - mail cc owner * @param string $sMailSrvType - mail server to use * @param string $template - mail template constant * @param int $lang - mail language * @param array $rdata - mail replace template data varibles k => v * @param string $attachment - attachment file * @param bool $send - send mail now * @param int $priority - mail priority enum 1-3 * @param string|bool $marker - mail tracking marker to check specific data * @return bool|int - */ public function addMail($to, $toCC = false, $sMailSrvType = self::MAIL_SERVER_DEFAULT, $template, $lang, $rdata = array(), $attachment = '', $send = false, $priority = 1, $marker = false){ // Check mail server if(!isset(self::$SERVER_CFG[$sMailSrvType])) cJSON::sendError(array('msg' => "Passed mail server does'nt exist!")); // Get mail template if(strlen($to) && $mailData = $this->module->getTemplateByType($template, $lang)){ $replace = array(); $replaceData = array(); if(count($rdata)){ foreach ($rdata as $k=>$v) { if($v && is_array($v)){ $this->composeArrayDataReplace($k, $v, $mailData['mail_data']); }else{ $replaceData[] = $v; $replace[] = $k; } } } // Replace constants $mailData['mail_data'] = str_replace($replace, $replaceData, $mailData['mail_data']); if($mailData['mail_data']){ // Add outgoing mail $mail = array( 'mail_server_type' => $sMailSrvType, 'mail_lang_id' => $lang, 'mail_template_id' => $mailData['template_id'], 'mail_owner' => $to, 'mail_owner_cc' => $toCC, 'mail_sender' => self::$SERVER_CFG[$sMailSrvType][self::SENDER], 'mail_title' => $mailData['mail_title'], 'mail_content' => $mailData['mail_data'], 'mail_attachment' => $attachment, 'mail_inserted' => time(), 'mail_modified' => time(), 'mail_priority' => $priority, 'mail_send_atempt' => 0, 'mail_marker' => $marker, ); // Check send mail flag if(defined('SEND_MAILS') && !SEND_MAILS) $send = false; // Add mail to outgoing list $mId = $this->module->insOutgoingMail($mail); // Send mail immediately if ($send && $mId) { $SSL = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443 ? 's' : ''); exec("screen -A -m -d -S " . self::MAIL_REQUEST_PROCESS_ID . " curl 'http{$SSL}://{$_SERVER['HTTP_HOST']}/cron/ctp:" . self::MAIL_REQUEST_KEY . "/ct:send/id:{$mId}'"); } return $mId; } } return false; } /** * Function to insert new mail into ned table * * @category LIB mail * @author Mareks Keišs * @param string $to - mail owner * @param string|bool $toCC - mail cc owner * @param string $sMailSrvType - mail server to use * @param array $mailData - mail data * @param int $lang - mail language * @param array $rdata - mail replace template data varibles k => v * @param string $attachment - attachment file * @param bool $send - send mail now * @param int $priority - mail priority enum 1-3 * @param string|bool $marker - mail tracking marker to check specific data * @return bool true/false */ public function addMailT($to, $toCC = false, $sMailSrvType = self::MAIL_SERVER_DEFAULT, $mailData = array(), $lang, $rdata = array(), $attachment = '', $send = false, $priority = 1, $marker = false){ // Check mail server if(!isset(self::$SERVER_CFG[$sMailSrvType])) cJSON::sendError(array('msg' => "Passed mail server does'nt exist!")); // Get mail template if(strlen($to) && !empty($mailData)){ $replace = array(); $replaceData = array(); if(count($rdata)){ foreach ($rdata as $k=>$v) { if($v && is_array($v)){ $this->composeArrayDataReplace($k, $v, $mailData['mail_data']); }else{ $replaceData[] = $v; $replace[] = $k; } } } // Replace constants $mailData['mail_data'] = str_replace($replace, $replaceData, $mailData['mail_data']); if($mailData['mail_data']){ // Add outgoing mail $mail = array( 'mail_server_type' => $sMailSrvType, 'mail_lang_id' => $lang, 'mail_template_id' => $mailData['template_id'], 'mail_owner' => $to, 'mail_owner_cc' => $toCC, 'mail_sender' => self::$SERVER_CFG[$sMailSrvType][self::SENDER], 'mail_title' => $mailData['mail_title'], 'mail_content' => $mailData['mail_data'], 'mail_attachment' => $attachment, 'mail_inserted' => time(), 'mail_modified' => time(), 'mail_priority' => $priority, 'mail_send_atempt' => 0, 'mail_marker' => $marker, ); // Check send mail flag if(defined('SEND_MAILS') && !SEND_MAILS) $send = false; // Add mail to outgoing list $mId = $this->module->insOutgoingMail($mail); // Send mail immediately if ($send && $mId) { $SSL = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443 ? 's' : ''); exec("screen -A -m -d -S " . self::MAIL_REQUEST_PROCESS_ID . " curl 'http{$SSL}://{$_SERVER['HTTP_HOST']}/cron/ctp:" . self::MAIL_REQUEST_KEY . "/ct:send/id:{$mId}'"); } return true; } } return false; } /** * Function to send mail * * @category LIB mail * @author Mareks Keišs * @param array|null $mailData - mail configuration data * @returns mixed */ public function sendMail(array $mailData = null) { if(is_null($mailData)) return false; if (!isset(self::$SERVER_CFG[$mailData['mail_server_type']])) { cJSON::sendError(array('msg' => "Passed mail server does'nt exist!")); } // Check send mail flag if(defined('SEND_MAILS') && !SEND_MAILS || !defined('SEND_MAILS')) cJSON::sendError('Outgoing E-Mails are DISABLED!!!'); $mailCfg = self::$SERVER_CFG[$mailData['mail_server_type']]; // Create SwiftMail instance $oMailer = new Swift_Mailer($this->getSwiftMailerTransport($mailCfg)); // Analyse & prepare data $senderTitle = (strlen($mailCfg[self::REWRITE_SENDER_NAME_TO]) ? $mailCfg[self::REWRITE_SENDER_NAME_TO] : $this->getDomainName($mailData['mail_sender'])); $mailData['mail_owner_title'] = (!isset($mailData['mail_owner_title']) ? $mailData['mail_owner_title'] = $mailData['mail_owner'] : $mailData['mail_owner_title']); $mailData['mail_owner_cc_title'] = (!isset($mailData['mail_owner_cc_title']) ? $mailData['mail_owner_cc_title'] = $mailData['mail_owner_cc'] : $mailData['mail_owner_cc_title']); // Strip left constants $this->stripLeftDataVariableInMailContent($mailData['mail_content']); // Create a message $oMessage = (new Swift_Message($mailData['mail_title'])) ->setReplyTo([$mailData['mail_sender'] => $senderTitle]) ->setFrom([$mailData['mail_sender'] => $senderTitle]) ->setTo([$mailData['mail_owner'] => $mailData['mail_owner_title']]) ->setBody($mailData['mail_content'], 'text/html'); // Check for plain message if(isset($mailData['plain_text']) && $mailData['plain_text']) $oMessage->addPart('My amazing body in plain text', 'text/plain'); // Add cc if specified if(!empty($mailData['mail_owner_cc'])) $oMessage->setCc([$mailData['mail_owner_cc'] => $mailData['mail_owner_cc_title']]); // Ask for a delivery receipt from the recipient to be sent to if(isset($mailCfg[self::SEND_READ_REC_TO])) $oMessage->setReadReceiptTo($mailCfg[self::SEND_READ_REC_TO]); // Create the attachment if(!empty($mailData['mail_attachment'])) $oMessage->attach(Swift_Attachment::fromPath($mailData['mail_attachment'])); // Send the message return $oMailer->send($oMessage); } /** * Function to get Swift Mail transport * * @category LIB mail * @author Mareks Keišs * @param array $mailCfg - mail configuration data * @returns Swift_Transport */ private function getSwiftMailerTransport(array $mailCfg): Swift_Transport { if (!defined('SEND_MAIL_SERVER')) define('SEND_MAIL_SERVER', 'MAILHOG'); switch (SEND_MAIL_SERVER) { case 'SMTP': $oTransport = new Swift_SmtpTransport( $mailCfg[self::SERVER], $mailCfg[self::PORT], $mailCfg[self::ENCRYPTION] ); $oTransport->setUsername($mailCfg[self::LOGIN])->setPassword($mailCfg[self::PWD]); break; case 'MAILHOG': default: $sendMailCommand = (defined('SEND_MAIL_COMMAND_PATH') ? SEND_MAIL_COMMAND_PATH : ini_get('sendmail_path')); $oTransport = new Swift_SendmailTransport($sendMailCommand); break; } return $oTransport; } /** * Function to get mail firs name * * @category LIB mail * @author Mareks Keišs * @param string $email - provided email * @return bool or email name */ public static function getMailName($email){ if($email){ $ch = explode('@', $email); if(count($ch)>1){ return $ch[0]; } } return false; } /** * Function to get mail domain name * * @category LIB mail * @author Mareks Keišs * @param string $email - provided email * @return bool or email name */ public static function getDomainName($email){ if($email){ $ch = explode('@', $email); if(count($ch)>1){ return $ch[1]; } } return false; } /** * Function to check if mail with pattern has been sent or prepared * * @category LIB mail * @author Mareks Keišs * @param string $email - provided email * @param string $pattern - pattern key to check * @param mixed $timeFrame - time frame to search mail for * @return bool or email name */ public function isMailSent($email, $pattern, $timeFrame = false){ // Setup base timeframe if(!$timeFrame || !is_array($timeFrame)){ $timeFrame = ($timeFrame > 0 ? $timeFrame : 24*60*60); $timeFrame = array( 'from' => time() - $timeFrame, 'till' => time() ); } if($id = $this->module->isMailSent($email, $pattern, $timeFrame)){ return true; } return false; } /** * Function to strip unused constants in mail * * @category APP pubPPR * @author Mareks Keišs * @param string $sMailData - mail data to check * @returns void */ public static function stripLeftDataVariableInMailContent(&$sMailData) { $sMailData = preg_replace('/(\[%[\w\d\n\t_ \|\-]*%\])/i', ' ', $sMailData); } /** * Function to replace data array - like table based on key & class to search and dublicate * * @category APP pubPPR * @author Mareks Keišs * @param string $tag - tag in htm to search * @param array $cfg - config array with data to compose * @param string $mailData - mail data in which to search * @returns bool true */ public function composeArrayDataReplace($tag, $cfg, &$mailData) { if($tag && @$cfg['class'] && count($cfg['data'])){ // Search for replica row in mail data $tlen = strlen(""); $start = strpos($mailData, '<' . $tag . ' class="' . $cfg['class']); $end = strpos($mailData, "", $start); // Extract string to multiple & replace with key $sStr = substr($mailData, $start, $end-$start+$tlen); $mailData = str_replace($sStr, '{ROW_DATA}', $mailData); // Setup replacement keys $tableData = ""; foreach ($cfg['data'] as $item) { $replace = array(); $replaceData = array(); if($item && is_array($item)){ foreach ($item as $k=>$v) { $replaceData[] = $v; $replace[] = $k; } $tableData .= $t = str_replace($replace, $replaceData, $sStr); } } // Replace constants $mailData = str_replace('{ROW_DATA}', $tableData, $mailData); } } }