public function getProcessedData() { $data = parent::getProcessedData(); if ($this->_context == self::CONTEXT_DELETE || $this->_context == self::CONTEXT_MOVE) { return $data; } $recs = array($data['to'], $data['cc'], $data['bcc']); /** * @see Conjoon_Filter_EmailRecipients */ require_once 'Conjoon/Filter/EmailRecipients.php'; /** * @see Conjoon_Filter_EmailRecipientsToString */ require_once 'Conjoon/Filter/EmailRecipientsToString.php'; $emailRecipientsFilter = new Conjoon_Filter_EmailRecipients(); $emailSenderFilter = new Conjoon_Filter_EmailRecipients(false, false); $emailRecipientsToStringFilter = new Conjoon_Filter_EmailRecipientsToString(); $emailSenderToStringFilter = new Conjoon_Filter_EmailRecipientsToString(false); $data['recipients'] = $emailRecipientsToStringFilter->filter($emailRecipientsFilter->filter($recs)); // it should be safe to store the sender without additional slashes $data['sender'] = $emailSenderToStringFilter->filter($emailSenderFilter->filter($data['from'])); return $data; }
/** * 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; }
/** * Bulk sends emails. Awaits the parameter ids as a numeric array with the ids of * the emails which should get send. * */ public function bulkSendAction() { /*@REMOVE@*/ if (!$this->_helper->connectionCheck()) { /** * @see Conjoon_Error_Factory */ require_once 'Conjoon/Error/Factory.php'; $this->view->success = false; $this->view->sentItems = array(); $this->view->error = null; $this->view->contextReferencedItems = array(); $this->view->error = Conjoon_Error_Factory::createError("Unexpected connection failure while trying to bulk-send emails. " . "Please try again.", Conjoon_Error::LEVEL_WARNING, Conjoon_Error::DATA)->getDto(); return; } /*@REMOVE@*/ $toSend = $_POST['ids']; if ($this->_helper->conjoonContext()->getCurrentContext() == self::CONTEXT_JSON) { require_once 'Zend/Json.php'; $toSend = Zend_Json::decode($toSend, Zend_Json::TYPE_ARRAY); } $date = null; if (isset($_POST['date'])) { require_once 'Conjoon/Filter/DateIso8601.php'; $dateFilter = new Conjoon_Filter_DateIso8601(); $date = $dateFilter->filter((int) $_POST['date']); } /** * @see Conjoon_Filter_EmailRecipients */ require_once 'Conjoon/Filter/EmailRecipients.php'; /** * @see Conjoon_Modules_Groupware_Email_Item_Filter_ItemResponse */ require_once 'Conjoon/Modules/Groupware/Email/Item/Filter/ItemResponse.php'; /** * @see Conjoon_Modules_Groupware_Email_Address */ require_once 'Conjoon/Modules/Groupware/Email/Address.php'; /** * @see Conjoon_Modules_Groupware_Email_Draft */ require_once 'Conjoon/Modules/Groupware/Email/Draft.php'; /** * @see Conjoon_BeanContext_Inspector */ require_once 'Conjoon/BeanContext/Inspector.php'; /** * @see Conjoon_BeanContext_Decorator */ require_once 'Conjoon/BeanContext/Decorator.php'; /** * @see Conjoon_Util_Array */ require_once 'Conjoon/Util/Array.php'; /** * @see Conjoon_Keys */ require_once 'Conjoon/Keys.php'; /** * @see Conjoon_Modules_Groupware_Email_Draft_Model_Draft */ require_once 'Conjoon/Modules/Groupware/Email/Draft/Model/Draft.php'; /** * @see Conjoon_Modules_Groupware_Email_Draft_Filter_DraftInput */ require_once 'Conjoon/Modules/Groupware/Email/Draft/Filter/DraftInput.php'; /** * @see Conjoon_Modules_Groupware_Email_Sender */ require_once 'Conjoon/Modules/Groupware/Email/Sender.php'; $auth = Zend_Registry::get(Conjoon_Keys::REGISTRY_AUTH_OBJECT); $userId = $auth->getIdentity()->getId(); $draftFilter = new Conjoon_Modules_Groupware_Email_Draft_Filter_DraftInput(array(), Conjoon_Filter_Input::CONTEXT_CREATE); $draftModel = new Conjoon_Modules_Groupware_Email_Draft_Model_Draft(); $accountDecorator = new Conjoon_BeanContext_Decorator('Conjoon_Modules_Groupware_Email_Account_Model_Account'); $recipientsFilter = new Conjoon_Filter_EmailRecipients(); $newVersions = array(); $sendItems = array(); $contextReferencedItems = array(); $errors = array(); foreach ($toSend as $pathInfo) { $remoteInfo = array(); $id = $pathInfo['id']; $path = $pathInfo['path']; $account = null; $remoteAttachments = array(); // check if path is remote! $isRemote = $this->isRemotePath($path, $userId); if ($isRemote) { $rawDraft = $this->getRawImapMessage($id, $path); if (empty($rawDraft)) { continue; } //we have to post the existing attachments of the remote draft // again when assembling the message to send. // Otherwise the sender would not know which attachments should get send // along with the message $remoteAttachments = $rawDraft['attachments']; foreach ($remoteAttachments as &$remoteAttachment) { $remoteAttachment['metaType'] = 'emailAttachment'; $remoteAttachment['name'] = $remoteAttachment['fileName']; } $remoteInfo = array('uid' => $id, 'account' => $isRemote, 'path' => $path); $rawDraft['groupwareEmailAccountsId'] = $isRemote->id; $account = $accountDecorator->getAccountAsEntity($rawDraft['groupwareEmailAccountsId'], $userId); } else { $rawDraft = $draftModel->getDraft($id, $userId); $account = $accountDecorator->getAccountAsEntity($rawDraft['groupware_email_accounts_id'], $userId); } // no account found? if (!$account) { /** * @todo think about using the standard account as a fallback or use at last * an error message to inform the user that the account used to write this email * is not available anymore */ continue; } $id = (int) $id; if ($id <= 0) { continue; } if (empty($rawDraft)) { continue; } Conjoon_Util_Array::camelizeKeys($rawDraft); $rawDraft['to'] = $recipientsFilter->filter($rawDraft['to']); $rawDraft['cc'] = $recipientsFilter->filter($rawDraft['cc']); $rawDraft['bcc'] = $recipientsFilter->filter($rawDraft['bcc']); // create the message object here $to = array(); $cc = array(); $bcc = array(); foreach ($rawDraft['cc'] as $dcc) { $add = new Conjoon_Modules_Groupware_Email_Address($dcc); $cc[] = $add; } foreach ($rawDraft['bcc'] as $dbcc) { $add = new Conjoon_Modules_Groupware_Email_Address($dbcc); $bcc[] = $add; } foreach ($rawDraft['to'] as $dto) { $add = new Conjoon_Modules_Groupware_Email_Address($dto); $to[] = $add; } $rawDraft['to'] = $to; $rawDraft['cc'] = $cc; $rawDraft['bcc'] = $bcc; $message = Conjoon_BeanContext_Inspector::create('Conjoon_Modules_Groupware_Email_Draft', $rawDraft, true); if ($date !== null) { $message->setDate($date); } try { $transport = $this->getTransportForAccount($account); $assembleInformation = Conjoon_Modules_Groupware_Email_Sender::getAssembledMail($message, $account, $remoteAttachments, array(), $this->getCurrentAppUser()->getId(), $transport); $assembledMail = $assembleInformation['message']; $postedAttachments = $assembleInformation['postedAttachments']; $mail = Conjoon_Modules_Groupware_Email_Sender::send($assembledMail); } catch (Exception $e) { $errors[] = array('subject' => $message->getSubject(), 'accountName' => $account->getName(), 'reason' => $e->getMessage()); continue; } if ($isRemote) { /** * @see Conjoon_Modules_Groupware_Email_ImapHelper */ require_once 'Conjoon/Modules/Groupware/Email/ImapHelper.php'; $uId = $remoteInfo['uid']; $account = $remoteInfo['account']; $path = $remoteInfo['path']; // check if folder is remote folder /** * @see Conjoon_Text_Parser_Mail_MailboxFolderPathJsonParser */ require_once 'Conjoon/Text/Parser/Mail/MailboxFolderPathJsonParser.php'; $parser = new Conjoon_Text_Parser_Mail_MailboxFolderPathJsonParser(); $pathInfo = $parser->parse(json_encode($path)); /** * @see Conjoon_Modules_Groupware_Email_Folder_Facade */ require_once 'Conjoon/Modules/Groupware/Email/Folder/Facade.php'; $facade = Conjoon_Modules_Groupware_Email_Folder_Facade::getInstance(); // get the account for the root folder first $imapAccount = $facade->getImapAccountForFolderIdAndUserId($pathInfo['rootId'], $userId); if ($imapAccount && !empty($pathInfo) && $facade->isRemoteFolder($pathInfo['rootId'])) { // if remote, where is the referenced mail stored? $globalName = $facade->getAssembledGlobalNameForAccountAndPath($imapAccount, $pathInfo['path']); /** * @see Conjoon_Modules_Groupware_Email_ImapHelper */ require_once 'Conjoon/Modules/Groupware/Email/ImapHelper.php'; /** * @see Conjoon_Mail_Storage_Imap */ require_once 'Conjoon/Mail/Storage/Imap.php'; $protocol = Conjoon_Modules_Groupware_Email_ImapHelper::reuseImapProtocolForAccount($imapAccount); $storage = new Conjoon_Mail_Storage_Imap($protocol); // get the number of the message by it's unique id $storage->selectFolder($globalName); $messageNumber = $storage->getNumberByUniqueId($uId); // move from sent folder $sentGlobalName = $this->getGlobalNameForFolderType($imapAccount, 'SENT'); if (!$sentGlobalName) { continue; } $storage->copyMessage($messageNumber, $sentGlobalName); $storage->selectFolder($sentGlobalName); $newMessageNumber = $storage->countMessages(); $storage->selectFolder($globalName); $storage->removeMessage($storage->getNumberByUniqueId($uId)); $storage->close(); } // put email into sent folder $protocol = Conjoon_Modules_Groupware_Email_ImapHelper::reuseImapProtocolForAccount($imapAccount); $storage = new Conjoon_Mail_Storage_Imap($protocol); // read out single item $item = $this->getSingleImapListItem($account, $userId, $newMessageNumber, $sentGlobalName); $newVersions[$uId] = $item['id']; $sendItems[] = $item; } else { // if the email was send successfully, save it into the db and // return the params savedId (id of the newly saved email) // and savedFolderId (id of the folder where the email was saved in) $itemDecorator = new Conjoon_BeanContext_Decorator('Conjoon_Modules_Groupware_Email_Item_Model_Item', new Conjoon_Modules_Groupware_Email_Item_Filter_ItemResponse(array(), Conjoon_Filter_Input::CONTEXT_RESPONSE), false); $item = $itemDecorator->saveSentEmailAsDto($message, $account, $userId, $mail, ''); if (!$item) { continue; } $sendItems[] = $item; $cri = $itemDecorator->getReferencedItemAsDto($item->id, $userId); if (!empty($cri)) { $contextReferencedItems[] = $cri; } } } if (!empty($errors)) { /** * @see Conjoon_Error */ require_once 'Conjoon/Error.php'; $m = array(); $m[] = "One or more messages could not be sent:"; for ($i = 0, $len = count($errors); $i < $len; $i++) { $m[] = "Message " . ($i + 1) . ":"; $m[] = "Subject: \"" . $errors[$i]['subject'] . "\""; $m[] = "Account: " . $errors[$i]['accountName']; $m[] = "Failure reason: " . $errors[$i]['reason']; } $errorMessage = implode("\n", $m); $error = new Conjoon_Error(); $error->setLevel(Conjoon_Error::LEVEL_WARNING); $error->setType(Conjoon_Error::DATA); $error->setMessage($errorMessage); } $this->view->newVersions = $newVersions; $this->view->success = true; $this->view->sentItems = $sendItems; $this->view->error = isset($error) ? $error->getDto() : null; $this->view->contextReferencedItems = $contextReferencedItems; }