/** * */ protected function saveDraftForImap($draft, $account, $userId, $type, array $referencedData, $postedAttachments, $removeAttachmentIds, $attachmentMap, $userId) { // check folder mapping for draft, return error if not available /** * @see Conjoon_Modules_Groupware_Email_ImapHelper */ require_once 'Conjoon/Modules/Groupware/Email/ImapHelper.php'; /** * @see Zend_Registry */ require_once 'Zend/Registry.php'; /** *@see Conjoon_Keys */ require_once 'Conjoon/Keys.php'; $entityManager = Zend_Registry::get(Conjoon_Keys::DOCTRINE_ENTITY_MANAGER); $mailAccountRepository = $entityManager->getRepository('\\Conjoon\\Data\\Entity\\Mail\\DefaultMailAccountEntity'); $accEntity = $mailAccountRepository->findById($account->getId()); $mappings = $accEntity->getFolderMappings(); $globalName = ""; for ($i = 0, $len = count($mappings); $i < $len; $i++) { if ($mappings[$i]->getType() == 'DRAFT') { $globalName = $mappings[$i]->getGlobalName(); } } if (!$globalName) { $this->view->error = $this->getErrorDto('Missing folder mapping', 'Cannot save draft, since no "draft" folder mapping is available. Please configure the folder mappings for this account first.', Conjoon_Error::LEVEL_ERROR); $this->view->success = false; $this->view->item = null; return; } // assemble mail /** * @see Conjoon_Modules_Groupware_Email_Sender */ require_once 'Conjoon/Modules/Groupware/Email/Sender.php'; $assembleInformation = Conjoon_Modules_Groupware_Email_Sender::getAssembledMail($draft, $account, $postedAttachments, $removeAttachmentIds, $userId, $this->getTransportForAccount($account)); $mail = $assembleInformation['message']; /** * @see Conjoon_Mail_Storage_Imap */ require_once 'Conjoon/Mail/Storage/Imap.php'; $protocol = Conjoon_Modules_Groupware_Email_ImapHelper::reuseImapProtocolForAccount($account->getDto()); $storage = new Conjoon_Mail_Storage_Imap($protocol); // remove the old draft $storage->selectFolder($globalName); $newVersion = false; if ($draft->getId() > -1) { $msgNumber = $storage->getNumberByUniqueId($draft->getId()); $newVersion = true; // remove old message. No need to invoke // the cache service for removing the cached version. // it is okay if this data exists until the cache gets emptied. $storage->removeMessage($msgNumber); } $response = $storage->appendMessage($mail->getExpectedHeaderText() . "\n\n" . $mail->getExpectedBodyText(), $globalName); $lastMessage = -1; $ret = null; if (is_array($response) && isset($response[0])) { $ret = explode(' ', $response[0]); } if (is_array($ret) && count($ret) == 2 && is_numeric($ret[0]) && trim(strtolower($ret[1])) == 'exists') { $lastMessage = $ret[0]; } if ($lastMessage == -1) { $lastMessage = $storage->countMessages(); } if ($lastMessage == -1) { throw new RuntimeException("Could not find message id."); } // immediately setting the \Seen flag does not seemt // to work. Do so by hand. $storage->setFlags($lastMessage, array('\\Seen', '\\Draft')); $item = $this->getSingleImapListItem($account->getDto(), $userId, $lastMessage, $globalName); // this is where the cache for the GetMessageServiceResult will // be rebuild automatically! No need to remove previous cached version! // The old plain mail message should by now be removed // from the IMAP server $emailRecord = $this->getMessageFromRemoteServer($item['id'], $item['path']); $this->view->error = null; $this->view->success = true; $this->view->item = $item; $this->view->newVersion = $newVersion; if ($newVersion) { $this->view->previousId = $draft->getId(); } $this->view->emailRecord = $emailRecord; }
/** * Sends an email to the specified recipients. * The action expects the following arguments to be passed: * * - format: The format the email should be send. Can default to * "text/plain", "text/html" - or "multipart" if the email should * be send both as html and plain-text. * - id: The id of the messge if this was loaded from an already existing * draft (i.e. a draft, an email that is being replied to which is being forwarded). * -type: The type of teh action: if this equals to "reply", "reply_all" or "forward", * this message references an existing one * Can default to 0 or -1 if the emil was created from the scratch * - groupwareEmailAccountsId: An integer specifying the id of the email account of the * user which will be used to send the message * - groupwareEmailFoldersId: The id of the folder from which this email was opened. Equals * to -1 or 0 if the messge was created from scratch * - subject: The subject of the message * - message: The message as edited in the browser. Will most likely have * HTML tags in it depending on the editor used * - to: An json encoded array with all addresses being specified in the "to" * field. Addresses may be separated by a comma "," or a semicolon ";" * - cc: An json encoded array with all addresses being specified in the "cc" * field. Addresses may be separated by a comma "," or a semicolon ";" * - bcc: An json encoded array with all addresses being specified in the "bcc" * field. Addresses may be separated by a comma "," or a semicolon ";" * - attachments: An array with attachments, structure according to * com.conjoon.cudgets.data.FileRecord. ids for files will be stored in * the orgId property * The view awaits a fully configured email item as the response. */ public function sendAction() { require_once 'Conjoon/Modules/Groupware/Email/Draft/Filter/DraftInput.php'; $data = array(); try { // the filter will transform the "message" into bodyHtml and bodyText, depending // on the passed format. both will only be filled if format equals to "multipart" $filter = new Conjoon_Modules_Groupware_Email_Draft_Filter_DraftInput($_POST, Conjoon_Filter_Input::CONTEXT_CREATE); $data = $filter->getProcessedData(); } catch (Exception $e) { require_once 'Conjoon/Error.php'; $error = Conjoon_Error::fromFilter($filter, $e); $this->view->success = false; $this->view->error = $error->getDto(); $this->view->item = null; return; } // input filter does not work properly sometimes with refrenced data // check here for referencedData, throw an exception if not set if (!isset($data['referencedData']) || !is_array($data['referencedData'])) { throw new Exception("referencedData missing."); } /** * @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'; $postedAttachments = $data['attachments']; $data['attachments'] = array(); $removeAttachmentIds = $data['removedAttachments']; unset($data['removedAttachments']); // create the message object here $to = array(); $cc = array(); $bcc = array(); foreach ($data['cc'] as $dcc) { $add = new Conjoon_Modules_Groupware_Email_Address($dcc); $cc[] = $add; } foreach ($data['bcc'] as $dbcc) { $add = new Conjoon_Modules_Groupware_Email_Address($dbcc); $bcc[] = $add; } foreach ($data['to'] as $dto) { $add = new Conjoon_Modules_Groupware_Email_Address($dto); $to[] = $add; } $data['cc'] = $cc; $data['to'] = $to; $data['bcc'] = $bcc; // get the specified account for the user /** * @see Conjoon_BeanContext_Decorator */ require_once 'Conjoon/BeanContext/Decorator.php'; /** * @see Conjoon_Keys */ require_once 'Conjoon/Keys.php'; $accountDecorator = new Conjoon_BeanContext_Decorator('Conjoon_Modules_Groupware_Email_Account_Model_Account'); $auth = Zend_Registry::get(Conjoon_Keys::REGISTRY_AUTH_OBJECT); $userId = $auth->getIdentity()->getId(); $account = $accountDecorator->getAccountAsEntity($data['groupwareEmailAccountsId'], $userId); // no account found? if (!$account) { $this->view->error = $this->getErrorDto('Error while sending email', 'Could not find specified account.', Conjoon_Error::LEVEL_ERROR); $this->view->success = false; $this->view->item = null; return; } $message = Conjoon_BeanContext_Inspector::create('Conjoon_Modules_Groupware_Email_Draft', $data, true); $updateCache = false; // check whether we need to apply attachments for a previously saved // draft if ($message->getId() > 0 && !$this->isRemotePath($data['path'], $userId)) { $updateCache = true; /** * @see Conjoon_Modules_Groupware_Email_Attachment_Filter_AttachmentResponse */ require_once 'Conjoon/Modules/Groupware/Email/Attachment/Filter/AttachmentResponse.php'; $attDecorator = new Conjoon_BeanContext_Decorator('Conjoon_Modules_Groupware_Email_Attachment_Model_Attachment', new Conjoon_Modules_Groupware_Email_Attachment_Filter_AttachmentResponse(array(), Conjoon_Modules_Groupware_Email_Attachment_Filter_AttachmentResponse::CONTEXT_RESPONSE)); $atts = $attDecorator->getAttachmentsForItemAsEntity($message->getId()); $message->setAttachments($atts); } /** * @see Conjoon_Modules_Groupware_Email_Sender */ require_once 'Conjoon/Modules/Groupware/Email/Sender.php'; try { $transport = $this->getTransportForAccount($account); $assembleInformation = Conjoon_Modules_Groupware_Email_Sender::getAssembledMail($message, $account, $postedAttachments, $removeAttachmentIds, $this->getCurrentAppUser()->getId(), $transport, $data['type']); $assembledMail = $assembleInformation['message']; $postedAttachments = $assembleInformation['postedAttachments']; $mail = Conjoon_Modules_Groupware_Email_Sender::send($assembledMail); } catch (Exception $e) { $errorMessage = $e->getMessage(); // check here if a message is set. We rely heavily on stream_socket_client // in Zend_Mail_Protocol_Abstract which may not set the error message all // the time. If no internet conn is available, the message will be missing // on windows systems, for example if ($errorMessage == "") { $errorMessage = "The message with the subject \"" . $message->getSubject() . "\" could not be sent. " . "Please check the internet connection of " . "the server this software runs on."; } $this->view->error = $this->getErrorDto('Error while sending email', $errorMessage, Conjoon_Error::LEVEL_ERROR); $this->view->success = false; $this->view->item = null; return; } // check here if the referenced data contains an IMAP message. // if this is the case, update the message with the \Answered // flag if applicable $referencedData = $message->getReferencedData(); $referencedRemoteItem = null; $contextReferencedItem = null; $isRemoteItemReferenced = false; // check if the mesage was loaded from a remote draft // if this is the case, remove the draft from the rmeote server $imapAccount = $message->getId() > 0 ? $this->isRemotePath($message->getPath(), $userId) : null; if ($message->getId() > 0 && $imapAccount) { $uId = $message->getId(); $path = $message->getPath(); /** * @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(); // 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); $storage->removeMessage($messageNumber); $storage->close(); } if (!empty($referencedData) && isset($referencedData['uId']) && $referencedData['uId'] > 0) { $uId = $referencedData['uId']; $referencedPath = $referencedData['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($referencedPath)); /** * @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'])) { $isRemoteItemReferenced = true; // 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); $flags = array('\\Seen'); if ($data['type'] == 'reply' || $data['type'] == 'reply_all') { $flags = array('\\Seen', '\\Answered'); } else { if ($data['type'] == 'forward') { $flags = array('\\Seen', '$Forwarded'); } } $protocol->store($flags, $messageNumber, null, '+'); $referencedRemoteItem = $this->getSingleImapListItem($imapAccount, $userId, $messageNumber, $globalName); // force a reconnect if internal noop fails Conjoon_Modules_Groupware_Email_ImapHelper::reuseImapProtocolForAccount($imapAccount); } } $folderMappingError = null; if ($account->getProtocol() == 'IMAP') { /** * @see Conjoon_Modules_Groupware_Email_ImapHelper */ require_once 'Conjoon/Modules/Groupware/Email/ImapHelper.php'; /** * @see Zend_Registry */ require_once 'Zend/Registry.php'; /** *@see Conjoon_Keys */ require_once 'Conjoon/Keys.php'; $entityManager = Zend_Registry::get(Conjoon_Keys::DOCTRINE_ENTITY_MANAGER); $mailAccountRepository = $entityManager->getRepository('\\Conjoon\\Data\\Entity\\Mail\\DefaultMailAccountEntity'); $accEntity = $mailAccountRepository->findById($account->getId()); $mappings = $accEntity->getFolderMappings(); $globalName = ""; for ($i = 0, $len = count($mappings); $i < $len; $i++) { if ($mappings[$i]->getType() == 'SENT') { $globalName = $mappings[$i]->getGlobalName(); } } if ($globalName != "") { /** * @see Conjoon_Mail_Storage_Imap */ require_once 'Conjoon/Mail/Storage/Imap.php'; $protocol = Conjoon_Modules_Groupware_Email_ImapHelper::reuseImapProtocolForAccount($account->getDto()); $storage = new Conjoon_Mail_Storage_Imap($protocol); try { $storage->selectFolder($globalName); $response = $storage->appendMessage($mail->getSentHeaderText() . "\n\n" . $mail->getSentBodyText(), $globalName); $lastMessage = -1; $ret = null; if (is_array($response) && isset($response[0])) { $ret = explode(' ', $response[0]); } if (is_array($ret) && count($ret) == 2 && is_numeric($ret[0]) && trim(strtolower($ret[1])) == 'exists') { $lastMessage = $ret[0]; } if ($lastMessage == -1) { $lastMessage = $storage->countMessages(); } if ($lastMessage == -1) { throw new RuntimeException("Could not find message id."); } // immediately setting the \Seen flag does not seemt // to work. Do so by hand. $storage->setFlags($lastMessage, array('\\Seen')); } catch (\Exception $e) { $folderMappingError = true; } } else { $folderMappingError = true; } if ($folderMappingError) { $folderMappingError = $this->getErrorDto('Missing folder mapping', 'The email was sent, but a "sent" version could not be stored to the configured IMAP account. Make sure you have configured the folder mappings for this account properly.', Conjoon_Error::LEVEL_ERROR); } else { $item = $this->getSingleImapListItem($account->getDto(), $userId, $lastMessage, $globalName); } // check here if a remote item was referenced. // if this is not the case, get the local itemand update it's // references if (!$isRemoteItemReferenced && !$referencedRemoteItem && isset($referencedData) && isset($referencedData['uId']) && $referencedData['uId'] > 0) { $uId = $referencedData['uId']; $localFolder = $referencedData['path'][count($referencedData['path']) - 1]; /** * @see Conjoon_Modules_Groupware_Email_Item_Model_Item */ require_once 'Conjoon/Modules/Groupware/Email/Item/Model/Item.php'; $iModel = new Conjoon_Modules_Groupware_Email_Item_Model_Item(); $iModel->updateReferenceFromARemoteItem($uId, $localFolder, $userId, $data['type']); /** * @see Conjoon_Modules_Groupware_Email_Item_Filter_ItemResponse */ require_once 'Conjoon/Modules/Groupware/Email/Item/Filter/ItemResponse.php'; // 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); $contextReferencedItem = $itemDecorator->getItemForUserAsDto($uId, $userId); } $this->view->error = null; $this->view->newVersion = $message->getId() > 0; if ($message->getId() > 0) { $this->view->previousId = $message->getId(); } $this->view->folderMappingError = $folderMappingError; $this->view->success = true; $this->view->item = isset($item) ? $item : null; $this->view->contextReferencedItem = $contextReferencedItem ? $contextReferencedItem : $referencedRemoteItem; return; } /** * @see Conjoon_Modules_Groupware_Email_Item_Filter_ItemResponse */ require_once 'Conjoon/Modules/Groupware/Email/Item/Filter/ItemResponse.php'; // 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, $data['type'], $referencedRemoteItem ? -1 : $data['referencedData']['uId'], $postedAttachments, $removeAttachmentIds); if (!$item) { $this->view->error = $this->getErrorDto('Error while saving email', 'The email was sent, but it could not be stored into the database.', Conjoon_Error::LEVEL_ERROR); $this->view->success = false; $this->view->item = null; return; } if ($updateCache) { /** * @see Conjoon_Modules_Groupware_Email_Message_Facade */ require_once 'Conjoon/Modules/Groupware/Email/Message/Facade.php'; // update cache Conjoon_Modules_Groupware_Email_Message_Facade::getInstance()->removeMessageFromCache($item->id, $this->_helper->registryAccess()->getUserId(), $data['path']); } // if the sent email referenced an existing message, tr to fetch this message // and send it along as context-referenced item if (!$referencedRemoteItem) { $contextReferencedItem = $itemDecorator->getReferencedItemAsDto($item->id, $userId); } $this->view->error = null; $this->view->foldermappingError = $folderMappingError; $this->view->success = true; $this->view->item = $item; $this->view->contextReferencedItem = $referencedRemoteItem ? $referencedRemoteItem : (empty($contextReferencedItem) ? null : $contextReferencedItem); }