Index: trunk/core/units/email_events/email_events_event_handler.php =================================================================== diff -u -N -r7702 -r7855 --- trunk/core/units/email_events/email_events_event_handler.php (.../email_events_event_handler.php) (revision 7702) +++ trunk/core/units/email_events/email_events_event_handler.php (.../email_events_event_handler.php) (revision 7855) @@ -1,5 +1,12 @@ getEventParam('EmailEventName'); - if( strpos($email_event, '_') !== false ) - { - trigger_error('Invalid email event name '.$email_event.'. Use only UPPERCASE characters and dots as email event names', E_USER_ERROR); + function GetMessageRecipients(&$event, &$event_id) + { + $email_event =& $event->getObject( Array('skip_autoload' => true) ); + /* @var $email_event kDBItem */ + + // get event parameters by name & type + $load_keys = Array ( + 'Event' => $event->getEventParam('EmailEventName'), + 'Type' => $event->getEventParam('EmailEventType'), + ); + $email_event->Load($load_keys); + + if (!$email_event->isLoaded()) { + // event record not found + return false; } + + $enabled = $email_event->GetDBField('Enabled'); + if ($enabled == EVENT_STATUS_DISABLED) { + return false; + } + if ($enabled == EVENT_STATUS_FRONTEND && $this->Application->IsAdmin()) { + return false; + } + // initial values $to_user_id = $event->getEventParam('EmailEventToUserId'); - $email_event_type = $event->getEventParam('EmailEventType'); - - $message_object = &$this->Application->recallObject('emailmessages', null, Array('skip_autoload' => true)); - $event_table = $this->Application->getUnitOption('emailevents', 'TableName'); - - $event_object =& $event->getObject( Array('skip_autoload' => true) ); - $event_object->Load(array('Event'=>$email_event, 'Type'=>$email_event_type)); - - $event_id = $event_object->GetDBField('EventId'); - $from_user_id = $event_object->GetDBField('FromUserId'); - $type = $event_object->GetDBField('Type'); - $enabled = $event_object->GetDBField('Enabled'); - - $direct_send_params = $event->getEventParam('DirectSendParams'); - - if ($enabled == 0) return; // disabled event - if ($enabled == 2 && $this->Application->IsAdmin() ) return; // event only for front-end - - if ($type == 1){ + $from_user_id = $email_event->GetDBField('FromUserId'); + + if ($email_event->GetDBField('Type') == EVENT_TYPE_ADMIN) { // For type "Admin" recipient is a user from field FromUserId which means From/To user in Email events list $to_user_id = $from_user_id; $from_user_id = -1; } - /* - if (!($to_user_id > 0) && !$direct_send_params){ - // if we can not determine recepient we will not send email - return; + + $event_id = $email_event->GetDBField('EventId'); + + return Array ($from_user_id, $to_user_id); + } + + /** + * Returns user name, email by id, or ones, that specified in $direct_params + * + * @param int $user_id + * @param string $user_type type of user = {to,from} + * @param Array $direct_params + * @return Array + */ + function GetRecipientInfo($user_id, $user_type, $direct_params = null) + { + // load user, because it can be addressed from email template tags + $user =& $this->Application->recallObject('u.email-'.$user_type, null, Array('skip_autoload' => true)); + /* @var $user UsersItem */ + + $email = $name = ''; + $result = $user_id > 0 ? $user->Load($user_id) : $user->Clear(); + if ($user->IsLoaded()) { + $email = $user->GetDBField('Email'); + $name = trim($user->GetDBField('FirstName').' '.$user->GetDBField('LastName')); } - */ - //Parse Message Template - $message_object->Load(array('EventId' => $event_id, 'LanguageId' => $this->Application->GetVar('m_lang'))); - $message_type = $message_object->GetDBField('MessageType'); - - $email_object = &$this->Application->recallObject('kEmailMessage'); - $email_object->Clear(); - - // add footer: begin + + if (is_array($direct_params)) { + if (isset($direct_params[$user_type.'_email'])) { + $email = $direct_params[$user_type.'_email']; + } + + if (isset($direct_params[$user_type.'_name'])) { + $name = $direct_params[$user_type.'_name']; + } + } + + if (!$email) { + // if email is empty, then use admins email + $email = $this->Application->ConfigValue('Smtp_AdminMailFrom'); + } + + if (!$name) { + $name = $user_type == 'from' ? strip_tags($this->Application->ConfigValue('Site_Name')) : $email; + } + + return Array ($email, $name); + } + + /** + * Returns email event message by ID (headers & body in one piece) + * + * @param int $event_id + * @param string $message_type contains message type = {text,html} + */ + function GetMessageBody($event_id, &$message_type) + { + $current_language = $this->Application->GetVar('m_lang'); + $message =& $this->Application->recallObject('emailmessages', null, Array('skip_autoload' => true)); + /* @var $message kDBItem */ + + $message->Load( Array('EventId' => $event_id, 'LanguageId' => $current_language) ); + if (!$message->isLoaded()) { + // event translation on required language not found + return false; + } + + $message_type = $message->GetDBField('MessageType'); + + // 1. get message body + $message_body = $message->GetDBField('Template'); + + // 2. add footer $sql = 'SELECT em.Template - FROM '.$message_object->TableName.' em + FROM '.$message->TableName.' em LEFT JOIN '.TABLE_PREFIX.'Events e ON e.EventId = em.EventId - WHERE em.LanguageId = '.$message_object->GetDBField('LanguageId').' AND e.Event = "COMMON.FOOTER"'; - $footer = explode("\n\n", $this->Conn->GetOne($sql)); - $footer = $message_object->GetDBField('MessageType') == 'text' ? $email_object->convertHTMLtoPlain($footer[1]) : $footer[1]; - $message_template = $message_object->GetDBField('Template')."\r\n".$footer; - // add footer: end - - $from_user_object = &$this->Application->recallObject('u.email-from', null, Array('skip_autoload' => true)); - $from_user_object->Load($from_user_id); - // here if we don't have from_user loaded, it takes a default user from config values - if ( $from_user_object->IsLoaded() ) { - $from_user_email = $from_user_object->GetDBField('Email'); - $from_user_name = trim($from_user_object->GetDBField('FirstName').' '.$from_user_object->GetDBField('LastName')); + WHERE em.LanguageId = '.$current_language.' AND e.Event = "COMMON.FOOTER"'; + + list (, $footer) = explode("\n\n", $this->Conn->GetOne($sql)); + if ($message_type == 'text') { + $esender =& $this->Application->recallObject('EmailSender'); + /* @var $esender kEmailSendingHelper */ + + $footer = $esender->ConvertToText($footer); } - else { - $from_user_email = $this->Application->ConfigValue('Smtp_AdminMailFrom'); + + if ($footer) { + $message_body .= "\r\n".$footer; } + + // 3. replace tags if needed + $default_replacement_tags = Array ( + ' ' ' 'GetDBField('ReplacementTags'); + $replacement_tags = $replacement_tags ? unserialize($replacement_tags) : Array (); + $replacement_tags = array_merge_recursive2($default_replacement_tags, $replacement_tags); - $to_user_object = &$this->Application->recallObject('u.email-to', null, Array('skip_autoload' => true)); - $to_user_object->Load($to_user_id); - $to_user_email = $to_user_object->GetDBField('Email'); - $to_user_name = trim($to_user_object->GetDBField('FirstName').' '.$to_user_object->GetDBField('LastName')); - - if($direct_send_params){ - $to_user_email = ( $direct_send_params['to_email'] ? $direct_send_params['to_email'] : $to_user_email ); - $to_user_name = ( $direct_send_params['to_name'] ? $direct_send_params['to_name'] : $to_user_name ); - $from_user_email = ( $direct_send_params['from_email'] ? $direct_send_params['from_email'] : $from_user_email); - $from_user_name = ( $direct_send_params['from_name'] ? $direct_send_params['from_name'] : $from_user_name ); - $message_body_additional = $direct_send_params['message']; + foreach ($replacement_tags as $replace_from => $replace_to) { + $message_body = str_replace($replace_from, $replace_to, $message_body); } - - $to_user_email = $to_user_email ? $to_user_email : $this->Application->ConfigValue('Smtp_AdminMailFrom'); - - $this->Application->makeClass('Template'); + + return $message_body; + } + + /** + * Parse message template and return headers (as array) and message body part + * + * @param string $message + * @param Array $direct_params + * @return Array + */ + function ParseMessageBody($message, $direct_params = null) + { + $direct_params['message_text'] = isset($direct_params['message']) ? $direct_params['message'] : ''; // parameter alias + + // 1. parse template $this->Application->InitParser(); - $parser_params = $this->Application->Parser->Params; - $direct_send_params['message_text'] = $message_body_additional; - $this->Application->Parser->Params = array_merge_recursive2($this->Application->Parser->Params, $direct_send_params); - $message_template = str_replace('Application->Parser->Parse($message_template, 'email_template', 0); - $this->Application->Parser->Params = $parser_params; + $parser_params = $this->Application->Parser->Params; // backup parser params + $this->Application->Parser->Params = array_merge_recursive2($this->Application->Parser->Params, $direct_params); + $message = $this->Application->Parser->Parse($message, 'email_template', 0); + $this->Application->Parser->Params = $parser_params; // restore parser params - $message_template = str_replace("\r", "", $message_template); + // 2. replace line endings, that are send with data submitted via request + $message = str_replace("\r\n", "\n", $message); // possible case + $message = str_replace("\r", "\n", $message); // impossible case, but just in case replace this too - list($message_headers, $message_body) = explode("\n\n", $message_template, 2); + // 3. separate headers from body + $message_headers = Array (); + list($headers, $message_body) = explode("\n\n", $message, 2); + + $headers = explode("\n", $headers); + foreach ($headers as $header) { + $header = explode(':', $header, 2); + $message_headers[ trim($header[0]) ] = trim($header[1]); + } + + return Array ($message_headers, $message_body); + } + + /** + * Raised when email message shoul be sent + * + * @param kEvent $event + */ + function OnEmailEvent(&$event) + { + $email_event_name = $event->getEventParam('EmailEventName'); + if (strpos($email_event_name, '_') !== false) { + trigger_error('Invalid email event name '.$email_event_name.'. Use only UPPERCASE characters and dots as email event names', E_USER_ERROR); + } - - $email_object->setFrom($from_user_email, $from_user_name); - $email_object->setTo($to_user_email, $to_user_name); - $email_object->setSubject('Mail message'); - - $email_object->setHeaders($message_headers); - - if ($message_type == 'html'){ - $email_object->setHTMLBody($message_body); + // additional parameters from kApplication->EmailEvent + $send_params = $event->getEventParam('DirectSendParams'); + + // 1. get information about message sender and recipient + $recipients = $this->GetMessageRecipients($event, $event_id); + if ($recipients === false) { + // if not valid recipients found, then don't send event + return false; } - else { - $email_object->setTextBody($message_body); + + list ($from_id, $to_id) = $recipients; + list ($from_email, $from_name) = $this->GetRecipientInfo($from_id, 'from', $send_params); + list ($to_email, $to_name) = $this->GetRecipientInfo($to_id, 'to', $send_params); + + // 2. prepare message to be sent + $message_template = $this->GetMessageBody($event_id, $message_type); + if (!trim($message_template)) { + return false; } + + list ($message_headers, $message_body) = $this->ParseMessageBody($message_template, $send_params); + if (!trim($message_body)) { + return false; + } + + // 3. set headers & send message + $esender =& $this->Application->recallObject('EmailSender'); + /* @var $esender kEmailSendingHelper */ + + $esender->SetFrom($from_email, $from_name); + $esender->AddTo($to_email, $to_name); + + $message_subject = isset($message_headers['Subject']) ? $message_headers['Subject'] : 'Mail message'; + $esender->SetSubject($message_subject); - $smtp_object = &$this->Application->recallObject('kSmtpClient'); - $smtp_object->debug = $this->Application->isDebugMode() && constOn('DBG_SMTP'); - - $smtp_server = $this->Application->ConfigValue('Smtp_Server'); - $smtp_port = $this->Application->ConfigValue('Smtp_Port'); - - $smtp_authenticate = $this->Application->ConfigValue('Smtp_Authenticate'); - if ($smtp_authenticate){ - $smtp_user = $this->Application->ConfigValue('Smtp_User'); - $smtp_pass = $this->Application->ConfigValue('Smtp_Pass'); - }else{ - $smtp_user = ''; - $smtp_pass = ''; + foreach ($message_headers as $header_name => $header_value) { + $esender->SetEncodedHeader($header_name, $header_value); } + $esender->CreateTextHtmlPart($message_body, $message_type == 'html'); - if ($smtp_server){ - if ($email_object->sendSMTP($smtp_object, $smtp_server, $smtp_user, $smtp_pass, $smtp_authenticate)){ - $event->status=erSUCCESS; - } - else { - $event->status=erFAIL; - } - }else{ - if($email_object->send()){ - $event->status=erSUCCESS; - } - else { - $event->status=erFAIL; - } - } + $event->status = $esender->Deliver() ? erSUCCESS : erFAIL; if ($event->status == erSUCCESS){ - if (!$from_user_name) { - $from_user_name = strip_tags( $this->Application->ConfigValue('Site_Name') ); + // all keys, that are not used in email sending are written to log record + $send_keys = Array ('from_email', 'from_name', 'to_email', 'to_name', 'message'); + foreach ($send_keys as $send_key) { + unset($send_params[$send_key]); } - $sql = 'INSERT INTO '.TABLE_PREFIX.'EmailLog SET - fromuser = '.$this->Conn->qstr($from_user_name.' ('.$from_user_email.')').', - addressto = '.$this->Conn->qstr($to_user_name.' ('.$to_user_email.')').', - subject = '.$this->Conn->qstr($email_object->Subject).', - timestamp = UNIX_TIMESTAMP(), - event = '.$this->Conn->qstr($email_event); - $this->Conn->Query($sql); + + $fields_hash = Array ( + 'fromuser' => $from_name.' ('.$from_email.')', + 'addressto' => $to_name.' ('.$to_email.')', + 'subject' => $message_subject, + 'timestamp' => adodb_mktime(), + 'event' => $email_event_name, + 'EventParams' => serialize($send_params), + ); + + $this->Conn->doInsert($fields_hash, TABLE_PREFIX.'EmailLog'); } $this->Application->removeObject('u.email-from'); $this->Application->removeObject('u.email-to'); - return $event; } } ?> \ No newline at end of file