/** * Save email message * This method should be protected, but we made it public for unit testing, so don't call it outside this class. * @param ImapMessage $message * @throws NotSupportedException * @return boolean */ public function saveEmailMessage(ImapMessage $message) { // Get owner for message try { $emailOwner = EmailArchivingUtil::resolveOwnerOfEmailMessage($message); } catch (CException $e) { // User not found, so inform user about issue and continue with next email. $this->resolveMessageSubjectAndContentAndSendSystemMessage('OwnerNotExist', $message); return false; } $emailSenderOrRecipientEmailFoundInSystem = false; $userCanAccessContacts = RightsUtil::canUserAccessModule('ContactsModule', $emailOwner); $userCanAccessLeads = RightsUtil::canUserAccessModule('LeadsModule', $emailOwner); $userCanAccessAccounts = RightsUtil::canUserAccessModule('AccountsModule', $emailOwner); $senderInfo = EmailArchivingUtil::resolveEmailSenderFromEmailMessage($message); if (!$senderInfo) { $this->resolveMessageSubjectAndContentAndSendSystemMessage('SenderNotExtracted', $message); return false; } else { $sender = EmailArchivingUtil::createEmailMessageSender($senderInfo, $userCanAccessContacts, $userCanAccessLeads, $userCanAccessAccounts); if ($sender->personsOrAccounts->count() > 0) { $emailSenderOrRecipientEmailFoundInSystem = true; } } try { $recipientsInfo = EmailArchivingUtil::resolveEmailRecipientsFromEmailMessage($message); } catch (NotSupportedException $exception) { $this->resolveMessageSubjectAndContentAndSendSystemMessage('RecipientNotExtracted', $message); return false; } $emailMessage = new EmailMessage(); $emailMessage->owner = $emailOwner; $emailMessage->subject = $message->subject; $emailContent = new EmailMessageContent(); $emailContent->textContent = $message->textBody; $emailContent->htmlContent = $message->htmlBody; $emailMessage->content = $emailContent; $emailMessage->sender = $sender; $emailRecipientFoundInSystem = false; foreach ($recipientsInfo as $recipientInfo) { $recipient = EmailArchivingUtil::createEmailMessageRecipient($recipientInfo, $userCanAccessContacts, $userCanAccessLeads, $userCanAccessAccounts); $emailMessage->recipients->add($recipient); // Check if at least one recipient email can't be found in Contacts, Leads, Account and User emails // so we will save email message in EmailFolder::TYPE_ARCHIVED_UNMATCHED folder, and user will // be able to match emails with items(Contacts, Accounts...) emails in systems if ($recipient->personsOrAccounts->count() > 0) { $emailRecipientFoundInSystem = true; } } // Override $emailSenderOrRecipientEmailFoundInSystem only if there are no errors if ($emailSenderOrRecipientEmailFoundInSystem == true) { $emailSenderOrRecipientEmailFoundInSystem = $emailRecipientFoundInSystem; } if ($emailOwner instanceof User) { $box = EmailBoxUtil::getDefaultEmailBoxByUser($emailOwner); } else { $box = EmailBox::resolveAndGetByName(EmailBox::NOTIFICATIONS_NAME); } if (!$emailSenderOrRecipientEmailFoundInSystem) { $emailMessage->folder = EmailFolder::getByBoxAndType($box, EmailFolder::TYPE_ARCHIVED_UNMATCHED); $notificationMessage = new NotificationMessage(); $notificationMessage->textContent = Zurmo::t('EmailMessagesModule', 'At least one archived email message does ' . 'not match any records in the system. ' . 'To manually match them use this link: {url}.', array('{url}' => Yii::app()->createUrl('emailMessages/default/matchingList'))); $notificationMessage->htmlContent = Zurmo::t('EmailMessagesModule', 'At least one archived email message does ' . 'not match any records in the system. ' . '<a href="{url}" target="_blank">Click here</a> to manually match them.', array('{url}' => Yii::app()->createUrl('emailMessages/default/matchingList'))); if ($emailOwner instanceof User) { $rules = new EmailMessageArchivingEmailAddressNotMatchingNotificationRules(); $rules->addUser($emailOwner); NotificationsUtil::submit($notificationMessage, $rules); } } else { $emailMessage->folder = EmailFolder::getByBoxAndType($box, EmailFolder::TYPE_ARCHIVED); } if (!empty($message->attachments)) { foreach ($message->attachments as $attachment) { if (!$attachment['is_attachment']) { continue; } $file = EmailArchivingUtil::createEmailAttachment($attachment); if ($file instanceof FileModel) { $emailMessage->files->add($file); } } } $emailMessage->sentDateTime = DateTimeUtil::convertTimestampToDbFormatDateTime(time()); $validated = $emailMessage->validate(); if (!$validated) { // Email message couldn't be validated(some related models can't be validated). Email user. $this->resolveMessageSubjectAndContentAndSendSystemMessage('EmailMessageNotValidated', $message); return false; } EmailArchivingUtil::resolveSanitizeFromImapToUtf8($emailMessage); $saved = $emailMessage->save(); try { if (!$saved) { throw new NotSupportedException(); } if (isset($message->uid)) { $this->imapManager->deleteMessage($message->uid); $this->getMessageLogger()->addDebugMessage('Deleted Message id: ' . $message->uid); } } catch (NotSupportedException $e) { // Email message couldn't be saved. Email user. $this->resolveMessageSubjectAndContentAndSendSystemMessage('EmailMessageNotSaved', $message); return false; } return true; }
/** * Create new model * @param $data * @return ApiResult * @throws ApiException */ protected function processCreate($data) { try { $model = new EmailMessage(); $emailMessage = $this->getImapMessageFromEmailData($data); if (isset($data['sentFrom'])) { unset($data['sentFrom']); } if (isset($data['recipients'])) { unset($data['recipients']); } if (isset($data['attachments'])) { unset($data['attachments']); } if (isset($data['owner']['id'])) { try { $emailOwner = User::getById((int) $data['owner']['id']); } catch (CException $e) { $message = Zurmo::t('ZurmoModule', 'Owner not found.'); throw new ApiException($message); } } else { $emailOwner = Yii::app()->user->userModel; } $emailSenderOrRecipientEmailFoundInSystem = false; $userCanAccessContacts = RightsUtil::canUserAccessModule('ContactsModule', $emailOwner); $userCanAccessLeads = RightsUtil::canUserAccessModule('LeadsModule', $emailOwner); $userCanAccessAccounts = RightsUtil::canUserAccessModule('AccountsModule', $emailOwner); if (!empty($emailMessage->fromEmail)) { $senderInfo['email'] = $emailMessage->fromEmail; $senderInfo['name'] = $emailMessage->fromName; $sender = EmailArchivingUtil::createEmailMessageSender($senderInfo, $userCanAccessContacts, $userCanAccessLeads, $userCanAccessAccounts); if ($sender->personsOrAccounts->count() > 0) { $emailSenderOrRecipientEmailFoundInSystem = true; } } else { $message = Zurmo::t('ZurmoModule', 'Sender not found.'); throw new ApiException($message); } try { $recipientsInfo = EmailArchivingUtil::resolveEmailRecipientsFromEmailMessage($emailMessage); } catch (NotSupportedException $exception) { $message = Zurmo::t('ZurmoModule', 'No recipients found.'); throw new ApiException($message); } $emailRecipientFoundInSystem = false; foreach ($recipientsInfo as $recipientInfo) { $recipient = EmailArchivingUtil::createEmailMessageRecipient($recipientInfo, $userCanAccessContacts, $userCanAccessLeads, $userCanAccessAccounts); $model->recipients->add($recipient); // Check if at least one recipient email can't be found in Contacts, Leads, Account and User emails // so we will save email message in EmailFolder::TYPE_ARCHIVED_UNMATCHED folder, and user will // be able to match emails with items(Contacts, Accounts...) emails in systems if ($recipient->personsOrAccounts->count() > 0) { $emailRecipientFoundInSystem = true; } } if ($emailSenderOrRecipientEmailFoundInSystem == true) { $emailSenderOrRecipientEmailFoundInSystem = $emailRecipientFoundInSystem; } if ($emailOwner instanceof User) { $box = EmailBoxUtil::getDefaultEmailBoxByUser($emailOwner); } else { $box = EmailBox::resolveAndGetByName(EmailBox::NOTIFICATIONS_NAME); } if (!$emailSenderOrRecipientEmailFoundInSystem) { $model->folder = EmailFolder::getByBoxAndType($box, EmailFolder::TYPE_ARCHIVED_UNMATCHED); $this->sendArchivedUnmatchedNotificationToEmailOwner($emailOwner); } else { $model->folder = EmailFolder::getByBoxAndType($box, EmailFolder::TYPE_ARCHIVED); } $model->sender = $sender; if (isset($data['textContent']) || isset($data['htmlContent'])) { $emailContent = new EmailMessageContent(); if (isset($data['textContent'])) { $emailContent->textContent = $data['textContent']; } else { $emailContent->textContent = ''; } if (isset($data['htmlContent'])) { $emailContent->htmlContent = $data['htmlContent']; } else { $emailContent->htmlContent = ''; } $model->content = $emailContent; unset($data['textContent']); unset($data['htmlContent']); } else { $message = Zurmo::t('ZurmoModule', 'No email content found.'); throw new ApiException($message); } if (!empty($emailMessage->attachments)) { foreach ($emailMessage->attachments as $attachment) { if (isset($attachment['filename']) && isset($attachment['attachment'])) { $file = EmailArchivingUtil::createEmailAttachment($attachment, true); if ($file instanceof FileModel) { $model->files->add($file); } } } } if (!isset($data['sentDateTime'])) { $model->sentDateTime = DateTimeUtil::convertTimestampToDbFormatDateTime(time()); } $this->setModelScenarioFromData($model, $data); $model = $this->attemptToSaveModelFromData($model, $data, null, false); $id = $model->id; $model->forget(); if (!count($model->getErrors())) { $data = array('id' => $id); $result = new ApiResult(ApiResponse::STATUS_SUCCESS, $data, null, null); } else { $errors = $model->getErrors(); $message = Zurmo::t('ZurmoModule', 'Model was not created.'); $result = new ApiResult(ApiResponse::STATUS_FAILURE, null, $message, $errors); } } catch (Exception $e) { $message = $e->getMessage(); throw new ApiException($message); } return $result; }
/** * @depends testIsMessageForwarded */ public function testResolveEmailRecipientsFromEmailMessage() { Yii::app()->imap->imapUsername = '******'; $imapMessage = new ImapMessage(); $imapMessage->subject = "Test subject"; $imapMessage->fromEmail = "*****@*****.**"; $imapMessage->to = array(array('email' => '*****@*****.**')); $recipients = EmailArchivingUtil::resolveEmailRecipientsFromEmailMessage($imapMessage); $this->assertEquals($imapMessage->to, $recipients); // Check with multiple recipients. $imapMessage->to = array(array('email' => '*****@*****.**'), array('email' => '*****@*****.**')); $recipients = EmailArchivingUtil::resolveEmailRecipientsFromEmailMessage($imapMessage); $this->assertEquals($imapMessage->to, $recipients); // Check without to recipients. $imapMessage->to = array(); $imapMessage->cc = array(array('email' => '*****@*****.**')); $recipients = EmailArchivingUtil::resolveEmailRecipientsFromEmailMessage($imapMessage); $this->assertEquals($imapMessage->cc, $recipients); //Test when email and name are the same $imapMessage->to = array(array('name' => '*****@*****.**', 'email' => '*****@*****.**')); $imapMessage->cc = array(); $recipients = EmailArchivingUtil::resolveEmailRecipientsFromEmailMessage($imapMessage); $this->assertEquals($imapMessage->to, $recipients); $imapMessage->subject = "FW: Test subject"; $imapMessage->to[0]['email'] = '*****@*****.**'; $recipients = EmailArchivingUtil::resolveEmailRecipientsFromEmailMessage($imapMessage); $compareData = array(array('email' => $imapMessage->fromEmail, 'name' => '', 'type' => EmailMessageRecipient::TYPE_TO)); $this->assertEquals($compareData, $recipients); }