/**
  * the constructor
  * 
  * creates instance of Expressomail_Backend_Imap with parameters
  * Supported parameters are
  *   - user username
  *   - host hostname or ip address of IMAP server [optional, default = 'localhost']
  *   - password password for user 'username' [optional, default = '']
  *   - port port for IMAP server [optional, default = 110]
  *   - ssl 'SSL' or 'TLS' for secure sockets
  *   - folder select this folder [optional, default = 'INBOX']
  *
  * @param  array $params mail reader specific parameters
  * @throws Expressomail_Exception_IMAPInvalidCredentials
  * @return void
  */
 public function __construct($params, $_readOnly = FALSE)
 {
     if (is_array($params)) {
         $params = (object) $params;
     }
     if (!isset($params->user)) {
         throw new Expressomail_Exception_IMAPInvalidCredentials('Need at least user in params.');
     }
     $params->host = isset($params->host) ? $params->host : 'localhost';
     $params->password = isset($params->password) ? $params->password : '';
     $params->port = isset($params->port) ? $params->port : null;
     $params->ssl = isset($params->ssl) ? $params->ssl : false;
     $this->_params = $params;
     $expressomailConfig = Expressomail_Config::getInstance();
     $imapBackendConfigDefinition = $expressomailConfig->getDefinition(Expressomail_Config::IMAPBACKEND);
     $backendClassName = self::$_availableBackends[$imapBackendConfigDefinition['default']];
     $expressomailSettings = $expressomailConfig->get(Expressomail_Config::EXPRESSOMAIL_SETTINGS);
     $backendName = isset($expressomailSettings[Expressomail_Config::IMAPBACKEND]) ? $expressomailSettings[Expressomail_Config::IMAPBACKEND] : $imapBackendConfigDefinition['default'];
     if ($backendName != $imapBackendConfigDefinition['default']) {
         if (Tinebase_Helper::checkClassExistence(self::$_availableBackends[$backendName], true) && Tinebase_Helper::checkSubClassOf(self::$_availableBackends[$backendName], 'Expressomail_Backend_Imap_Interface', true)) {
             $backendClassName = self::$_availableBackends[$backendName];
         }
     }
     $this->_backend = new $backendClassName($params, $_readOnly);
 }
 /**
  * factory function to return a selected account/imap backend class
  *
  * @param   string|Expressomail_Model_Account $_accountId
  * @return  Expressomail_Backend_Sieve
  */
 public static function factory($_accountId)
 {
     $accountId = $_accountId instanceof Expressomail_Model_Account ? $_accountId->getId() : $_accountId;
     if (!isset(self::$_backends[$accountId])) {
         $account = $_accountId instanceof Expressomail_Model_Account ? $_accountId : Expressomail_Controller_Account::getInstance()->get($accountId);
         // get imap config from account to connect with sieve server
         $sieveConfig = $account->getSieveConfig();
         // we need to instantiate a new sieve backend
         if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
             Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Connecting to server ' . $sieveConfig['host'] . ':' . $sieveConfig['port'] . ' (secure: ' . (array_key_exists('ssl', $sieveConfig) && $sieveConfig['ssl'] !== FALSE ? $sieveConfig['ssl'] : 'none') . ') with user ' . $sieveConfig['username']);
         }
         $expressomailConfig = Expressomail_Config::getInstance();
         $sieveBackendDefinition = $expressomailConfig->getDefinition(Expressomail_Config::SIEVEBACKEND);
         $backendClassName = self::$_availableBackends[$sieveBackendDefinition['default']];
         $expressomailSettings = $expressomailConfig->get(Expressomail_Config::EXPRESSOMAIL_SETTINGS);
         $backendName = isset($expressomailSettings[Expressomail_Config::SIEVEBACKEND]) ? $expressomailSettings[Expressomail_Config::SIEVEBACKEND] : $sieveBackendDefinition['default'];
         if ($sieveBackendName != $sieveBackendDefinition['default']) {
             if (Tinebase_Helper::checkClassExistence(self::$_availableBackends[$backendName], true)) {
                 $backendClassName = self::$_availableBackends[$backendName];
             }
         }
         self::$_backends[$accountId] = new $backendClassName($sieveConfig);
     }
     return self::$_backends[$accountId];
 }
 /**
  * init config settings
  * - save default values at database
  * - based from the code of class Addressbook_Setup_Initialize
  * (non-PHPdoc) @see tine20/Addressbook/Setup/Initialize::setDefaultInternalAddressbook()
  */
 protected function _initializeConfig()
 {
     $properties = Expressomail_Config::getProperties();
     $property_imapSearchMaxResults = $properties[Expressomail_Config::IMAPSEARCHMAXRESULTS];
     $default_value_imapSearchMaxResults = $property_imapSearchMaxResults['default'];
     $config = array(Expressomail_Config::IMAPSEARCHMAXRESULTS => $default_value_imapSearchMaxResults);
     $property_autoSaveDraftsInterval = $properties[Expressomail_Config::AUTOSAVEDRAFTSINTERVAL];
     $default_value_autoSaveDraftsInterval = $property_autoSaveDraftsInterval['default'];
     $config[Expressomail_Config::AUTOSAVEDRAFTSINTERVAL] = $default_value_autoSaveDraftsInterval;
     $property_reportPhishingEmail = $properties[Expressomail_Config::REPORTPHISHINGEMAIL];
     $default_value_reportPhishingEmail = $property_reportPhishingEmail['default'];
     $config[Expressomail_Config::REPORTPHISHINGEMAIL] = $default_value_reportPhishingEmail;
     Expressomail_Controller::getInstance()->saveConfigSettings($config);
 }
 /**
  * send one message through smtp
  *
  * @param Expressomail_Model_Message $_message
  * @return Expressomail_Model_Message
  */
 public function sendMessage(Expressomail_Model_Message $_message)
 {
     if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
         Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Sending message with subject ' . $_message->subject . ' to ' . print_r($_message->to, TRUE));
     }
     if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) {
         Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' ' . print_r($_message->toArray(), TRUE));
     }
     // increase execution time (sending message with attachments can take a long time)
     $oldMaxExcecutionTime = Tinebase_Core::setExecutionLifeTime(300);
     // 5 minutes
     $account = Expressomail_Controller_Account::getInstance()->get($_message->account_id);
     $this->_resolveOriginalMessage($_message);
     $mail = $this->createMailForSending($_message, $account);
     date_default_timezone_set(Tinebase_Core::getUserTimezone());
     //fetch date header to use GMT
     $this->_sendMailViaTransport($mail, $account, $_message, true);
     // get an array with all recipients
     $recipients = $this->_getRecipients($_message);
     $nonPrivateRecipients = array_merge($recipients['to'], $recipients['cc']);
     $allRecipients = array_merge($recipients['bcc'], $nonPrivateRecipients);
     $config = Tinebase_Core::getConfig();
     $maxRecipients = Expressomail_Config::getInstance()->get(Expressomail_Config::MAX_CONTACT_ADD_TO_UNKNOWN);
     if (isset($config->email->maxContactAddToUnknown)) {
         $maxRecipients = $config->email->maxContactAddToUnknown;
     }
     if (count($allRecipients) <= $maxRecipients && $_message->add_contacts) {
         Tinebase_Core::getLogger()->debug(__METHOD__ . ' Starting search and import of ' . count($allRecipients) . ' contacts');
         $_message->added_contacts = $this->_saveUnknownContacts($account->user_id, $allRecipients);
         Tinebase_Core::getLogger()->debug(__METHOD__ . ' Search and import completed, ' . $_message->added_contacts . ' where added');
     }
     if ($_message->note) {
         // save note to contacts
         $this->_addEmailNote($nonPrivateRecipients, $_message->subject, $_message->getPlainTextBody());
     }
     // reset max execution time to old value
     Tinebase_Core::setExecutionLifeTime($oldMaxExcecutionTime);
     $this->removeTempFiles($_message);
     return $_message;
 }
 /**
  * update to 0.5
  * add Expressomail config parameter AUTOSAVEDRAFTSINTERVAL
  *
  * @return void
  */
 public function update_4()
 {
     $settings = Expressomail_Config::getInstance()->get(Expressomail_Config::EXPRESSOMAIL_SETTINGS);
     if (!array_key_exists(Expressomail_Config::REPORTPHISHINGEMAIL, $settings)) {
         try {
             $properties = Expressomail_Config::getProperties();
             $property = $properties[Expressomail_Config::REPORTPHISHINGEMAIL];
             $default_value = $property['default'];
             $settings[Expressomail_Config::REPORTPHISHINGEMAIL] = $default_value;
             Expressomail_Controller::getInstance()->saveConfigSettings($settings);
         } catch (Tinebase_Exception_NotFound $tenf) {
             // do nothing
         }
     }
     $this->setApplicationVersion('Expressomail', '0.5');
 }
 /**
  * save Expressomail settings
  *
  * @param $_settings: array of tuples [parameter -> value]
  * @return array of [parameter -> value]
  *
  * @todo generalize this
  */
 public function saveConfigSettings($_settings)
 {
     if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
         Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Updating Expressomail Settings: ' . print_r($_settings, TRUE));
     }
     Expressomail_Config::getInstance()->set(Expressomail_Config::EXPRESSOMAIL_SETTINGS, $_settings);
     return $this->getConfigSettings();
 }
 /**
  * get vacation message from template file
  * 
  * @param string $templateId
  * @return string
  * 
  * @todo generalize and move to Tinebase_FileSystem / Node controller
  */
 protected function _getMessageFromTemplateFile($templateId)
 {
     $template = Tinebase_FileSystem::getInstance()->searchNodes(new Tinebase_Model_Tree_Node_Filter(array(array('field' => 'id', 'operator' => 'equals', 'value' => $templateId))))->getFirstRecord();
     if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) {
         Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' ' . print_r($template->toArray(), TRUE));
     }
     $templateContainer = Tinebase_Container::getInstance()->getContainerById(Expressomail_Config::getInstance()->{Expressomail_Config::VACATION_TEMPLATES_CONTAINER_ID});
     $path = Tinebase_FileSystem::getInstance()->getContainerPath($templateContainer) . '/' . $template->name;
     $templateHandle = Tinebase_FileSystem::getInstance()->fopen($path, 'r');
     $message = stream_get_contents($templateHandle);
     Tinebase_FileSystem::getInstance()->fclose($templateHandle);
     if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) {
         Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' ' . $message);
     }
     return $message;
 }
 /**
  * update to 0.6
  * add Expressomail domain config file parameter ENABLEMAILDIREXPORT
  * add Expressomail table 'expressomail_maildirexport_queue'
  * insert Expressomail applications table new record
  *
  * @return void
  * @throws Tinebase_Exception_NotFound|Tinebase_Exception_Backend_Database|Tinebase_Exception
  */
 public function update_5()
 {
     //Add new setup entry at domain setup configuration file
     $settings = Expressomail_Config::getInstance()->get(Expressomail_Config::EXPRESSOMAIL_SETTINGS);
     if (!array_key_exists(Expressomail_Config::ENABLEMAILDIREXPORT, $settings)) {
         try {
             $properties = Expressomail_Config::getProperties();
             $property = $properties[Expressomail_Config::ENABLEMAILDIREXPORT];
             $defaultValue = $property['default'];
             $settings[Expressomail_Config::ENABLEMAILDIREXPORT] = $defaultValue;
             Expressomail_Controller::getInstance()->saveConfigSettings($settings);
             Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' ExpressoMail upgrade to 0.6 successfully added new entry at domain configuration file: "' . $settings[Expressomail_Config::ENABLEMAILDIREXPORT] . '"');
         } catch (Tinebase_Exception_NotFound $tenf) {
             Tinebase_Core::getLogger()->error(__METHOD__ . '::' . __LINE__ . ' ExpressoMail upgrade to 0.6 fails to add new domain entry: "' . $settings[Expressomail_Config::ENABLEMAILDIREXPORT] . '"');
         }
     } else {
         Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . ' ExpressoMail upgrade to 0.6 attempted to created a new domain config file entry, but it already exists! "' . Expressomail_Config::ENABLEMAILDIREXPORT . '"');
     }
     //Add table used by queue script for export mail dir data
     $newTable = 'expressomail_backup_scheduler';
     if (!$this->_backend->tableExists($newTable)) {
         try {
             $table = Setup_Backend_Schema_Table_Factory::factory('String', '
                 <table>
                     <name>' . $newTable . '</name>
                     <version>1</version>
                     <declaration>
                         <field>
                             <name>id</name>
                             <type>text</type>
                             <length>40</length>
                             <notnull>true</notnull>
                         </field>
                         <field>
                             <name>account_id</name>
                             <type>text</type>
                             <length>40</length>
                             <notnull>true</notnull>
                         </field>
                         <field>
                             <name>folder</name>
                             <type>text</type>
                             <length>250</length>
                             <notnull>true</notnull>
                         </field>
                         <field>
                             <name>scheduler_time</name>
                             <type>datetime</type>
                             <notnull>true</notnull>
                         </field>
                         <field>
                             <name>start_time</name>
                             <type>datetime</type>
                         </field>
                         <field>
                             <name>end_time</name>
                             <type>datetime</type>
                         </field>
                         <field>
                             <name>status</name>
                             <type>text</type>
                             <length>40</length>
                             <notnull>true</notnull>
                             <default>PENDING</default>
                         </field>
                         <field>
                             <name>is_deleted</name>
                             <type>boolean</type>
                             <default>false</default>
                         </field>
                         <field>
                             <name>deleted_time</name>
                             <type>datetime</type>
                         </field>
                         <field>
                             <name>deleted_by</name>
                             <type>text</type>
                             <length>40</length>
                         </field>
                         <field>
                             <name>priority</name>
                             <type>integer</type>
                             <notnull>true</notnull>
                             <default>5</default>
                         </field>
                         <field>
                             <name>expunged_time</name>
                             <type>datetime</type>
                         </field>
                         <index>
                             <name>id</name>
                             <field>
                                 <name>id</name>
                             </field>
                         </index>
                         <index>
                             <name>account_id</name>
                             <field>
                                 <name>account_id</name>
                             </field>
                         </index>
                         <index>
                             <name>folder</name>
                             <field>
                                 <name>folder</name>
                             </field>
                         </index>
                         <index>
                             <name>status</name>
                             <field>
                                 <name>status</name>
                             </field>
                         </index>
                         <index>
                             <name>scheduler_time</name>
                             <field>
                                 <name>scheduler_time</name>
                             </field>
                         </index>
                         <index>
                             <name>is_deleted</name>
                             <field>
                                 <name>is_deleted</name>
                             </field>
                         </index>
                         <index>
                             <name>priority</name>
                             <field>
                                 <name>priority</name>
                             </field>
                         </index>
                         <index>
                             <name>id</name>
                             <primary>true</primary>
                             <field>
                                 <name>id</name>
                             </field>
                         </index>
                         <index>
                             <name>account_id--folder--status--is_deleted</name>
                             <unique>true</unique>
                             <field>
                                 <name>account_id</name>
                             </field>
                             <field>
                                 <name>folder</name>
                             </field>
                             <field>
                                 <name>status</name>
                             </field>
                             <field>
                                 <name>is_deleted</name>
                             </field>
                         </index>
                         <index>
                             <name>' . $newTable . '::account_id--accounts::id</name>
                             <field>
                                 <name>account_id</name>
                             </field>
                             <foreign>true</foreign>
                             <reference>
                                 <table>accounts</table>
                                 <field>id</field>
                                 <ondelete>CASCADE</ondelete>
                             </reference>
                         </index>
                     </declaration>
                 </table>
             ');
             $this->_backend->createTable($table);
             Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' ExpressoMail upgrade 0.6 successfully created a new table at data base schema: "' . $newTable . '"');
             //Insert new Expressomail application table record
             try {
                 //Fetch application id to perform insert operation
                 $selectId = $this->_db->select()->from(SQL_TABLE_PREFIX . 'applications', 'id')->where($this->_db->quoteIdentifier('name') . ' = ?', 'Expressomail');
                 $resultId = $this->_db->fetchAll($selectId);
                 $appId = $resultId[0]["id"];
                 //Check basic data consistence at table application
                 if (count($resultId) != 1) {
                     Tinebase_Core::getLogger()->error(__METHOD__ . '::' . __LINE__ . ' ExpressoMail upgrade to 0.6 inconsistent data at applications table for appName "ExpressoMail"');
                     throw new Tinebase_Exception_Backend_Database("Application 'Expressomail' inconsistent data at applications table!");
                 }
                 //Try to find out if some corrupted event have already iserted this data before
                 $selectAppTable = $this->_db->select()->from(SQL_TABLE_PREFIX . 'application_tables', 'name')->where($this->_db->quoteIdentifier('name') . ' = ?', $newTable);
                 $resultAppTable = $this->_db->fetchAll($selectAppTable);
                 if (count($resultAppTable) != 0) {
                     Tinebase_Core::getLogger()->error(__METHOD__ . '::' . __LINE__ . ' ExpressoMail upgrade to 0.6 inconsistent data at applications table for appName "ExpressoMail": the new table "' . $newTable . '" already is there!');
                     throw new Tinebase_Exception_Backend_Database("Application 'Expressomail' inconsistent data at applications table: new table '{$newTable}' relationship already exists at 'application_tables'!");
                 }
                 //Follows to add new record
                 $appRecord = new SimpleXMLElement("\n                                <record>\n                                    <table>\n                                        <name>application_tables</name>\n                                    </table>\n                                    <field>\n                                        <name>application_id</name>\n                                        <value>{$appId}</value>\n                                    </field>\n                                    <field>\n                                        <name>name</name>\n                                        <value>{$newTable}</value>\n                                    </field>\n                                    <field>\n                                        <name>version</name>\n                                        <value>1</value>\n                                    </field>\n                                </record>\n                    ");
                 //Performs insert new record
                 $this->_backend->execInsertStatement($appRecord);
                 Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' ExpressoMail upgrade to 0.6 successfully inserted a new record at "application_tables" table: "' . $newTable . '"');
                 try {
                     //Fetch update action
                     $this->setApplicationVersion('Expressomail', '0.6');
                     Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' ExpressoMail upgrade to 0.6 successfully finished.');
                 } catch (Tinebase_Exception $updateException) {
                     Tinebase_Core::getLogger()->error(__METHOD__ . '::' . __LINE__ . ' ExpressoMail upgrade to 0.6 fails to be up to dated: ' . $updateException->getMessage());
                     throw new Tinebase_Exception_Backend_Database("Application 'Expressomail' fails to update to 0.6 at 'setApplicationVersion':" . $updateException->getMessage());
                 }
             } catch (Tinebase_Exception_Backend_Database $insertAppException) {
                 Tinebase_Core::getLogger()->error(__METHOD__ . '::' . __LINE__ . ' ExpressoMail upgrade to 0.6 fails to insert new applications table: ' . $insertAppException->getMessage());
                 throw new Tinebase_Exception_Backend_Database("Application 'Expressomail' fails to update to 0.6 at insert applicatons table new record:" . $insertAppException->getMessage());
             }
         } catch (Tinebase_Exception_Backend_Database $createException) {
             Tinebase_Core::getLogger()->error(__METHOD__ . '::' . __LINE__ . ' ExpressoMail upgrade to 0.6 fails to create new table: ' . $createException->getMessage());
             throw new Tinebase_Exception_Backend_Database("Application 'Expressomail' fails to update to 0.6 at create new table:" . $createException->getMessage());
         }
     } else {
         Tinebase_Core::getLogger()->error(__METHOD__ . '::' . __LINE__ . ' ExpressoMail upgrade to 0.6 fails to process new table creation: table "' . $newTable . '" already exists at application schema database!');
         throw new Tinebase_Exception_Backend_Database("Application 'Expressomail' fails to update to 0.6: base table '{$newTable}' already exists at database schema!");
     }
 }
 /**
  * Returns instance of Tinebase_Config
  *
  * @return Tinebase_Config
  */
 public static function getInstance()
 {
     if (self::$_instance === NULL) {
         self::$_instance = new self();
     }
     return self::$_instance;
 }
 /**
  * get available vacation message templates
  *
  * @return array
  *
  * @todo perhaps we should use the node controller for the search and move it to tinebase
  */
 public function getVacationMessageTemplates()
 {
     try {
         $templateContainer = Tinebase_Container::getInstance()->getContainerById(Expressomail_Config::getInstance()->{Expressomail_Config::VACATION_TEMPLATES_CONTAINER_ID});
         $path = Tinebase_FileSystem::getInstance()->getContainerPath($templateContainer);
         $parentNode = Tinebase_FileSystem::getInstance()->stat($path);
         $filter = new Tinebase_Model_Tree_Node_Filter(array(array('field' => 'parent_id', 'operator' => 'equals', 'value' => $parentNode->getId())));
         $templates = Tinebase_FileSystem::getInstance()->searchNodes($filter);
         $result = $this->_multipleRecordsToJson($templates, $filter);
     } catch (Exception $e) {
         if (Tinebase_Core::isLogLevel(Zend_Log::WARN)) {
             Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . ' Could not get vacation template files: ' . $e);
         }
         $result = array();
     }
     return array('totalcount' => count($result), 'results' => $result);
 }