/** * Adds recipient emails as recipients to the email message. If the recipient email already matches * an person or account on the email message it will ignore it. * @param Array $recipients * @param EmailMessage $emailMessage * @param integer $type */ public static function attachRecipientsToMessage(array $recipients, EmailMessage $emailMessage, $type) { assert('is_int($type)'); $existingPersonsOrAccounts = array(); if ($emailMessage->recipients->count() > 0) { foreach ($emailMessage->recipients as $recipient) { if ($recipient->personOrAccount != null && $recipient->personOrAccount->id > 0) { $existingPersonsOrAccounts[] = $recipient->personOrAccount->getClassId('Item'); } } } foreach ($recipients as $recipient) { if ($recipient != null) { $personsOrAccounts = EmailArchivingUtil::getPersonsAndAccountsByEmailAddressForUser($recipient, Yii::app()->user->userModel); if (empty($personsOrAccounts)) { $personsOrAccounts[] = null; } foreach ($personsOrAccounts as $personOrAccount) { if ($personOrAccount == null || !in_array($personOrAccount->getClassId('Item'), $existingPersonsOrAccounts)) { $messageRecipient = new EmailMessageRecipient(); $messageRecipient->toAddress = $recipient; $messageRecipient->type = $type; if ($personOrAccount != null) { $messageRecipient->toName = strval($personOrAccount); $messageRecipient->personOrAccount = $personOrAccount; $existingPersonsOrAccounts[] = $personOrAccount->getClassId('Item'); } $emailMessage->recipients->add($messageRecipient); } } } } }
/** * 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; }
/** * 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; }
public function testCreateEmailAttachment() { $user = UserTestHelper::createBasicUser('attachmentTestUser'); Yii::app()->user->userModel = $user; $imapMessage = new ImapMessage(); $pathToFiles = Yii::getPathOfAlias('application.modules.emailMessages.tests.unit.files'); $filePath_1 = $pathToFiles . DIRECTORY_SEPARATOR . 'table.csv'; $data['attachments'] = array(array('filename' => 'table.csv', 'attachment' => file_get_contents($filePath_1))); $imapMessage->attachments = $data['attachments']; $file = EmailArchivingUtil::createEmailAttachment($imapMessage->attachments[0]); $this->assertTrue($file instanceof FileModel); $this->assertEquals($file->name, $imapMessage->attachments[0]['filename']); $this->assertTrue($file->fileContent instanceof FileContent); $this->assertEquals($file->fileContent->content, $imapMessage->attachments[0]['attachment']); $this->assertEquals($file->type, 'text/csv'); $this->assertEquals($file->size, strlen($imapMessage->attachments[0]['attachment'])); // Test with not allowed extension $imapMessage = new ImapMessage(); $data['attachments'] = array(array('filename' => 'table.abc', 'attachment' => 'notAllowed')); $imapMessage->attachments = $data['attachments']; $file = EmailArchivingUtil::createEmailAttachment($imapMessage->attachments[0]); $this->assertFalse($file); }
/** * Create EmailMessageRecipient * @param array $recipientInfo * @param boolean $userCanAccessContacts * @param boolean $userCanAccessLeads * @param boolean $userCanAccessAccounts * @return EmailMessageRecipient */ public static function createEmailMessageRecipient($recipientInfo, $userCanAccessContacts, $userCanAccessLeads, $userCanAccessAccounts) { $recipient = new EmailMessageRecipient(); $recipient->toAddress = $recipientInfo['email']; if (isset($recipientInfo['name'])) { $recipient->toName = $recipientInfo['name']; } $recipient->type = $recipientInfo['type']; $personsOrAccounts = EmailArchivingUtil::getPersonsAndAccountsByEmailAddress($recipientInfo['email'], $userCanAccessContacts, $userCanAccessLeads, $userCanAccessAccounts); if (!empty($personsOrAccounts)) { foreach ($personsOrAccounts as $personOrAccount) { $recipient->personsOrAccounts->add($personOrAccount); } } return $recipient; }
/** * * Test EmailArchivingUtil::resolveSanitizeFromImapToUtf8 to ensure that email subject is UTF8 */ public function testResolveSanitizeMessageSubject() { $super = User::getByUsername('super'); Yii::app()->user->userModel = $super; $subjectUTF8 = 'Тестовое письмо. Test email'; $subjectKOI8R = '=?KOI8-R?Q?=F4=C5=D3=D4=CF=D7=CF=C5_=D0=C9=D3=D8=CD=CF=2E_Te?= =?KOI8-R?Q?st_email?='; // Not Coding Standard $emailMessage = new EmailMessage(); $emailMessage->subject = $subjectKOI8R; $this->assertEquals($subjectKOI8R, $emailMessage->subject); EmailArchivingUtil::resolveSanitizeFromImapToUtf8($emailMessage); $this->assertEquals($subjectUTF8, $emailMessage->subject); //$this->assertTrue($emailMessage->save(false)); }