/**
  * 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;
 }
 /**
  * @depends testIsMessageForwarded
  */
 public function testResolveOwnerOfEmailMessage()
 {
     $user = UserTestHelper::createBasicUser('billy');
     $email = new Email();
     $email->emailAddress = '*****@*****.**';
     $user->primaryEmail = $email;
     $this->assertTrue($user->save());
     // User send message to dropbox, via additional to field
     // This shouldn't be done in practice, but we need to cover it.
     $imapMessage = new ImapMessage();
     $imapMessage->subject = "Test subject";
     $imapMessage->fromEmail = "*****@*****.**";
     $imapMessage->to = array(array('email' => '*****@*****.**'), array('email' => '*****@*****.**'));
     $owner = EmailArchivingUtil::resolveOwnerOfEmailMessage($imapMessage);
     $this->assertEquals($user->id, $owner->id);
     // User sent CC copy of his email to dropbox
     // This also shouldn't be done in practice, because email recipient will see dropbox email account,
     // but we need to cover it.
     $imapMessage = new ImapMessage();
     $imapMessage->subject = "Test subject";
     $imapMessage->fromEmail = "*****@*****.**";
     $imapMessage->to = array(array('email' => '*****@*****.**'));
     $imapMessage->cc = array(array('email' => '*****@*****.**'));
     $owner = EmailArchivingUtil::resolveOwnerOfEmailMessage($imapMessage);
     $this->assertEquals($user->id, $owner->id);
     // User sent BCC copy of his email to dropbox
     $imapMessage = new ImapMessage();
     $imapMessage->subject = "Test subject";
     $imapMessage->fromEmail = "*****@*****.**";
     $imapMessage->to = array(array('email' => '*****@*****.**'));
     $imapMessage->bcc = array(array('email' => '*****@*****.**'));
     $owner = EmailArchivingUtil::resolveOwnerOfEmailMessage($imapMessage);
     $this->assertEquals($user->id, $owner->id);
     // Forwarded message, user should be in from field
     $imapMessage->subject = "Fwd: Test subject";
     $imapMessage->fromEmail = "*****@*****.**";
     $imapMessage->to = array(array('email' => '*****@*****.**'));
     $owner = EmailArchivingUtil::resolveOwnerOfEmailMessage($imapMessage);
     $this->assertEquals($user->id, $owner->id);
 }