/**
  * 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;
 }
 public function testCreateEmailMessageRecipient()
 {
     $user = UserTestHelper::createBasicUser('recipientTestUser');
     Yii::app()->user->userModel = $user;
     $account = AccountTestHelper::createAccountByNameForOwner('RecipientAccount', $user);
     $account->primaryEmail->emailAddress = '*****@*****.**';
     $this->assertTrue($account->save());
     $contact = ContactTestHelper::createContactByNameForOwner('RecipientContact', $user);
     $contact->primaryEmail->emailAddress = '*****@*****.**';
     $this->assertTrue($contact->save());
     $recipientInfo = array('name' => 'Recipient Name', 'email' => '*****@*****.**', 'type' => EmailMessageRecipient::TYPE_CC);
     $emailMessageRecipient = EmailArchivingUtil::createEmailMessageRecipient($recipientInfo, true, true, true);
     $this->assertTrue($emailMessageRecipient instanceof EmailMessageRecipient);
     $this->assertEquals($emailMessageRecipient->toAddress, $recipientInfo['email']);
     $this->assertEquals($emailMessageRecipient->toName, $recipientInfo['name']);
     $this->assertEquals($emailMessageRecipient->type, $recipientInfo['type']);
     $this->assertTrue($emailMessageRecipient->personsOrAccounts[0]->isSame($contact));
     $this->assertTrue($emailMessageRecipient->personsOrAccounts[1]->isSame($account));
     $this->assertEquals($emailMessageRecipient->personsOrAccounts->count(), 2);
     // Test when user can't access Contacts
     $recipientInfo['type'] = EmailMessageRecipient::TYPE_TO;
     $emailMessageRecipient = EmailArchivingUtil::createEmailMessageRecipient($recipientInfo, false, true, true);
     $this->assertTrue($emailMessageRecipient instanceof EmailMessageRecipient);
     $this->assertEquals($emailMessageRecipient->toAddress, $recipientInfo['email']);
     $this->assertEquals($emailMessageRecipient->toName, $recipientInfo['name']);
     $this->assertEquals($emailMessageRecipient->type, $recipientInfo['type']);
     $this->assertEquals($emailMessageRecipient->personsOrAccounts->count(), 1);
     $this->assertTrue($emailMessageRecipient->personsOrAccounts[0]->isSame($account));
     // Test when user can't access Contacts
     $recipientInfo['type'] = EmailMessageRecipient::TYPE_BCC;
     $emailMessageRecipient = EmailArchivingUtil::createEmailMessageRecipient($recipientInfo, false, true, false);
     $this->assertTrue($emailMessageRecipient instanceof EmailMessageRecipient);
     $this->assertEquals($emailMessageRecipient->toAddress, $recipientInfo['email']);
     $this->assertEquals($emailMessageRecipient->toName, $recipientInfo['name']);
     $this->assertEquals($emailMessageRecipient->type, $recipientInfo['type']);
     $this->assertEquals($emailMessageRecipient->personsOrAccounts->count(), 0);
     $recipientInfo = array('name' => 'Recipient Name', 'email' => '*****@*****.**', 'type' => EmailMessageRecipient::TYPE_CC);
     $emailMessageRecipient = EmailArchivingUtil::createEmailMessageRecipient($recipientInfo, true, true, true);
     $this->assertTrue($emailMessageRecipient instanceof EmailMessageRecipient);
     $this->assertEquals($emailMessageRecipient->toAddress, $recipientInfo['email']);
     $this->assertEquals($emailMessageRecipient->toName, $recipientInfo['name']);
     $this->assertEquals($emailMessageRecipient->type, $recipientInfo['type']);
     $this->assertEquals($emailMessageRecipient->personsOrAccounts->count(), 0);
 }