Esempio n. 1
0
 /**
  * Returns the transport with the server/auth information from the specified
  * account, along with the configuration's smtp client name for using when
  * helo'ing the mail server.
  *
  * @param Conjoon_Modules_Groupware_Email_Account $account The account for
  *        which the transport should be returned
  *
  * @return Conjoon\Mail\Transport\Smtp
  */
 protected function getTransportForAccount(\Conjoon_Modules_Groupware_Email_Account $account)
 {
     $regCon = $this->getApplicationConfiguration();
     $clientName = $regCon->application->mail->smtp->client_name;
     $config = array();
     if ($account->isOutboxAuth()) {
         $config = array('name' => $clientName, 'auth' => 'login', 'username' => $account->getUsernameOutbox(), 'password' => $account->getPasswordOutbox(), 'port' => $account->getPortOutbox());
         $ssl = $account->getOutboxConnectionType();
         if ($ssl == 'SSL' || $ssl == 'TLS') {
             $config['ssl'] = $ssl;
         }
     }
     /**
      * @see \Conjoon\Mail\Transport\Smtp
      */
     require_once 'Conjoon/Mail/Transport/Smtp.php';
     return new \Conjoon\Mail\Transport\Smtp($account->getServerOutbox(), $config);
 }
Esempio n. 2
0
 /**
  * Saves a sent email into the database.
  *
  * @param Conjoon_Modules_Groupware_Email_Draft $message
  * @param Conjoon_Modules_Groupware_Email_Account $account
  * @param integer $userId
  * @param Conjoon_Mail_Sent $mailSent
  * @param string $type
  * @param integer $referencesId The id of the email that was refernced sending this
  * message. This argument will only be taken into account if $type euqals to
  * reply or reply_all
  * @param array $postedAttachments
  * @param array $removeAttachmentIds
  *
  * @return array the data from groupware_email_item associated with
  * the newly saved entry
  */
 public function saveSentEmail(Conjoon_Modules_Groupware_Email_Draft $message, Conjoon_Modules_Groupware_Email_Account $account, $userId, Conjoon_Mail_Sent $mailSent, $type = "", $referencesId = -1, $postedAttachments = array(), $removeAttachmentIds = array())
 {
     $mail = $mailSent->getMailObject();
     $userId = (int) $userId;
     $accountId = (int) $account->getId();
     $messageId = (int) $message->getId();
     $referenceId = $referencesId <= 0 ? 0 : $referencesId;
     if ($userId <= 0 || $accountId <= 0) {
         return array();
     }
     $referencesModel = new Conjoon_Modules_Groupware_Email_Item_Model_References();
     $emailRecipientsFilter = new Conjoon_Filter_EmailRecipients();
     $emailRecipientsToStringFilter = new Conjoon_Filter_EmailRecipientsToString();
     $outboxModel = new Conjoon_Modules_Groupware_Email_Item_Model_Outbox();
     $folderModel = new Conjoon_Modules_Groupware_Email_Folder_Model_Folder();
     // first check the folder type of the email
     $folderId = $message->getGroupwareEmailFoldersId();
     $messageType = 'scratch';
     // negative/0, means the message was created from draft
     if ($folderId <= 0) {
         $messageType = 'scratch';
     } else {
         // anything else needs the meta info type fetched out of the folder model
         $metaInfo = $folderModel->getMetaInfo($folderId);
         switch ($metaInfo) {
             case Conjoon_Modules_Groupware_Email_Folder_Model_Folder::META_INFO_OUTBOX:
                 $messageType = 'outbox';
                 break;
             case Conjoon_Modules_Groupware_Email_Folder_Model_Folder::META_INFO_DRAFT:
                 $messageType = 'draft';
                 break;
                 // anything else is probably a reply or forward to an existing message in any other
                 // folder
             // anything else is probably a reply or forward to an existing message in any other
             // folder
             default:
                 $messageType = 'scratch';
                 break;
         }
     }
     // adjust the message type depending on the type
     if ($type == 'reply' || $type == 'reply_all' || $type == 'forward') {
         $messageType = 'scratch';
     }
     // prefill update/insert arrays
     $sentFolderId = $folderModel->getSentFolder($accountId, $userId);
     $date = new Zend_Date($mail->getDate(), Zend_Date::RFC_2822);
     $replyTo = (string) $mail->getReplyTo();
     $to = $message->getTo();
     $cc = $message->getCc();
     $bcc = $message->getBcc();
     $fromAddress = new Conjoon_Modules_Groupware_Email_Address(array($account->getAddress(), $account->getUserName()));
     $toString = array();
     foreach ($to as $recipient) {
         $toString[] = $recipient->__toString();
     }
     $toString = implode(', ', $toString);
     $ccString = array();
     foreach ($cc as $recipient) {
         $ccString[] = $recipient->__toString();
     }
     $ccString = implode(', ', $ccString);
     $bccString = array();
     foreach ($bcc as $recipient) {
         $bccString[] = $recipient->__toString();
     }
     $bccString = implode(', ', $bccString);
     $outboxUpdate = array('sent_timestamp' => time(), 'raw_header' => $mailSent->getSentHeaderText(), 'raw_body' => $mailSent->getSentBodyText(), 'groupware_email_accounts_id' => $message->getGroupwareEmailAccountsId());
     /**
      * @see Conjoon_Filter_DateToUtc
      */
     require_once 'Conjoon/Filter/DateToUtc.php';
     $filterToUtc = new Conjoon_Filter_DateToUtc();
     $itemUpdate = array('reply_to' => $replyTo, 'from' => $fromAddress->__toString(), 'recipients' => $emailRecipientsToStringFilter->filter($emailRecipientsFilter->filter(array($toString, $ccString, $bccString))), 'sender' => $emailRecipientsToStringFilter->filter($emailRecipientsFilter->filter(array($fromAddress->__toString()))), 'groupware_email_folders_id' => $sentFolderId, 'date' => $filterToUtc->filter($date->get(Zend_Date::ISO_8601)));
     switch ($messageType) {
         // if the message was sent from an opened draft or from the outbox,
         // we simply can create a new entry in the tables,
         // as if it was created from scratch
         // if, however, the email was sent from drafts, a user might have updated
         // the addresses, the subject, the email text and the attachments.
         // those fields have to be updated in the datastorage as well
         case 'draft':
             Conjoon_Util_Array::apply($itemUpdate, array('subject' => $message->getSubject(), 'to' => $toString, 'cc' => $ccString, 'bcc' => $bccString, 'content_text_plain' => $message->getContentTextPlain(), 'content_text_html' => $message->getContentTextHtml()));
             $this->saveAttachmentsForDraft($message, $postedAttachments, $removeAttachmentIds);
             // most simple: mesageType is outbox which means we have simply to update a few fields
         // most simple: mesageType is outbox which means we have simply to update a few fields
         case 'outbox':
             if ($messageId <= 0 || $sentFolderId == 0) {
                 return array();
             }
             // the message might have referenced an item when it was created.
             // look up entry in reference table and set this to is_pending = false
             $referencesWhere = $referencesModel->getAdapter()->quoteInto('groupware_email_items_id = ?', $messageId) . ' AND ' . $referencesModel->getAdapter()->quoteInto('user_id = ?', $userId);
             $referencesModel->update(array('is_pending' => 0), $referencesWhere);
             $outboxWhere = $outboxModel->getAdapter()->quoteInto('groupware_email_items_id = ?', $messageId);
             $outboxModel->update($outboxUpdate, $outboxWhere);
             $itemWhere = $this->getAdapter()->quoteInto('id = ?', $messageId);
             $this->update($itemUpdate, $itemWhere);
             return $this->getItemForUser($messageId, $userId);
             break;
             // if the message was created from scratch, i.e. has no id and no folderId,
             // save a fresh row into the tables groupware_email_items_id, groupware_email_items_flags,
             // groupware_email_items_outbox
         // if the message was created from scratch, i.e. has no id and no folderId,
         // save a fresh row into the tables groupware_email_items_id, groupware_email_items_flags,
         // groupware_email_items_outbox
         case 'scratch':
             Conjoon_Util_Array::apply($itemUpdate, array('subject' => $message->getSubject(), 'to' => $toString, 'cc' => $ccString, 'bcc' => $bccString, 'in_reply_to' => $message->getInReplyTo(), 'references' => $message->getReferences(), 'content_text_plain' => $message->getContentTextPlain(), 'content_text_html' => $message->getContentTextHtml()));
             $messageId = (int) $this->insert($itemUpdate);
             if ($messageId <= 0) {
                 return array();
             }
             $flagModel = new Conjoon_Modules_Groupware_Email_Item_Model_Flag();
             $referenceType = '';
             if (($type == Conjoon_Modules_Groupware_Email_Keys::REFERENCE_TYPE_REPLY || $type == Conjoon_Modules_Groupware_Email_Keys::REFERENCE_TYPE_REPLY_ALL || $type == Conjoon_Modules_Groupware_Email_Keys::REFERENCE_TYPE_FORWARD) && $referenceId != 0) {
                 $referenceType = $type;
                 $referenceUpdate = array('groupware_email_items_id' => $messageId, 'user_id' => $userId, 'reference_items_id' => $referenceId, 'reference_type' => $referenceType);
                 $referencesModel->insert($referenceUpdate);
             }
             $flagUpdate = array('groupware_email_items_id' => $messageId, 'user_id' => $userId, 'is_read' => 1, 'is_spam' => 0, 'is_deleted' => 0);
             $flagModel->insert($flagUpdate);
             Conjoon_Util_Array::apply($outboxUpdate, array('groupware_email_items_id' => $messageId));
             $outboxModel->insert($outboxUpdate);
             $message->setId($messageId);
             $this->saveAttachmentsForDraft($message, $postedAttachments, $removeAttachmentIds);
             return $this->getItemForUser($messageId, $userId);
             break;
     }
     return null;
 }
Esempio n. 3
0
 /**
  * @param int $userId The id of the user to process the email-accounts for.
  * @param int $accountId The id of the account to fetch the emails for
  *
  * @return Array An associative array with the keys of the fetched and saved
  * emails in the array 'fetched', and error-messages in the key 'errors'.
  */
 private function _fetchEmails($userId, Conjoon_Modules_Groupware_Email_Account $account)
 {
     $fetchedEmailIds = array();
     $fetchedEmailErrors = array();
     $userId = (int) $userId;
     if ($userId <= 0) {
         return $fetchedEmailIds;
     }
     $transports = array(Conjoon_Modules_Groupware_Email_Account::PROTOCOL_POP3 => "Conjoon_Mail_Storage_Pop3", Conjoon_Modules_Groupware_Email_Account::PROTOCOL_IMAP => "Conjoon_Mail_Storage_Imap");
     self::_setIconvEncoding(self::ICONV_UTF_8);
     $accountId = $account->getId();
     $transport = $transports[$account->getProtocol()];
     $isPop3 = $account->getProtocol() == Conjoon_Modules_Groupware_Email_Account::PROTOCOL_POP3;
     $isCopyLeftOnServer = $account->isCopyLeftOnServer();
     $cconf = array('host' => $account->getServerInbox(), 'port' => $account->getPortInbox(), 'user' => $account->getUsernameInbox(), 'password' => $account->getPasswordInbox());
     $ssl = $account->getInboxConnectionType();
     if ($ssl == 'SSL' || $ssl == 'TLS') {
         $cconf['ssl'] = $ssl;
     }
     $mail = new $transport($cconf);
     $hasUniqueId = $mail->hasUniqueId;
     $mailCount = count($mail);
     if ($hasUniqueId) {
         $uidl = $mail->getUniqueId();
         $this->_cacheUidl($uidl, $accountId, $this->_computeChunkSize($mailCount));
         // this is to prevent undefined indexes when the count of uidl
         // differs from the number of emails fetched. This is a very rare error
         // that occures now and then - see http://wiki.conjoon.org/ticket/189
         // it's assumed its related to connection aborts during communication
         // with the mail server
         if (count($uidl) != $mailCount) {
             return array('fetched' => $fetchedEmailIds, 'errors' => array('Could not retrieve messages - number of items in unique id list ' . 'differs from total number of emails on the server: ' . 'Number of unique ids: ' . count($uidl) . '; number of messages: ' . $mailCount . '; ' . 'This is possibly related to a connection abort while attempting to fetch ' . 'messages from a server. Please try again.'));
         }
     }
     $messagesToRemove = array();
     for ($oo = 1; $oo < $mailCount + 1; $oo++) {
         $messageNum = $oo;
         $this->_attachmentCounter = 1;
         $emailItem = array();
         $rawHeader = "";
         $rawBody = "";
         // check if the account supports UIDL, and skip the message
         // if it is already available in the db
         if ($hasUniqueId) {
             if ($this->_isUidPresent($accountId, $uidl[$oo]) === true) {
                 if (!$isCopyLeftOnServer && $isPop3) {
                     $messagesToRemove[] = $messageNum;
                 }
                 continue;
             } else {
                 $emailItem['uid'] = $uidl[$oo];
             }
         }
         // check here if we can process the message, taking memory limit
         // of php ini into account
         if (!$this->_maxMemory) {
             $this->_maxMemory = Conjoon_Util_Format::convertToBytes(ini_get('memory_limit'));
         }
         $s = $mail->getSize($messageNum);
         if ($s == 0) {
             $fetchedEmailErrors[] = 'Could not save message No. ' . $messageNum . ' - message size seems to be 0 bytes';
             continue;
         }
         if ($this->_maxMemory / $s <= 17) {
             $fetchedEmailErrors[] = 'Could not save message No. ' . $messageNum . ' - message could exceed available memory size (' . $this->_maxMemory . ' bytes, message size ' . $s . ').';
             continue;
         }
         self::_splitMessage($mail->getRawMessage($messageNum), $rawHeader, $rawBody);
         $message = new Conjoon_Mail_Message(array('headers' => $rawHeader, 'noToplines' => true, 'content' => $rawBody));
         $messageId = "";
         try {
             $messageId = $message->messageId;
         } catch (Zend_Mail_Exception $e) {
             // ignore
         }
         $emailItem['messageId'] = $messageId;
         $mail->noop();
         // check here if we can remove the mail from the server
         // check first if UIDL is supported. if not, look up the
         // message
         if (!$hasUniqueId) {
             $id = $this->_isMessageIdPresent($messageId, $accountId, $rawHeader, $rawBody);
             $mail->noop();
             if ($id === true) {
                 if (!$isCopyLeftOnServer && $isPop3) {
                     $messagesToRemove[] = $messageNum;
                 }
                 continue;
             }
         } else {
             if (!$isCopyLeftOnServer && $isPop3) {
                 $messagesToRemove[] = $messageNum;
             }
         }
         $mail->noop();
         $emailItem['attachments'] = array();
         $emailItem['userId'] = $userId;
         try {
             $emailItem['from'] = $message->from;
         } catch (Zend_Mail_Exception $e) {
             // may be changed to localized header values by anti vir programs
             try {
                 $emailItem['from'] = $message->von;
             } catch (Zend_Mail_Exception $e) {
                 $emailItem['from'] = "-";
             }
         }
         if (!isset($emailItem['from'])) {
             throw new Zend_Mail_Exception("No header with the name \"from\" found. Please check if you have an anti virus program runnning in the background. Some are known to change the header values to localized derivates.");
         }
         $emailItem['subject'] = "";
         // very few emails will come in without a subject.
         try {
             $emailItem['subject'] = $message->subject;
         } catch (Zend_Mail_Exception $e) {
             try {
                 // may be changed to localized header values by anti vir programs
                 $emailItem['subject'] = $message->betreff;
             } catch (Zend_Mail_exception $e) {
                 // ignore
             }
         } catch (Zend_Mail_exception $e) {
             // ignore
         }
         $emailItem['date'] = "";
         // date field will be given presedence
         try {
             $emailItem['date'] = $message->date;
         } catch (Zend_Mail_Exception $e) {
             // ignore
         }
         // if date not found, look up deliveryDate
         if (!$emailItem['date']) {
             try {
                 $emailItem['date'] = $message->deliveryDate;
             } catch (Zend_Mail_Exception $e) {
                 // ignore
             }
             if (!$emailItem['date']) {
                 try {
                     // may be changed to localized header values by anti vir programs
                     $emailItem['date'] = $message->datum;
                 } catch (Zend_Mail_Exception $e) {
                     // ignore
                 }
                 // and one further down to fall back to actual
                 // date if none was found
                 if (!$emailItem['date']) {
                     /**
                      * @see Zend_Date
                      */
                     require_once 'Zend/Date.php';
                     $zd = new Zend_Date();
                     $emailItem['date'] = $zd->get(Zend_Date::RFC_2822);
                 }
             }
         }
         try {
             $emailItem['to'] = $message->to;
         } catch (Zend_Mail_Exception $e) {
             // "to" might not be used, instead "cc" will be probably available
             // then
             $emailItem['to'] = "";
         }
         if (!$emailItem['to']) {
             try {
                 // may be changed to localized header values by anti vir programs
                 $emailItem['to'] = $message->an;
             } catch (Zend_Mail_Exception $e) {
                 // ignore
             }
         }
         try {
             $emailItem['cc'] = $message->cc;
         } catch (Zend_Mail_Exception $e) {
             $emailItem['cc'] = '';
         }
         try {
             $emailItem['references'] = $message->references;
         } catch (Zend_Mail_Exception $e) {
             $emailItem['references'] = '';
         }
         try {
             $emailItem['replyTo'] = $message->replyTo;
         } catch (Zend_Mail_Exception $e) {
             $emailItem['replyTo'] = '';
         }
         try {
             $emailItem['inReplyTo'] = $message->inReplyTo;
         } catch (Zend_Mail_Exception $e) {
             $emailItem['inReplyTo'] = '';
         }
         $encodingInformation = $this->_getEncodingInformation($message);
         $contentType = $encodingInformation['contentType'];
         $mail->noop();
         try {
             switch ($contentType) {
                 case 'text/plain':
                     $emailItem['contentTextPlain'] = $this->_decode($message->getContent(), $encodingInformation);
                     break;
                 case 'text/html':
                     $emailItem['contentTextHtml'] = $this->_decode($message->getContent(), $encodingInformation);
                     break;
                 case 'multipart/mixed':
                     $this->_parseMultipartMixed($message, $emailItem);
                     break;
                 case 'multipart/alternative':
                     $this->_parseMultipartAlternative($message, $emailItem);
                     break;
                 case 'multipart/related':
                     $this->_parseMultipartRelated($message, $emailItem);
                     break;
                 case 'multipart/signed':
                     $this->_parseMultipartSigned($message, $emailItem);
                     break;
                 case 'multipart/report':
                     $this->_parseMultipartReport($message, $emailItem);
                     break;
                 default:
                     $emailItem['contentTextPlain'] = $this->_decode($message->getContent(), $encodingInformation);
                     break;
             }
         } catch (Exception $e) {
             $fetchedEmailErrors[] = "Could not save message No. " . $messageNum . " with the subject \"" . $emailItem['subject'] . "\". " . "An unexpected error occurred: \"" . $e->getMessage() . "\"";
             $mail->noop();
             continue;
         }
         $mail->noop();
         if (!isset($emailItem['contentTextPlain'])) {
             $emailItem['contentTextPlain'] = '';
         }
         if (!isset($emailItem['contentTextHtml'])) {
             $emailItem['contentTextHtml'] = '';
         }
         $this->_assignJunkStatus($userId, $emailItem);
         $this->_assignFolderId($userId, $accountId, $emailItem);
         $emailItem['rawHeader'] =& $rawHeader;
         $emailItem['rawBody'] =& $rawBody;
         $mail->noop();
         if (!$emailItem['messageId']) {
             $emailItem['hash'] = Conjoon_Modules_Groupware_Email_Item_Model_Inbox::computeMessageHash($rawHeader, $rawBody);
         }
         $mail->noop();
         $saved = $this->_saveEmail($emailItem, $userId);
         $mail->noop();
         if (is_int($saved) > 0) {
             $fetchedEmailIds[] = $saved;
         } else {
             $fetchedEmailErrors[] = "Could not save Email Message with the " . " subject \"" . $emailItem['subject'] . "\"" . ", date \"" . $emailItem['date'] . "\"" . ": " . $saved;
             continue;
         }
         $mail->noop();
         if (!$isCopyLeftOnServer && $isPop3) {
             $messagesToRemove[] = $messageNum;
         }
     }
     $messagesToRemove = array_unique($messagesToRemove);
     foreach ($messagesToRemove as $id) {
         $mail->removeMessage($id);
     }
     self::_setIconvEncoding(self::ICONV_OLD);
     return array('fetched' => $fetchedEmailIds, 'errors' => $fetchedEmailErrors);
 }