dev
This commit is contained in:
@@ -131,7 +131,7 @@ class Sender
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function send(Email $email, $params = array(), &$message = null)
|
||||
public function send(Email $email, $params = array(), &$message = null, $attachmetList = [])
|
||||
{
|
||||
$message = new Message();
|
||||
$config = $this->config;
|
||||
@@ -220,6 +220,10 @@ class Sender
|
||||
$attachmentCollection = $email->get('attachments');
|
||||
$attachmentInlineCollection = $email->getInlineAttachments();
|
||||
|
||||
foreach ($attachmetList as $attachment) {
|
||||
$attachmentCollection[] = $attachment;
|
||||
}
|
||||
|
||||
if (!empty($attachmentCollection)) {
|
||||
foreach ($attachmentCollection as $a) {
|
||||
$fileName = 'data/upload/' . $a->id;
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2015 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: http://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Crm\Entities;
|
||||
|
||||
class EmailQueueItem extends \Espo\Core\ORM\Entity
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2015 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
|
||||
* Website: http://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Modules\Crm\Jobs;
|
||||
|
||||
use \Espo\Core\Exceptions;
|
||||
|
||||
class ProcessMassEmail extends \Espo\Core\Jobs\Base
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$service = $this->getServiceFactory()->create('MassEmail');
|
||||
|
||||
$massEmailList = $this->getEntityManager()->getRepository('MassEmail')->where(array(
|
||||
'status' => 'Pending',
|
||||
'startAt<=' => date('Y-m-d H:i:s')
|
||||
))->find();
|
||||
foreach ($massEmailList as $massEmail) {
|
||||
try {
|
||||
$service->createQueue($massEmail);
|
||||
} catch (\Exception $e) {
|
||||
$GLOBALS['log']->error('Job ProcessMassEmail#createQueue '.$massEmail->id.': [' . $e->getCode() . '] ' .$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
$massEmailList = $this->getEntityManager()->getRepository('MassEmail')->where(array(
|
||||
'status' => 'In Process'
|
||||
))->find();
|
||||
foreach ($massEmailList as $massEmail) {
|
||||
try {
|
||||
$service->processSending($massEmail);
|
||||
} catch (\Exception $e) {
|
||||
$GLOBALS['log']->error('Job ProcessMassEmail#processSending '.$massEmail->id.': [' . $e->getCode() . '] ' .$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
"Pending": "Pending",
|
||||
"In Process": "In Process",
|
||||
"Complete": "Complete",
|
||||
"Canceled": "Canceled"
|
||||
"Canceled": "Canceled",
|
||||
"Failed": "Failed"
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"options": {
|
||||
"job": {
|
||||
"ProcessMassEmail": "Send Mass Emails"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
"default": 0
|
||||
},
|
||||
"target": {
|
||||
"type": "linkTarget",
|
||||
"type": "linkParent",
|
||||
"readOnly": true
|
||||
},
|
||||
"sentAt": {
|
||||
|
||||
@@ -28,6 +28,18 @@ use \Espo\ORM\Entity;
|
||||
|
||||
class MassEmail extends \Espo\Services\Record
|
||||
{
|
||||
const MAX_ATTEMPT_COUNT = 3;
|
||||
|
||||
protected function init()
|
||||
{
|
||||
$this->dependencies[] = 'container';
|
||||
}
|
||||
|
||||
protected function getMailSender()
|
||||
{
|
||||
return $this->getInjection('container')->get('mailSender');
|
||||
}
|
||||
|
||||
protected function beforeCreate(Entity $entity, array $data = array())
|
||||
{
|
||||
parent::beforeCreate($entity, $data);
|
||||
@@ -35,5 +47,200 @@ class MassEmail extends \Espo\Services\Record
|
||||
throw new Forbidden();
|
||||
}
|
||||
}
|
||||
|
||||
public function createQueue(Entity $massEmail)
|
||||
{
|
||||
$existingQueueItemList = $this->getEntityManager()->getRepository('EmailQueueItem')->where(array(
|
||||
'status' => ['Pending', 'Failed'],
|
||||
'massEmailId' => $massEmail->id
|
||||
))->find();
|
||||
foreach ($existingQueueItemList as $existingQueueItem) {
|
||||
$this->getEntityManager()->getMapper('RDB')->deleteFromDb('EmailQueueItem', $existingQueueItem->id);
|
||||
}
|
||||
|
||||
$targetHash = array();
|
||||
$entityList = [];
|
||||
|
||||
$targetListCollection = $massEmail->get('targetLists');
|
||||
foreach ($targetListCollection as $targetList) {
|
||||
$accountList = $targetList->get('accounts');
|
||||
foreach ($accountList as $account) {
|
||||
$hashId = $account->getEntityType() . '-'. $account->id;
|
||||
if (!empty($targetHash[$hashId])) {
|
||||
continue;
|
||||
}
|
||||
$entityList[] = $account;
|
||||
$targetHash[$hashId] = true;
|
||||
}
|
||||
$contactList = $targetList->get('contacts');
|
||||
foreach ($contactList as $contact) {
|
||||
$hashId = $contact->getEntityType() . '-'. $contact->id;
|
||||
if (!empty($targetHash[$hashId])) {
|
||||
continue;
|
||||
}
|
||||
$entityList[] = $contact;
|
||||
$targetHash[$hashId] = true;
|
||||
}
|
||||
$leadList = $targetList->get('leads');
|
||||
foreach ($leadList as $lead) {
|
||||
$hashId = $lead->getEntityType() . '-'. $lead->id;
|
||||
if (!empty($targetHash[$hashId])) {
|
||||
continue;
|
||||
}
|
||||
$entityList[] = $lead;
|
||||
$targetHash[$hashId] = true;
|
||||
}
|
||||
$userList = $targetList->get('users');
|
||||
foreach ($userList as $user) {
|
||||
$hashId = $user->getEntityType() . '-'. $user->id;
|
||||
if (!empty($targetHash[$hashId])) {
|
||||
continue;
|
||||
}
|
||||
$entityList[] = $user;
|
||||
$targetHash[$hashId] = true;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($entityList as $target) {
|
||||
$queueItem = $this->getEntityManager()->getEntity('EmailQueueItem');
|
||||
$queueItem->set(array(
|
||||
'massEmailId' => $massEmail->id,
|
||||
'status' => 'Pending',
|
||||
'targetId' => $target->id,
|
||||
'targetType' => $target->getEntityType()
|
||||
));
|
||||
$this->getEntityManager()->saveEntity($queueItem);
|
||||
}
|
||||
|
||||
$massEmail->set('status', 'In Process');
|
||||
|
||||
if (empty($entityList)) {
|
||||
$massEmail->set('status', 'Complete');
|
||||
}
|
||||
|
||||
$this->getEntityManager()->saveEntity($massEmail);
|
||||
}
|
||||
|
||||
protected function setFailed(Entity $massEmail)
|
||||
{
|
||||
$massEmail->set('status', 'Failed');
|
||||
$this->getEntityManager()->saveEntity($massEmail);
|
||||
|
||||
$queueItemList = $this->getEntityManager()->getRepository('EmailQueueItem')->where(array(
|
||||
'status' => 'Pending',
|
||||
'massEmailId' => $massEmail->id
|
||||
))->find();
|
||||
foreach ($queueItemList as $queueItem) {
|
||||
$queueItem->set('status', 'Failed');
|
||||
$this->getEntityManager()->saveEntity($queueItem);
|
||||
}
|
||||
}
|
||||
|
||||
public function processSending(Entity $massEmail)
|
||||
{
|
||||
$queueItemList = $this->getEntityManager()->getRepository('EmailQueueItem')->where(array(
|
||||
'status' => 'Pending',
|
||||
'massEmailId' => $massEmail->id
|
||||
))->find();
|
||||
|
||||
$templateId = $massEmail->get('emailTemplateId');
|
||||
if (!$templateId) {
|
||||
$this->setFailed($massEmail);
|
||||
return;
|
||||
}
|
||||
|
||||
$emailTemplate = $this->getEntityManager()->getEntity('EmailTemplate', $templateId);
|
||||
if (!$emailTemplate) {
|
||||
$this->setFailed($massEmail);
|
||||
return;
|
||||
}
|
||||
$attachmetList = $emailTemplate->get('attachmets');
|
||||
|
||||
foreach ($queueItemList as $queueItem) {
|
||||
$this->sendQueueItem($queueItem, $massEmail, $emailTemplate, $attachmetList);
|
||||
}
|
||||
|
||||
$countLeft = $this->getEntityManager()->getRepository('EmailQueueItem')->where(array(
|
||||
'status' => 'Pending',
|
||||
'massEmailId' => $massEmail->id
|
||||
))->count();
|
||||
if ($countLeft == 0) {
|
||||
$massEmail->set('status', 'Complete');
|
||||
$this->getEntityManager()->saveEntity($massEmail);
|
||||
}
|
||||
}
|
||||
|
||||
protected function sendQueueItem(Entity $queueItem, Entity $massEmail, Entity $emailTemplate, $attachmetList = [])
|
||||
{
|
||||
$target = $this->getEntityManager()->getEntity($queueItem->get('targetType'), $queueItem->get('targetId'));
|
||||
if (!$target || !$target->id || !$target->get('emailAddress')) {
|
||||
$queueItem->set('status', 'Failed');
|
||||
$this->getEntityManager()->saveEntity($queueItem);
|
||||
return;
|
||||
}
|
||||
|
||||
$templateParams = array(
|
||||
'parent' => $target
|
||||
);
|
||||
|
||||
$emailData = $this->getEmailTemplateService()->parseTemplate($emailTemplate, $templateParams);
|
||||
|
||||
print_r($emailData);
|
||||
return;
|
||||
|
||||
$email = $this->getEntityManager()->getEntity('Email');
|
||||
$email->set($emailData);
|
||||
$emailAddress = $target->get('emailAddress');
|
||||
|
||||
if (empty($emailAddress)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$email->set('to', $emailAddress);
|
||||
|
||||
$params = array();
|
||||
if ($massEmail->get('fromAddress')) {
|
||||
$email->set('from', $massEmail->get('fromAddress'));
|
||||
}
|
||||
if ($massEmail->get('replyToAddress')) {
|
||||
$email->set('replyToAddress', $massEmail->get('replyToAddress'));
|
||||
}
|
||||
if ($massEmail->get('fromName')) {
|
||||
$params['fromName'] = $massEmail->get('fromName');
|
||||
}
|
||||
if ($massEmail->get('replyToName')) {
|
||||
$params['replyToName'] = $massEmail->get('replyToName');
|
||||
}
|
||||
|
||||
try {
|
||||
$attemptCount = $queueItem->get('attemptCount');
|
||||
$attemptCount++;
|
||||
$queueItem->set('attemptCount', $attemptCount);
|
||||
|
||||
$message = false;
|
||||
$this->getMailSender()->useGlobal()->send($email, $params, $message, $attachmetList);
|
||||
|
||||
$queueItem->set('status', 'Sent');
|
||||
$queueItem->set('sentAt', date('Y-m-d H:i:s'));
|
||||
$this->getEntityManager()->saveEntity($queueItem);
|
||||
} catch (\Exception $e) {
|
||||
if ($queueItem->get('attemptCount') >= self::MAX_ATTEMPT_COUNT) {
|
||||
$queueItem->set('status', 'Failed');
|
||||
}
|
||||
$this->getEntityManager()->saveEntity($queueItem);
|
||||
$GLOBALS['log']->error('MassEmail#sendQueueItem: [' . $e->getCode() . '] ' .$e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function getEmailTemplateService()
|
||||
{
|
||||
if (!$this->emailTemplateService) {
|
||||
$this->emailTemplateService = $this->getServiceFactory()->create('EmailTemplate');
|
||||
}
|
||||
return $this->emailTemplateService;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ class EntityManager
|
||||
protected function getMapperClassName($name)
|
||||
{
|
||||
$className = null;
|
||||
|
||||
|
||||
switch ($name) {
|
||||
case 'RDB':
|
||||
$platform = $this->params['platform'];
|
||||
|
||||
@@ -48,20 +48,15 @@ class EmailTemplate extends Record
|
||||
return $this->injections['dateTime'];
|
||||
}
|
||||
|
||||
public function parse($id, array $params = array(), $copyAttachments = false)
|
||||
public function parseTemplate(Entity $emailTemplate, array $params = array(), $copyAttachments = false)
|
||||
{
|
||||
$emailTemplate = $this->getEntity($id);
|
||||
if (empty($emailTemplate)) {
|
||||
throw new NotFound();
|
||||
}
|
||||
|
||||
$entityList = array();
|
||||
$entityHash = array();
|
||||
if (!empty($params['entityHash']) && is_array($params['entityHash'])) {
|
||||
$entityList = $params['entityHash'];
|
||||
$entityHash = $params['entityHash'];
|
||||
}
|
||||
|
||||
if (!isset($entityList['User'])) {
|
||||
$entityList['User'] = $this->getUser();
|
||||
if (!isset($entityHash['User'])) {
|
||||
$entityHash['User'] = $this->getUser();
|
||||
}
|
||||
|
||||
if (!empty($params['emailAddress'])) {
|
||||
@@ -73,33 +68,40 @@ class EmailTemplate extends Record
|
||||
|
||||
if ($entity) {
|
||||
if ($entity instanceof Person) {
|
||||
$entityList['Person'] = $entity;
|
||||
$entityHash['Person'] = $entity;
|
||||
}
|
||||
if (empty($entityList[$entity->getEntityType()])) {
|
||||
$entityList[$entity->getEntityType()] = $entity;
|
||||
if (empty($entityHash[$entity->getEntityType()])) {
|
||||
$entityHash[$entity->getEntityType()] = $entity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($params['parentId']) && !empty($params['parentType'])) {
|
||||
$parent = $this->getEntityManager()->getEntity($params['parentType'], $params['parentId']);
|
||||
if (!empty($parent)) {
|
||||
$entityList[$params['parentType']] = $parent;
|
||||
$entityList['Parent'] = $parent;
|
||||
|
||||
if (empty($entityList['Person']) && ($parent instanceof Person)) {
|
||||
$entityList['Person'] = $parent;
|
||||
if (empty($params['parent'])) {
|
||||
if (!empty($params['parentId']) && !empty($params['parentType'])) {
|
||||
$parent = $this->getEntityManager()->getEntity($params['parentType'], $params['parentId']);
|
||||
if ($parent) {
|
||||
$params['parent'] = $parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($params['parent'])) {
|
||||
$parent = $params['parent'];
|
||||
$entityHash[$parent->getEntityType()] = $parent;
|
||||
$entityHash['Parent'] = $parent;
|
||||
|
||||
if (empty($entityHash['Person']) && ($parent instanceof Person)) {
|
||||
$entityHash['Person'] = $parent;
|
||||
}
|
||||
}
|
||||
|
||||
$subject = $emailTemplate->get('subject');
|
||||
$body = $emailTemplate->get('body');
|
||||
|
||||
foreach ($entityList as $type => $entity) {
|
||||
foreach ($entityHash as $type => $entity) {
|
||||
$subject = $this->parseText($type, $entity, $subject);
|
||||
}
|
||||
foreach ($entityList as $type => $entity) {
|
||||
foreach ($entityHash as $type => $entity) {
|
||||
$body = $this->parseText($type, $entity, $body);
|
||||
}
|
||||
|
||||
@@ -139,6 +141,16 @@ class EmailTemplate extends Record
|
||||
);
|
||||
}
|
||||
|
||||
public function parse($id, array $params = array(), $copyAttachments = false)
|
||||
{
|
||||
$emailTemplate = $this->getEntity($id);
|
||||
if (empty($emailTemplate)) {
|
||||
throw new NotFound();
|
||||
}
|
||||
|
||||
return $this->parseTemplate($emailTemplate, $params, $copyAttachments);
|
||||
}
|
||||
|
||||
protected function parseText($type, Entity $entity, $text)
|
||||
{
|
||||
$fieldList = array_keys($entity->getFields());
|
||||
|
||||
@@ -54,6 +54,12 @@ return array(
|
||||
'status' => 'Active',
|
||||
'scheduling' => '1 1 * * 0',
|
||||
),
|
||||
4 => array(
|
||||
'name' => 'Send Mass Emails',
|
||||
'job' => 'ProcessMassEmail',
|
||||
'status' => 'Active',
|
||||
'scheduling' => '0 2-5 * * *',
|
||||
),
|
||||
|
||||
),
|
||||
);
|
||||
Reference in New Issue
Block a user