/**
  * Send an email to a number of recipients
  * Returns the number of successful recipients, or FALSE on failure
  * @param mixed The recipients to send to.  One of string, array, 2-dimensional array or Swift_Address
  * @param mixed The address to send from. string or Swift_Address
  * @param string The message subject
  * @param string The message body, optional
  * @return int
  */
 public function send($recipients, $from, $subject, $body = null)
 {
     $this->addTo($recipients);
     $sender = false;
     if (is_string($from)) {
         $sender = $this->stringToAddress($from);
     } elseif ($from instanceof Swift_Address) {
         $sender = $from;
     }
     if (!$sender) {
         return false;
     }
     $this->message->setSubject($subject);
     if ($body) {
         $this->message->setBody($body);
     }
     try {
         if (!$this->exactCopy && !$this->recipients->getCc() && !$this->recipients->getBcc()) {
             $sent = $this->swift->batchSend($this->message, $this->recipients, $sender);
         } else {
             $sent = $this->swift->send($this->message, $this->recipients, $sender);
         }
         if ($this->autoFlush) {
             $this->flush();
         }
         return $sent;
     } catch (Swift_ConnectionException $e) {
         $this->setError("Sending failed:<br />" . $e->getMessage());
         return false;
     }
 }
Example #2
0
 /**
  * Send an email to a number of recipients
  * Returns the number of successful recipients, or FALSE on failure
  * @param mixed The recipients to send to.  One of string, array, 2-dimensional array or Swift_Address
  * @param mixed The address to send from. string or Swift_Address
  * @param string The message subject
  * @param string The message body, optional
  * @return int
  */
 function send($recipients, $from, $subject, $body = null)
 {
     $this->addTo($recipients);
     $sender = false;
     if (is_string($from)) {
         $sender = $this->stringToAddress($from);
     } elseif (is_a($from, "Swift_Address")) {
         $sender =& $from;
     }
     if (!$sender) {
         return false;
     }
     $this->message->setSubject($subject);
     if ($body) {
         $this->message->setBody($body);
     }
     $sent = 0;
     Swift_Errors::expect($e, "Swift_ConnectionException");
     if (!$this->exactCopy && !$this->recipients->getCc() && !$this->recipients->getBcc()) {
         $sent = $this->swift->batchSend($this->message, $this->recipients, $sender);
     } else {
         $sent = $this->swift->send($this->message, $this->recipients, $sender);
     }
     if (!$e) {
         Swift_Errors::clear("Swift_ConnectionException");
         if ($this->autoFlush) {
             $this->flush();
         }
         return $sent;
     }
     $this->setError("Sending failed:<br />" . $e->getMessage());
     return false;
 }
Example #3
0
 /**
  * Sends notifications *now*
  * @param mixed $to string or array...the type of address (email, task ID, user ID) is specified below
  * @param integer $to_type type of $to address
  * @param integer $type type of notification
  * @param array $data additional info needed for notification
  * @access public
  * @return bool
  */
 function send_now($to, $to_type, $type, $data = array())
 {
     global $db, $fs, $proj;
     $emails = array();
     $jids = array();
     $result = true;
     if (defined('FS_NO_MAIL')) {
         return true;
     }
     switch ($to_type) {
         case ADDRESS_DONE:
             // from send_stored()
             list($emails, $jids) = $to;
             $data = unserialize($data['message_data']);
             $subject = $data['subject'];
             $body = $data['body'];
             break;
         case ADDRESS_EMAIL:
             // this happens on email confirmation, when no user exists
             $emails = is_array($to) ? $to : array($to);
             break;
         case ADDRESS_USER:
             // list of user IDs
             list($emails, $jids) = Notifications::user_to_address($to, $type);
             break;
         case ADDRESS_TASK:
             // now we need everyone on the notification list and the assignees
             list($emails, $jids) = Notifications::task_notifications($to, $type, ADDRESS_EMAIL);
             $data['task_id'] = $to;
             break;
     }
     if (isset($data['task_id'])) {
         $data['task'] = Flyspray::getTaskDetails($data['task_id']);
         // we have project specific options
         $pid = $db->x->GetOne('SELECT project_id FROM {tasks} WHERE task_id = ?', null, $data['task_id']);
         $data['project'] = new Project($pid);
     }
     if ($to_type != ADDRESS_DONE) {
         list($subject, $body) = Notifications::generate_message($type, $data);
     }
     if (isset($data['task_id'])) {
         // Now, we add the project contact addresses,
         // but only if the task is public
         $data['task'] = Flyspray::getTaskDetails($data['task_id']);
         if ($data['task']['mark_private'] != '1' && in_array($type, explode(' ', $data['project']->prefs['notify_types']))) {
             $proj_emails = preg_split('/[\\s,;]+/', $proj->prefs['notify_email'], -1, PREG_SPLIT_NO_EMPTY);
             $proj_jids = preg_split('/[\\s,;]+/', $proj->prefs['notify_jabber'], -1, PREG_SPLIT_NO_EMPTY);
             $emails = array_merge($proj_emails, $emails);
             if ($fs->prefs['global_email']) {
                 $emails[] = $fs->prefs['global_email'];
             }
             if ($fs->prefs['global_jabber']) {
                 $jids[] = $fs->prefs['global_jabber'];
             }
             $jids = array_merge($proj_jids, $emails);
         }
     }
     // Now we start sending
     if (count($emails)) {
         Swift_ClassLoader::load('Swift_Connection_Multi');
         Swift_ClassLoader::load('Swift_Connection_SMTP');
         $pool = new Swift_Connection_Multi();
         // first choose method
         if ($fs->prefs['smtp_server']) {
             $split = explode(':', $fs->prefs['smtp_server']);
             $port = null;
             if (count($split) == 2) {
                 $fs->prefs['smtp_server'] = $split[0];
                 $port = $split[1];
             }
             // connection... SSL, TLS or none
             if ($fs->prefs['email_ssl']) {
                 $smtp = new Swift_Connection_SMTP($fs->prefs['smtp_server'], $port ? $port : SWIFT_SMTP_PORT_SECURE, SWIFT_SMTP_ENC_SSL);
             } else {
                 if ($fs->prefs['email_tls']) {
                     $smtp = new Swift_Connection_SMTP($fs->prefs['smtp_server'], $port ? $port : SWIFT_SMTP_PORT_SECURE, SWIFT_SMTP_ENC_TLS);
                 } else {
                     $smtp = new Swift_Connection_SMTP($fs->prefs['smtp_server'], $port);
                 }
             }
             if ($fs->prefs['smtp_user']) {
                 $smtp->setUsername($fs->prefs['smtp_user']);
                 $smtp->setPassword($fs->prefs['smtp_pass']);
             }
             if (defined('FS_SMTP_TIMEOUT')) {
                 $smtp->setTimeout(FS_SMTP_TIMEOUT);
             }
             $pool->addConnection($smtp);
         } else {
             Swift_ClassLoader::load('Swift_Connection_NativeMail');
             // a connection to localhost smtp server as fallback, discarded if there is no such thing available.
             $pool->addConnection(new Swift_Connection_SMTP());
             $pool->addConnection(new Swift_Connection_NativeMail());
         }
         $swift = new Swift($pool);
         if (isset($data['task_id'])) {
             $swift->attachPlugin(new NotificationsThread($data['task_id'], $emails, $db), 'MessageThread');
         }
         if (defined('FS_MAIL_DEBUG')) {
             $swift->log->enable();
             Swift_ClassLoader::load('Swift_Plugin_VerboseSending');
             $view = new Swift_Plugin_VerboseSending_DefaultView();
             $swift->attachPlugin(new Swift_Plugin_VerboseSending($view), "verbose");
         }
         $message = new Swift_Message($subject, $body);
         // check for reply-to
         if (isset($data['project']) && $data['project']->prefs['notify_reply']) {
             $message->setReplyTo($data['project']->prefs['notify_reply']);
         }
         if (isset($data['project']) && isset($data['project']->prefs['bounce_address'])) {
             $message->setReturnPath($data['project']->prefs['bounce_address']);
         }
         $message->headers->setCharset('utf-8');
         $message->headers->set('Precedence', 'list');
         $message->headers->set('X-Mailer', 'Flyspray');
         // Add custom headers, possibly
         if (isset($data['headers'])) {
             $headers = array_map('trim', explode("\n", $data['headers']));
             if ($headers = array_filter($headers)) {
                 foreach ($headers as $header) {
                     list($name, $value) = explode(':', $header);
                     $message->headers->set(sprintf('X-Flyspray-%s', $name), $value);
                 }
             }
         }
         $recipients = new Swift_RecipientList();
         $recipients->addTo($emails);
         // && $result purpose: if this has been set to false before, it should never become true again
         // to indicate an error
         $result = $swift->batchSend($message, $recipients, $fs->prefs['admin_email']) === count($emails) && $result;
         if (isset($data['task_id'])) {
             $plugin =& $swift->getPlugin('MessageThread');
             if (count($plugin->thread_info)) {
                 $stmt = $db->x->autoPrepare('{notification_threads}', array('task_id', 'recipient_id', 'message_id'));
                 $db->x->executeMultiple($stmt, $plugin->thread_info);
                 $stmt->free();
             }
         }
         $swift->disconnect();
     }
     if (count($jids)) {
         $jids = array_unique($jids);
         if (!$fs->prefs['jabber_username'] || !$fs->prefs['jabber_password']) {
             return $result;
         }
         // nothing that can't be guessed correctly ^^
         if (!$fs->prefs['jabber_port']) {
             $fs->prefs['jabber_port'] = 5222;
         }
         require_once 'class.jabber2.php';
         $jabber = new Jabber($fs->prefs['jabber_username'], $fs->prefs['jabber_password'], $fs->prefs['jabber_security'], $fs->prefs['jabber_port'], $fs->prefs['jabber_server']);
         $jabber->SetResource('flyspray');
         $jabber->login();
         foreach ($jids as $jid) {
             $result = $jabber->send_message($jid, $body, $subject, 'normal') && $result;
         }
     }
     return $result;
 }
 /**
  * Send email to list of recipients
  * 
  * $to is a list of users who need to receive email notifications. If this 
  * function gets list of email addresses default language will be used. If 
  * we get User instances we'll use language set as prefered on their profile 
  * page
  * 
  * $to can also be a single user or email address
  * 
  * $tpl is a script in format module/name. If / is not present activeCollab 
  * will assume that template is in system module
  * 
  * Context is object that this email is primary related to
  * 
  * $attachments is array of attachments that are structured like this
  *    path -> path to file
  *    name -> name which will be displayed in email (if ommited original filename will be used)
  *    mime_type -> file mime type (if ommited system will determine mime type automatically)
  * here is sample of one $attachments array
  *    $attachments = array(
  *      array('path' => '/work/picture3.png', 'name' => 'simple_file_name.png', 'mime_type' => 'image/png')
  *    );
  * 
  * @param array $to
  * @param string $tpl
  * @param array $replacements
  * @param mixed $context
  * @param array $attachments
  * @return boolean
  */
 function send($to, $tpl, $replacements = null, $context = null, $attachments = null)
 {
     static $mark_as_bulk = null, $empty_return_path = null;
     if (isset($this) && instance_of($this, 'ApplicationMailer')) {
         if (!$this->connected) {
             $this->connect();
         }
         // if
         if (!is_foreachable($to)) {
             if (instance_of($to, 'User') || is_valid_email($to)) {
                 $to = array($to);
             } else {
                 return true;
                 // no recipients
             }
             // if
         }
         // if
         if (strpos($tpl, '/') === false) {
             $template_module = SYSTEM_MODULE;
         } else {
             list($template_module, $template_name) = explode('/', $tpl);
         }
         // if
         $template = EmailTemplates::findById(array('module' => $template_module, 'name' => $template_name));
         if (!instance_of($template, 'EmailTemplate')) {
             return false;
         }
         // if
         $owner_company = get_owner_company();
         if (is_array($replacements)) {
             $replacements['owner_company_name'] = $owner_company->getName();
         } else {
             $replacements = array('owner_company_name' => $owner_company->getName());
         }
         // if
         // Array of messages and recipients organized by language
         $to_send = array();
         // Set default locale (built in one)
         $default_locale = BUILT_IN_LOCALE;
         // Do we have a default language set
         $default_language_id = ConfigOptions::getValue('language');
         if ($default_language_id) {
             $default_language = Languages::findById($default_language_id);
             if (instance_of($default_language, 'Language') && !$default_language->isBuiltIn()) {
                 $default_locale = $default_language->getLocale();
             }
             // if
         }
         // if
         // Cache of loaded languages
         $languages = array();
         // Get from email and from name
         $from_email = ConfigOptions::getValue('notifications_from_email');
         $from_name = ConfigOptions::getValue('notifications_from_name');
         if (!is_valid_email($from_email)) {
             $from_email = ADMIN_EMAIL;
         }
         // if
         if (empty($from_name)) {
             $from_name = $owner_company->getName();
         }
         // if
         // Now prepare messages
         foreach ($to as $recipient) {
             $locale = $default_locale;
             if (instance_of($recipient, 'User')) {
                 $locale = $recipient->getLocale($default_locale);
                 $recipient_name = $recipient->getDisplayName();
                 $recipient_email = $recipient->getEmail();
                 // If same reset name... "name@site.com <*****@*****.**>" can cause
                 // problems with some servers
                 if ($recipient_name == $recipient_email) {
                     $recipient_name = null;
                 }
                 // if
             } else {
                 $recipient_name = null;
                 $recipient_email = $recipient;
             }
             // if
             $language = isset($languages[$locale]) ? $languages[$locale] : Languages::findByLocale($locale);
             // We have message prepared, just need to add a recipient
             //BOF:mod
             //if(isset($to_send[$locale])) {
             if (isset($to_send[$locale]) && $tpl != 'resources/new_comment') {
                 //EOF:moid
                 $to_send[$locale]['recipients']->add($recipient_email, $recipient_name);
                 // Need to prepare message and add first recipient
             } else {
                 //BOF:mod 20110711 ticketid231
                 if ($tpl == 'resources/new_comment') {
                     $mark_actionrequest_complete = '';
                     $link = mysql_connect(DB_HOST, DB_USER, DB_PASS);
                     mysql_select_db(DB_NAME);
                     $query = "select a.is_action_request, b.project_id from healingcrystals_assignments_action_request a inner join healingcrystals_project_objects b on a.comment_id=b.id where a.comment_id='" . $replacements['comment_id'] . "' and a.user_id='" . $recipient->getId() . "'";
                     $result = mysql_query($query);
                     if (mysql_num_rows($result)) {
                         $info = mysql_fetch_assoc($result);
                         if ($info['is_action_request'] == '1') {
                             $mark_actionrequest_complete = '<div style="margin:5px 0 5px 0;"><a href="' . assemble_url('project_comment_action_request_completed', array('project_id' => $info['project_id'], 'comment_id' => $replacements['comment_id'])) . '">Click here to Mark this Action Request Complete</a></div>';
                         }
                     }
                     mysql_close($link);
                     $replacements['mark_actionrequest_complete'] = $mark_actionrequest_complete;
                 }
                 //EOF:mod 20110711 ticketid231
                 $subject = $template->getSubject($locale);
                 $body = $template->getBody($locale);
                 foreach ($replacements as $k => $v) {
                     if (is_array($v)) {
                         $v = isset($v[$locale]) ? $v[$locale] : array_shift($v);
                     }
                     // if
                     $subject = str_replace(":{$k}", $v, $subject);
                     if (str_ends_with($k, '_body')) {
                         $body = str_replace(":{$k}", $v, $body);
                     } else {
                         //$body = str_replace(":$k", clean($v), $body);
                         $body = str_replace(":{$k}", $v, $body);
                     }
                     // if
                 }
                 // foreach
                 //BOF:mod
                 //BOF:mod 20111101
                 /*
                 //EOF:mod 20111101
                 if ($tpl=='resources/new_comment'){
                 	$add_to_subject = '';
                 	            $link = mysql_connect(DB_HOST, DB_USER, DB_PASS);
                 				mysql_select_db(DB_NAME);
                 				$query = "select a.is_action_request, a.is_fyi, a.priority_actionrequest, b.project_id from healingcrystals_assignments_action_request a inner join healingcrystals_project_objects b on a.comment_id=b.id where a.comment_id='" . $replacements['comment_id'] . "' and a.user_id='" . $recipient->getId() . "'";
                 				$result = mysql_query($query, $link);
                 				if (mysql_num_rows($result)){
                 					$info = mysql_fetch_assoc($result);
                 					$flag_action_request = $info['is_action_request'];
                 					$flag_fyi = $info['is_fyi'];
                 					$priority = $info['priority_actionrequest'];
                 					if ($flag_action_request=='1'){
                 						switch($priority){
                 							case PRIORITY_LOWEST:
                 								$priority_desc = 'Lowest Priority ';
                 								break;
                 							case PRIORITY_LOW:
                 								$priority_desc = 'Low Priority ';
                 								break;
                 							case PRIORITY_NORMAL:
                 								$priority_desc = 'Normal Priority ';
                 								break;
                 							case PRIORITY_HIGH:
                 								$priority_desc = 'High Priority ';
                 								break;
                 							case PRIORITY_HIGHEST:
                 								$priority_desc = 'Highest Priority ';
                 								break;
                 							default:
                 								$priority_desc = '';
                 						}
                 						$add_to_subject .= $priority_desc . 'Action Request';
                 						
                 					}
                 					if ($flag_fyi=='1'){
                 						if (!empty($add_to_subject)){
                 							$add_to_subject .= '/';
                 						}
                 						$add_to_subject .= 'FYI';
                 						$body = '<a href="' . assemble_url('project_comment_fyi_read', array('project_id' => $info['project_id'], 'comment_id' => $replacements['comment_id'])) . '">Mark this FYI Notification as Read</a>' . "<br>\n" . $body;
                 					}
                 					if (!empty($add_to_subject)){
                 						$add_to_subject .= ' - ';
                 					}
                 				}
                 				mysql_close($link);
                 	            $subject =  $add_to_subject . $subject;
                 }
                 //EOF:mod
                 //BOF:mod 20111101
                 */
                 //EOF:mod 20111101
                 //BOF:mod 20111110 #493
                 if ($tpl == 'resources/new_comment') {
                     $subject .= ' [CID' . $replacements['comment_id'] . ']';
                 }
                 //EOF:mod 20111110 #493
                 event_trigger('on_prepare_email', array($tpl, $recipient_email, $context, &$body, &$subject, &$attachments, &$language, $replacements['subscribers_name']));
                 // if files need to be attached, message will be multipart
                 if (is_foreachable($attachments)) {
                     $message = new Swift_Message($subject);
                     $message->attach(new Swift_Message_Part($body, 'text/html', EMAIL_ENCODING, EMAIL_CHARSET));
                     foreach ($attachments as $attachment) {
                         $file_path = array_var($attachment, 'path', null);
                         if (file_exists($file_path)) {
                             $message->attach(new Swift_Message_Attachment(new Swift_File($file_path), array_var($attachment, 'name', basename($file_path)), array_var($attachment, 'mime_type', mime_content_type($file_path))));
                         }
                     }
                     // if
                 } else {
                     $message = new Swift_Message($subject, $body, 'text/html', EMAIL_ENCODING, EMAIL_CHARSET);
                 }
                 // if
                 // Load values...
                 if ($mark_as_bulk === null || $empty_return_path === null) {
                     $mark_as_bulk = (bool) ConfigOptions::getValue('mailing_mark_as_bulk');
                     $empty_return_path = (bool) ConfigOptions::getValue('mailing_empty_return_path');
                 }
                 // if
                 // Custom headers (to prevent auto responders)
                 if ($mark_as_bulk) {
                     $message->headers->set('Auto-Submitted', 'auto-generated');
                     $message->headers->set('Precedence', 'bulk');
                 }
                 // if
                 if ($empty_return_path) {
                     $message->headers->set('Return-Path', '<>');
                 } else {
                     $message->headers->set('Return-Path', "<{$from_email}>");
                 }
                 // if
                 if (!isset($to_send[$locale])) {
                     $to_send[$locale] = array('recipients' => new Swift_RecipientList(), 'message' => $message);
                 }
                 //BOF:mod
                 //BOF:mod 20111101
                 /*
                 //EOF:mod 20111101
                 if ($tpl=='resources/new_comment'){
                     $to_send[$locale]['modified_subject'][$recipient_email] =  $subject;
                 }
                 //BOF:mod 20111101
                 */
                 //EOF:mod 20111101
                 //EOF:mod
                 $to_send[$locale]['recipients']->add($recipient_email, $recipient_name);
             }
             // if
         }
         // foreach
         if (is_foreachable($to_send)) {
             foreach ($to_send as $locale => $message_data) {
                 //BOF:mod 20111101
                 /*
                 //EOF:mod 20111101
                 $this->swift->batchSend($message_data['message'], $message_data['recipients'], new Swift_Address($from_email, $from_name), $message_data['modified_subject']);
                 //BOF:mod 20111101
                 */
                 $this->swift->batchSend($message_data['message'], $message_data['recipients'], new Swift_Address($from_email, $from_name));
                 //EOF:mod 20111101
             }
             // foreach
         }
         // if
         return true;
     } else {
         $instance =& ApplicationMailer::instance();
         return $instance->send($to, $tpl, $replacements, $context, $attachments);
     }
     // if
 }
 public function testBatchSendingDoesNotCopyAllRecipientsInOnASingleEmail()
 {
     //Most of this test has been removed due to complexity working out when the commands when be issued. Sorry.
     $conn = new FullMockConnection();
     $conn->setReturnValueAt(0, "read", "220 xxx ESMTP");
     $conn->setReturnValueAt(1, "read", "250-Hello xxx\r\n250 HELP");
     $conn->setReturnValueAt(2, "read", "250 Ok");
     $conn->setReturnValueAt(3, "read", "250 Ok");
     $conn->setReturnValueAt(4, "read", "354 Go ahead");
     $conn->setReturnValueAt(5, "read", "250 ok");
     $conn->setReturnValueAt(6, "read", "250 Ok");
     $conn->setReturnValueAt(7, "read", "250 Ok");
     $conn->setReturnValueAt(8, "read", "354 Go ahead");
     $conn->setReturnValueAt(9, "read", "250 ok");
     $message = new Swift_Message("My Subject", "my body");
     $message->setEncoding("8bit");
     $swift = new Swift($conn, "abc", Swift::ENABLE_LOGGING);
     $recipients = new Swift_RecipientList();
     $recipients->addTo("*****@*****.**", "XXX YYY");
     $recipients->addTo("*****@*****.**");
     $this->assertEqual(2, $swift->batchSend($message, $recipients, new Swift_Address("*****@*****.**", "Foo Bar")));
 }