Fisheye: Tag 7748 refers to a dead (removed) revision in file `branches/unlabeled/unlabeled-1.3.62/core/kernel/utility/smtp_client.php'.
Fisheye: No comparison available. Pass `N' to diff?
Index: branches/unlabeled/unlabeled-1.5.2/core/install/install_data.sql
===================================================================
diff -u -r7712 -r7748
--- branches/unlabeled/unlabeled-1.5.2/core/install/install_data.sql (.../install_data.sql) (revision 7712)
+++ branches/unlabeled/unlabeled-1.5.2/core/install/install_data.sql (.../install_data.sql) (revision 7748)
@@ -63,6 +63,7 @@
INSERT INTO ConfigurationAdmin VALUES ('NoPermissionTemplate', 'la_Text_Website', 'la_config_nopermission_template', 'text', '', '', 10.17, 0, 0);
INSERT INTO ConfigurationAdmin (VariableName, heading, prompt, element_type, validation, ValueList, DisplayOrder, GroupDisplayOrder, Install) VALUES ('UseOutputCompression', 'la_Text_Website', 'la_config_UseOutputCompression', 'checkbox', '', '', 10.18, 0, 1);
INSERT INTO ConfigurationAdmin (VariableName, heading, prompt, element_type, validation, ValueList, DisplayOrder, GroupDisplayOrder, Install) VALUES ('OutputCompressionLevel', 'la_Text_Website', 'la_config_OutputCompressionLevel', 'text', '', '', 10.19, 0, 1);
+INSERT INTO ConfigurationAdmin VALUES ('MailFunctionHeaderSeparator', 'la_Text_smtp_server', 'la_config_MailFunctionHeaderSeparator', 'radio', NULL, '1=la_Linux,2=la_Windows', 30.08, 0, 0);
INSERT INTO ConfigurationValues VALUES (NULL, 'Columns_Category', '2', 'In-Portal', 'Categories');
INSERT INTO ConfigurationValues VALUES (NULL, 'DomainSelect','1','In-Portal','in-portal:configure_general');
@@ -198,6 +199,7 @@
INSERT INTO ConfigurationValues VALUES (NULL, 'NoPermissionTemplate', 'no_permission', 'In-Portal', 'in-portal:configure_general');
INSERT INTO ConfigurationValues (VariableName, VariableValue, ModuleOwner, Section) VALUES ('UseOutputCompression', '0', 'In-Portal', 'in-portal:configure_general');
INSERT INTO ConfigurationValues (VariableName, VariableValue, ModuleOwner, Section) VALUES ('OutputCompressionLevel', '7', 'In-Portal', 'in-portal:configure_general');
+INSERT INTO ConfigurationValues VALUES (0, 'MailFunctionHeaderSeparator', 1, 'In-Portal', 'in-portal:configure_general');
INSERT INTO Events VALUES (30, 'USER.ADD', 1, 0, 'In-Portal:Users', 'la_event_user.add', 0);
INSERT INTO Events VALUES (32, 'USER.ADD', 2, 0, 'In-Portal:Users', 'la_event_user.add', 1);
Index: branches/unlabeled/unlabeled-1.1.2/admin/install/upgrades/inportal_upgrade_v4.0.1.sql
===================================================================
diff -u -r7712 -r7748
--- branches/unlabeled/unlabeled-1.1.2/admin/install/upgrades/inportal_upgrade_v4.0.1.sql (.../inportal_upgrade_v4.0.1.sql) (revision 7712)
+++ branches/unlabeled/unlabeled-1.1.2/admin/install/upgrades/inportal_upgrade_v4.0.1.sql (.../inportal_upgrade_v4.0.1.sql) (revision 7748)
@@ -3,4 +3,9 @@
ALTER TABLE EmailMessage ADD `Subject` TINYTEXT NULL ;
+ALTER TABLE EmailLog ADD EventParams TEXT NOT NULL;
+
+INSERT INTO ConfigurationAdmin VALUES ('MailFunctionHeaderSeparator', 'la_Text_smtp_server', 'la_config_MailFunctionHeaderSeparator', 'radio', NULL, '1=la_Linux,2=la_Windows', 30.08, 0, 0);
+INSERT INTO ConfigurationValues VALUES (0, 'MailFunctionHeaderSeparator', 1, 'In-Portal', 'in-portal:configure_general');
+
UPDATE Modules SET Version = '4.0.1' WHERE Name = 'In-Portal';
\ No newline at end of file
Index: branches/unlabeled/unlabeled-1.1.4/core/kernel/utility/socket.php
===================================================================
diff -u
--- branches/unlabeled/unlabeled-1.1.4/core/kernel/utility/socket.php (revision 0)
+++ branches/unlabeled/unlabeled-1.1.4/core/kernel/utility/socket.php (revision 7748)
@@ -0,0 +1,361 @@
+fp)) {
+ @fclose($this->fp);
+ $this->fp = null;
+ }
+
+ // convert hostname to ip address
+ if (!$addr) {
+ return $this->raiseError('host address cannot be empty');
+ } elseif (strspn($addr, '.0123456789') == strlen($addr) || strstr($addr, '/') !== false) {
+ $this->addr = $addr;
+ } else {
+ $this->addr = @gethostbyname($addr);
+ }
+
+ $this->port = $port % 65536;
+
+ if ($persistent !== null) {
+ $this->persistent = $persistent;
+ }
+
+ if ($timeout !== null) {
+ $this->timeout = $timeout;
+ }
+
+ $openfunc = $this->persistent ? 'pfsockopen' : 'fsockopen';
+ $errno = 0;
+ $errstr = '';
+
+ if ($this->timeout) {
+ $fp = @$openfunc($this->addr, $this->port, $errno, $errstr, $this->timeout);
+ } else {
+ $fp = @$openfunc($this->addr, $this->port, $errno, $errstr);
+ }
+
+ if (!$fp) {
+ return $this->raiseError($errstr, Array($errno));
+ }
+
+ $this->fp = $fp;
+
+ return $this->setBlocking($this->blocking);
+ }
+
+ /**
+ * Disconnects from the peer, closes the socket.
+ *
+ * @access public
+ * @return mixed true on success or an error object otherwise
+ */
+ function disconnect()
+ {
+ if (!is_resource($this->fp)) {
+ return $this->raiseError('not connected');
+ }
+
+ @fclose($this->fp);
+ $this->fp = null;
+ return true;
+ }
+
+ /**
+ * Find out if the socket is in blocking mode.
+ *
+ * @access public
+ * @return boolean The current blocking mode.
+ */
+ function isBlocking()
+ {
+ return $this->blocking;
+ }
+
+ /**
+ * Sets whether the socket connection should be blocking or
+ * not. A read call to a non-blocking socket will return immediately
+ * if there is no data available, whereas it will block until there
+ * is data for blocking sockets.
+ *
+ * @param boolean $mode True for blocking sockets, false for nonblocking.
+ * @access public
+ * @return mixed true on success or an error object otherwise
+ */
+ function setBlocking($mode)
+ {
+ if (!is_resource($this->fp)) {
+ return $this->raiseError('not connected');
+ }
+
+ $this->blocking = $mode;
+ socket_set_blocking($this->fp, $this->blocking);
+ return true;
+ }
+
+ /**
+ * Sets the timeout value on socket descriptor,
+ * expressed in the sum of seconds and microseconds
+ *
+ * @param integer $seconds Seconds.
+ * @param integer $microseconds Microseconds.
+ * @access public
+ * @return mixed true on success or an error object otherwise
+ */
+ function setTimeout($seconds, $microseconds)
+ {
+ if (!is_resource($this->fp)) {
+ return $this->raiseError('not connected');
+ }
+
+ return socket_set_timeout($this->fp, $seconds, $microseconds);
+ }
+
+ /**
+ * Returns information about an existing socket resource.
+ * Currently returns four entries in the result array:
+ *
+ *
+ * timed_out (bool) - The socket timed out waiting for data
+ * blocked (bool) - The socket was blocked
+ * eof (bool) - Indicates EOF event
+ * unread_bytes (int) - Number of bytes left in the socket buffer
+ *
+ *
+ * @access public
+ * @return mixed Array containing information about existing socket resource or an error object otherwise
+ */
+ function getStatus()
+ {
+ if (!is_resource($this->fp)) {
+ return $this->raiseError('not connected');
+ }
+
+ return socket_get_status($this->fp);
+ }
+
+ /**
+ * Get a specified line of data
+ *
+ * @access public
+ * @return $size bytes of data from the socket, or a PEAR_Error if
+ * not connected.
+ */
+ function gets($size)
+ {
+ if (!is_resource($this->fp)) {
+ return $this->raiseError('not connected');
+ }
+
+ return @fgets($this->fp, $size);
+ }
+
+ /**
+ * Read a specified amount of data. This is guaranteed to return,
+ * and has the added benefit of getting everything in one fread()
+ * chunk; if you know the size of the data you're getting
+ * beforehand, this is definitely the way to go.
+ *
+ * @param integer $size The number of bytes to read from the socket.
+ * @access public
+ * @return $size bytes of data from the socket, or a PEAR_Error if
+ * not connected.
+ */
+ function read($size)
+ {
+ if (!is_resource($this->fp)) {
+ return $this->raiseError('not connected');
+ }
+
+ return @fread($this->fp, $size);
+ }
+
+ /**
+ * Write a specified amount of data.
+ *
+ * @param string $data Data to write.
+ * @param integer $blocksize Amount of data to write at once.
+ * NULL means all at once.
+ *
+ * @access public
+ * @return mixed true on success or an error object otherwise
+ */
+ function write($data, $blocksize = null)
+ {
+ if (!is_resource($this->fp)) {
+ return $this->raiseError('not connected');
+ }
+
+ if (is_null($blocksize) && !OS_WINDOWS) {
+ return fwrite($this->fp, $data);
+ } else {
+ if (is_null($blocksize)) {
+ $blocksize = 1024;
+ }
+
+ $pos = 0;
+ $size = strlen($data);
+ while ($pos < $size) {
+ $written = @fwrite($this->fp, substr($data, $pos, $blocksize));
+ if ($written === false) {
+ return false;
+ }
+ $pos += $written;
+ }
+
+ return $pos;
+ }
+ }
+
+ /**
+ * Write a line of data to the socket, followed by a trailing "\r\n".
+ *
+ * @access public
+ * @return mixed fputs result, or an error
+ */
+ function writeLine($data)
+ {
+ if (!is_resource($this->fp)) {
+ return $this->raiseError('not connected');
+ }
+
+ return fwrite($this->fp, $data . "\r\n");
+ }
+
+ /**
+ * Tests for end-of-file on a socket descriptor.
+ *
+ * @access public
+ * @return bool
+ */
+ function eof()
+ {
+ return (is_resource($this->fp) && feof($this->fp));
+ }
+
+ /**
+ * Read until either the end of the socket or a newline, whichever
+ * comes first. Strips the trailing newline from the returned data.
+ *
+ * @access public
+ * @return All available data up to a newline, without that
+ * newline, or until the end of the socket, or a PEAR_Error if
+ * not connected.
+ */
+ function readLine()
+ {
+ if (!is_resource($this->fp)) {
+ return $this->raiseError('not connected');
+ }
+
+ $line = '';
+ $timeout = time() + $this->timeout;
+ while (!feof($this->fp) && (!$this->timeout || time() < $timeout)) {
+ $line .= @fgets($this->fp, $this->lineLength);
+ if (substr($line, -1) == "\n") {
+ return rtrim($line, "\r\n");
+ }
+ }
+ return $line;
+ }
+
+ /**
+ * Read until the socket closes, or until there is no more data in
+ * the inner PHP buffer. If the inner buffer is empty, in blocking
+ * mode we wait for at least 1 byte of data. Therefore, in
+ * blocking mode, if there is no data at all to be read, this
+ * function will never exit (unless the socket is closed on the
+ * remote end).
+ *
+ * @access public
+ *
+ * @return string All data until the socket closes, or a PEAR_Error if
+ * not connected.
+ */
+ function readAll()
+ {
+ if (!is_resource($this->fp)) {
+ return $this->raiseError('not connected');
+ }
+
+ $data = '';
+ while (!feof($this->fp)) {
+ $data .= @fread($this->fp, $this->lineLength);
+ }
+ return $data;
+ }
+
+ function raiseError($text, $params = Array())
+ {
+ trigger_error(vsprintf($text, $params), E_USER_WARNING);
+ return false;
+ }
+ }
+
+?>
\ No newline at end of file
Index: branches/unlabeled/unlabeled-1.4.2/core/kernel/constants.php
===================================================================
diff -u -r7652 -r7748
--- branches/unlabeled/unlabeled-1.4.2/core/kernel/constants.php (.../constants.php) (revision 7652)
+++ branches/unlabeled/unlabeled-1.4.2/core/kernel/constants.php (.../constants.php) (revision 7748)
@@ -45,4 +45,8 @@
// don't show debugger buttons on front (if not overrided in "debug.php")
safeDefine('DBG_TOOLBAR_BUTTONS', 0);
}
+
+ // common usage regular expressions
+ define('REGEX_EMAIL_USER', '[-a-zA-Z0-9!\#$%&*+\/=?^_`{|}~.]+');
+ define('REGEX_EMAIL_DOMAIN', '[a-zA-Z0-9]{1}[-.a-zA-Z0-9_]*\.[a-zA-Z]{2,6}');
?>
\ No newline at end of file
Index: branches/unlabeled/unlabeled-1.4.2/core/install/install_schema.sql
===================================================================
diff -u -r7652 -r7748
--- branches/unlabeled/unlabeled-1.4.2/core/install/install_schema.sql (.../install_schema.sql) (revision 7652)
+++ branches/unlabeled/unlabeled-1.4.2/core/install/install_schema.sql (.../install_schema.sql) (revision 7748)
@@ -286,9 +286,10 @@
EmailLogId int(11) NOT NULL auto_increment,
fromuser varchar(200) default NULL,
addressto varchar(255) default NULL,
- subject varchar(255) default NULL,
- timestamp bigint(20) default '0',
+ `subject` varchar(255) default NULL,
+ `timestamp` bigint(20) default '0',
event varchar(100) default NULL,
+ EventParams text NOT NULL,
PRIMARY KEY (EmailLogId)
);
Index: branches/unlabeled/unlabeled-1.33.2/core/units/categories/categories_tag_processor.php
===================================================================
diff -u -r7650 -r7748
--- branches/unlabeled/unlabeled-1.33.2/core/units/categories/categories_tag_processor.php (.../categories_tag_processor.php) (revision 7650)
+++ branches/unlabeled/unlabeled-1.33.2/core/units/categories/categories_tag_processor.php (.../categories_tag_processor.php) (revision 7748)
@@ -184,13 +184,11 @@
// $cat_id = $this->Application->Parser->GetParam('cat_id');
$cat_id = $this->Application->GetVar($this->getPrefixSpecial().'_id');
}
- if($cat_id == 'Root')
- {
- $object =& $this->Application->recallObject('mod.'.$params['module']);
- $params['m_cat_id'] = $object->GetDBField('RootCat');
+ if ("$cat_id" == 'Root') {
+ $params['m_cat_id'] = $this->Application->findModule('Name', $params['module'], 'RootCat');
unset($params['module']);
}
- else{
+ else {
$params['m_cat_id'] = $cat_id;
}
unset($params['cat_id']);
Fisheye: Tag 7748 refers to a dead (removed) revision in file `branches/unlabeled/unlabeled-1.16.8/core/kernel/utility/email.php'.
Fisheye: No comparison available. Pass `N' to diff?
Index: branches/unlabeled/unlabeled-1.29.2/core/units/email_events/email_events_event_handler.php
===================================================================
diff -u -r7696 -r7748
--- branches/unlabeled/unlabeled-1.29.2/core/units/email_events/email_events_event_handler.php (.../email_events_event_handler.php) (revision 7696)
+++ branches/unlabeled/unlabeled-1.29.2/core/units/email_events/email_events_event_handler.php (.../email_events_event_handler.php) (revision 7748)
@@ -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
+ // $replacement_tags = $message->GetDBField('ReplacementTags');
+ // $replacement_tags = $replacement_tags ? unserialize($replacement_tags) : Array ();
+
+ $replacement_tags = Array (
+ ' ' ' '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
Index: branches/unlabeled/unlabeled-1.1.4/core/kernel/utility/email_send.php
===================================================================
diff -u
--- branches/unlabeled/unlabeled-1.1.4/core/kernel/utility/email_send.php (revision 0)
+++ branches/unlabeled/unlabeled-1.1.4/core/kernel/utility/email_send.php (revision 7748)
@@ -0,0 +1,1939 @@
+guessOptions = Array (
+ 'attachments' => Array(),
+ 'inline_attachments' => Array (),
+ 'text_part' => false,
+ 'html_part' => false,
+ );
+
+ // read SMTP server connection params from config
+ $smtp_mapping = Array ('server' => 'Smtp_Server', 'port' => 'Smtp_Port');
+ if ($this->Application->ConfigValue('Smtp_Authenticate')) {
+ $smtp_mapping['username'] = 'Smtp_User';
+ $smtp_mapping['password'] = 'Smtp_Pass';
+ }
+
+ foreach ($smtp_mapping as $smtp_name => $config_name) {
+ $this->smtpParams[$smtp_name] = $this->Application->ConfigValue($config_name);
+ }
+ $this->smtpParams['use_auth'] = isset($this->smtpParams['username']) ? true : false;
+ $this->smtpParams['localhost'] = 'localhost'; // The value to give when sending EHLO or HELO.
+
+ $this->sendMethod = $this->smtpParams['server'] && $this->smtpParams['port'] ? 'SMTP' : 'Mail';
+
+ if ($this->sendMethod == 'SMTP') {
+ // create connection object if we will use SMTP
+ $this->smtpSocket =& $this->Application->makeClass('Socket');
+ }
+
+ $this->SetCharset(null, true);
+ }
+
+
+ /**
+ * Returns new message id header by sender's email address
+ *
+ * @param string $email_address email address
+ * @return string
+ */
+ function GenerateMessageID($email_address)
+ {
+ list ($micros, $seconds) = explode(' ', microtime());
+ list ($user, $domain) = explode('@', $email_address, 2);
+
+ $message_id = strftime('%Y%m%d%H%M%S', $seconds).substr($micros, 1, 5).'.'.preg_replace('/[^A-Za-z]+/', '-', $user).'@'.$domain;
+
+ $this->SetHeader('Message-ID', '<'.$message_id.'>');
+ }
+
+ /**
+ * Returns extension of given filename
+ *
+ * @param string $filename
+ * @return string
+ */
+ function GetFilenameExtension($filename)
+ {
+ $last_dot = strrpos($filename, '.');
+ return $last_dot !== false ? substr($filename, $last_dot + 1) : '';
+ }
+
+ /**
+ * Creates boundary for part by number (only if it's missing)
+ *
+ * @param int $part_number
+ *
+ */
+
+ function CreatePartBoundary($part_number)
+ {
+ $part =& $this->parts[$part_number];
+ if (!isset($part['BOUNDARY'])) {
+ $part['BOUNDARY'] = md5(uniqid($part_number.time()));
+
+ }
+ }
+
+ /**
+ * Returns ready to use headers associative array of any message part by it's number
+ *
+ * @param int $part_number
+ * @return Array
+ */
+ function GetPartHeaders($part_number)
+ {
+ $part =& $this->parts[$part_number];
+
+ if (!isset($part['Content-Type'])) {
+ return $this->SetError('MISSING_CONTENT_TYPE');
+ }
+
+ $full_type = strtolower($part['Content-Type']);
+ list ($type, $sub_type) = explode('/', $full_type);
+
+ $headers['Content-Type'] = $full_type;
+ switch ($type) {
+ case 'text':
+ case 'image':
+ case 'audio':
+ case 'video':
+ case 'application':
+ case 'message':
+ // 1. update content-type header
+ if (isset($part['CHARSET'])) {
+ $headers['Content-Type'] .= '; charset='.$part['CHARSET'];
+ }
+ if (isset($part['NAME'])) {
+ $headers['Content-Type'] .= '; name="'.$part['NAME'].'"';
+ }
+
+ // 2. set content-transfer-encoding header
+ if (isset($part['Content-Transfer-Encoding'])) {
+ $headers['Content-Transfer-Encoding'] = $part['Content-Transfer-Encoding'];
+ }
+
+ // 3. set content-disposition header
+ if (isset($part['DISPOSITION']) && $part['DISPOSITION']) {
+ $headers['Content-Disposition'] = $part['DISPOSITION'];
+ if (isset($part['NAME'])) {
+ $headers['Content-Disposition'] .= '; filename="'.$part['NAME'].'"';
+ }
+ }
+ break;
+
+ case 'multipart':
+ switch ($sub_type) {
+ case 'alternative':
+ case 'related':
+ case 'mixed':
+ case 'parallel':
+ $this->CreatePartBoundary($part_number);
+ $headers['Content-Type'] .= '; boundary="'.$part['BOUNDARY'].'"';
+ break;
+
+ default:
+ return $this->SetError('INVALID_MULTIPART_SUBTYPE', Array($sub_type));
+ }
+ break;
+
+ default:
+ return $this->SetError('INVALID_CONTENT_TYPE', Array($full_type));
+ }
+
+ // set content-id if any
+ if (isset($part['Content-ID'])) {
+ $headers['Content-ID'] = '<'.$part['Content-ID'].'>';
+ }
+
+ return $headers;
+ }
+
+ function GetPartBody($part_number)
+ {
+ $part =& $this->parts[$part_number];
+
+ if (!isset($part['Content-Type'])) {
+ return $this->SetError('MISSING_CONTENT_TYPE');
+ }
+
+ $full_type = strtolower($part['Content-Type']);
+ list ($type, $sub_type) = explode('/', $full_type);
+
+ $body = '';
+ switch ($type) {
+ // compose text/binary content
+ case 'text':
+ case 'image':
+ case 'audio':
+ case 'video':
+ case 'application':
+ case 'message':
+ // 1. get content of part
+ if (isset($part['FILENAME'])) {
+ // content provided via absolute path to content containing file
+ $filename = $part['FILENAME'];
+ $file_size = filesize($filename);
+
+ $body = file_get_contents($filename);
+ if ($body === false) {
+ return $this->SetError('FILE_PART_OPEN_ERROR', Array($filename));
+ }
+
+ $actual_size = strlen($body);
+ if (($file_size === false || $actual_size > $file_size) && get_magic_quotes_runtime()) {
+ $body = stripslashes($body);
+ }
+
+ if ($file_size !== false && $actual_size != $file_size) {
+ return $this->SetError('FILE_PART_DATA_ERROR', Array($filename));
+ }
+ }
+ else {
+ // content provided directly as one of part keys
+ if (!isset($part['DATA'])) {
+ return $this->SetError('FILE_PART_DATA_MISSING');
+ }
+ $body =& $part['DATA'];
+ }
+
+ // 2. get part transfer encoding
+ $encoding = isset($part['Content-Transfer-Encoding']) ? strtolower($part['Content-Transfer-Encoding']) : '';
+ if (!in_array($encoding, Array ('', 'base64', 'quoted-printable', '7bit'))) {
+ return $this->SetError('INVALID_ENCODING', Array($encoding));
+ }
+
+ if ($encoding == 'base64') {
+ // split base64 encoded text by 76 symbols at line (MIME requirement)
+ $body = chunk_split( base64_encode($body) );
+ }
+ break;
+
+ case 'multipart':
+ // compose multipart message
+ switch ($sub_type) {
+ case 'alternative':
+ case 'related':
+ case 'mixed':
+ case 'parallel':
+ $this->CreatePartBoundary($part_number);
+ $boundary = $this->line_break.'--'.$part['BOUNDARY'];
+
+ foreach ($part['PARTS'] as $multipart_number) {
+ $body .= $boundary.$this->line_break;
+ $part_headers = $this->GetPartHeaders($multipart_number);
+ if ($part_headers === false) {
+ // some of sub-part headers were invalid
+ return false;
+ }
+
+ foreach ($part_headers as $header_name => $header_value) {
+ $body .= $header_name.': '.$header_value.$this->line_break;
+ }
+
+ $part_body = $this->GetPartBody($multipart_number);
+ if ($part_body === false) {
+ // part body was invalid
+ return false;
+ }
+
+ $body .= $this->line_break.$part_body;
+ }
+ $body .= $boundary.'--'.$this->line_break;
+ break;
+
+ default:
+ return $this->SetError('INVALID_MULTIPART_SUBTYPE', Array($sub_type));
+ }
+ break;
+ default:
+ return $this->SetError('INVALID_CONTENT_TYPE', Array($full_type));
+ }
+
+ return $body;
+ }
+
+ /**
+ * Applies quoted-printable encoding to specified text
+ *
+ * @param string $text
+ * @param string $header_charset
+ * @param int $break_lines
+ * @return unknown
+ */
+ function QuotedPrintableEncode($text, $header_charset = '', $break_lines = 1)
+ {
+ $ln = strlen($text);
+ $h = strlen($header_charset) > 0;
+ if ($h) {
+ $s = Array (
+ '=' => 1,
+ '?' => 1,
+ '_' => 1,
+ '(' => 1,
+ ')' => 1,
+ '<' => 1,
+ '>' => 1,
+ '@' => 1,
+ ',' => 1,
+ ';' => 1,
+ '"' => 1,
+ '\\' => 1,
+ /*
+ '/' => 1,
+ '[' => 1,
+ ']' => 1,
+ ':' => 1,
+ '.' => 1,
+ */
+ );
+
+ $b = $space = $break_lines = 0;
+ for ($i = 0; $i < $ln; $i++) {
+ if (isset($s[$text[$i]])) {
+ $b = 1;
+ break;
+ }
+
+ switch ($o = ord($text[$i])) {
+ case 9:
+ case 32:
+ $space = $i + 1;
+ $b = 1;
+ break 2;
+ case 10:
+ case 13:
+ break 2;
+ default:
+ if ($o < 32 || $o > 127) {
+ $b = 1;
+ break 2;
+ }
+ }
+ }
+
+ if($i == $ln) {
+ return $text;
+ }
+
+ if ($space > 0) {
+ return substr($text, 0, $space).($space < $ln ? $this->QuotedPrintableEncode(substr($text, $space), $header_charset, 0) : '');
+ }
+ }
+
+ for ($w = $e = '', $n = 0, $l = 0, $i = 0; $i < $ln; $i++) {
+ $c = $text[$i];
+ $o = ord($c);
+ $en = 0;
+ switch ($o) {
+ case 9:
+ case 32:
+ if (!$h) {
+ $w = $c;
+ $c = '';
+ }
+ else {
+ if ($b) {
+ if ($o == 32) {
+ $c = '_';
+ }
+ else {
+ $en = 1;
+ }
+ }
+ }
+ break;
+ case 10:
+ case 13:
+ if (strlen($w)) {
+ if ($break_lines && $l + 3 > 75) {
+ $e .= '='.$this->line_break;
+ $l = 0;
+ }
+
+ $e .= sprintf('=%02X', ord($w));
+ $l += 3;
+ $w = '';
+ }
+
+ $e .= $c;
+ if ($h) {
+ $e .= "\t";
+ }
+ $l = 0;
+ continue 2;
+ case 46:
+ case 70:
+ case 102:
+ $en = (!$h && ($l == 0 || $l + 1 > 75));
+ break;
+ default:
+ if ($o > 127 || $o < 32 || !strcmp($c, '=')) {
+ $en = 1;
+ }
+ elseif ($h && isset($s[$c])) {
+ $en = 1;
+ }
+ break;
+ }
+
+ if (strlen($w)) {
+ if ($break_lines && $l + 1 > 75) {
+ $e .= '='.$this->line_break;
+ $l = 0;
+ }
+ $e .= $w;
+ $l++;
+ $w = '';
+ }
+
+ if (strlen($c)) {
+ if ($en) {
+ $c = sprintf('=%02X', $o);
+ $el = 3;
+ $n = 1;
+ $b = 1;
+ }
+ else {
+ $el = 1;
+ }
+ if ($break_lines && $l + $el > 75) {
+ $e .= '='.$this->line_break;
+ $l = 0;
+ }
+ $e .= $c;
+ $l += $el;
+ }
+ }
+ if (strlen($w)) {
+ if ($break_lines && $l + 3 > 75) {
+ $e .= '='.$this->line_break;
+ }
+ $e .= sprintf('=%02X', ord($w));
+ }
+
+ return $h && $n ? '=?'.$header_charset.'?q?'.$e.'?=' : $e;
+ }
+
+ /**
+ * Sets message header + encodes is by quoted-printable using charset specified
+ *
+ * @param string $name
+ * @param string $value
+ * @param string $encoding_charset
+ */
+ function SetHeader($name, $value, $encoding_charset = '')
+ {
+ if ($encoding_charset) {
+ // actually for headers base64 method may give shorter result
+ $value = $this->QuotedPrintableEncode($value, $encoding_charset);
+ }
+
+ $this->headers[$name] = $value;
+ }
+
+ /**
+ * Sets header + automatically encodes it using default charset
+ *
+ * @param string $name
+ * @param string $value
+ */
+ function SetEncodedHeader($name, $value)
+ {
+ $this->SetHeader($name, $value, $this->charset);
+ }
+
+ /**
+ * Sets header which value is email and username +autoencode
+ *
+ * @param string $header
+ * @param string $address
+ * @param string $name
+ */
+ function SetEncodedEmailHeader($header, $address, $name)
+ {
+ $this->SetHeader($header, $this->QuotedPrintableEncode($name, $this->charset).' <'.$address.'>');
+ }
+
+ function SetMultipleEncodedEmailHeader($header, $addresses)
+ {
+ $value = '';
+ foreach ($addresses as $name => $address) {
+ $value .= $this->QuotedPrintableEncode($name, $this->charset).' <'.$address.'>, ';
+ }
+ $value = preg_replace('/(.*),$/', '\\1', $value);
+
+ $this->SetHeader($header, $value);
+ }
+
+
+ /**
+ * Adds new part to message and returns it's number
+ *
+ * @param Array $part_definition
+ * @param int $part_number number of new part
+ * @return int
+ */
+ function AddPart(&$part_definition, $part_number = false)
+ {
+ $part_number = $part_number !== false ? $part_number : count($this->parts);
+ $this->parts[$part_number] =& $part_definition;
+ return $part_number;
+ }
+
+ /**
+ * Returns text version of HTML document
+ *
+ * @param string $html
+ * @return string
+ */
+ function ConvertToText($html)
+ {
+ $search = Array (
+ "'(<\/td>.*)[\r\n]+(.*[\r\n]{0,2})|(<\/p>)|(<\/div>)|(<\/tr>)'i",
+ "'(.*?)'si",
+ "' |