email filters dev
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
<?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\Core\Mail;
|
||||
|
||||
|
||||
use \Espo\Entities\Email;
|
||||
|
||||
class FiltersMatcher
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function match(Email $email, $filterList = [])
|
||||
{
|
||||
foreach ($filterList as $filter) {
|
||||
if ($filter->get('from')) {
|
||||
if (strtolower($filter->get('from')) === strtolower($email->get('from'))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if ($filter->get('to')) {
|
||||
if ($email->get('to')) {
|
||||
$toArr = explode(';', $email->get('to'));
|
||||
foreach ($toArr as $to) {
|
||||
if (strtolower($to) === strtolower($filter->get('to'))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($filter->get('subject')) {
|
||||
if ($this->matchString($filter->get('subject'), $email->get('name'))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function matchBody(Email $email, $filterList = [])
|
||||
{
|
||||
foreach ($filterList as $filter) {
|
||||
if ($filter->get('bodyContains')) {
|
||||
$phraseList = $filter->get('bodyContains');
|
||||
$body = $email->get('body');
|
||||
$bodyPlain = $email->get('bodyPlain');
|
||||
foreach ($phraseList as $phrase) {
|
||||
if (stripos($bodyPlain, $phrase) !== false) {
|
||||
return true;
|
||||
}
|
||||
if (stripos($body, $phrase) !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function matchString($pattern, $value)
|
||||
{
|
||||
if ($pattern == $value) {
|
||||
return true;
|
||||
}
|
||||
$pattern = preg_quote($pattern, '#');
|
||||
$pattern = str_replace('\*', '.*', $pattern).'\z';
|
||||
if (preg_match('#^'.$pattern.'#', $value)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ namespace Espo\Core\Mail;
|
||||
use \Zend\Mime\Mime as Mime;
|
||||
|
||||
use \Espo\ORM\Entity;
|
||||
use \Espo\ORM\Email;
|
||||
|
||||
class Importer
|
||||
{
|
||||
@@ -34,11 +35,14 @@ class Importer
|
||||
|
||||
private $config;
|
||||
|
||||
private $filtersMatcher;
|
||||
|
||||
public function __construct($entityManager, $fileManager, $config)
|
||||
{
|
||||
$this->entityManager = $entityManager;
|
||||
$this->fileManager = $fileManager;
|
||||
$this->config = $config;
|
||||
$this->filtersMatcher = new FiltersMatcher();
|
||||
}
|
||||
|
||||
protected function getEntityManager()
|
||||
@@ -55,7 +59,12 @@ class Importer
|
||||
return $this->fileManager;
|
||||
}
|
||||
|
||||
public function importMessage($message, $userId, $teamsIds = array())
|
||||
protected function getFiltersMatcher()
|
||||
{
|
||||
return $this->filtersMatcher;
|
||||
}
|
||||
|
||||
public function importMessage($message, $userId, $teamsIds = [], $filterList = [])
|
||||
{
|
||||
try {
|
||||
$email = $this->getEntityManager()->getEntity('Email');
|
||||
@@ -87,6 +96,10 @@ class Importer
|
||||
$email->set('to', implode(';', $toArr));
|
||||
$email->set('cc', implode(';', $ccArr));
|
||||
|
||||
if ($this->getFiltersMatcher()->match($email, $filterList)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isset($message->messageId) && !empty($message->messageId)) {
|
||||
$email->set('messageId', $message->messageId);
|
||||
if (isset($message->deliveredTo)) {
|
||||
@@ -149,6 +162,10 @@ class Importer
|
||||
$email->set('body', $body);
|
||||
}
|
||||
|
||||
if ($this->getFiltersMatcher()->matchBody($email, $filterList)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$parentFound = false;
|
||||
|
||||
if (isset($message->references) && !empty($message->references)) {
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
},
|
||||
"tooltips": {
|
||||
"name": "Just a name of the filter.",
|
||||
"subject": "Use wildcard %:\n\ntext% - starts with text,\n%text% - contains text,\n%text - ends with text.",
|
||||
"subject": "Use wildcard *:\n\ntext* - starts with text,\n*text* - contains text,\n*text - ends with text.",
|
||||
"bodyContains": "Body of email contains any of specified words or phrases.",
|
||||
"from": "Emails being sent from the specified address. Leave empty if not needed.",
|
||||
"to": "Emails being sent to the specified address. Leave empty if not needed.",
|
||||
|
||||
@@ -176,7 +176,6 @@ class EmailAccount extends Record
|
||||
$maxSize = $this->getConfig()->get('emailMessageMaxSize');
|
||||
|
||||
$user = $this->getEntityManager()->getEntity('User', $emailAccount->get('assignedUserId'));
|
||||
|
||||
if (!$user) {
|
||||
throw new Error();
|
||||
}
|
||||
@@ -188,6 +187,18 @@ class EmailAccount extends Record
|
||||
$teamIds[] = $teamId;
|
||||
}
|
||||
|
||||
$filterCollection = $this->getEntityManager()->getRepository('EmailFilter')->where([
|
||||
'OR' => [
|
||||
[
|
||||
'parentType' => $emailAccount->getEntityType(),
|
||||
'parentId' => $emailAccount->id
|
||||
],
|
||||
[
|
||||
'parentId' => null
|
||||
]
|
||||
]
|
||||
])->find();
|
||||
|
||||
$fetchData = json_decode($emailAccount->get('fetchData'), true);
|
||||
if (empty($fetchData)) {
|
||||
$fetchData = array();
|
||||
@@ -263,7 +274,7 @@ class EmailAccount extends Record
|
||||
$flags = $message->getFlags();
|
||||
}
|
||||
try {
|
||||
$email = $importer->importMessage($message, $userId, $teamIds);
|
||||
$email = $importer->importMessage($message, $userId, $teamIds, $filterCollection);
|
||||
} catch (\Exception $e) {
|
||||
$GLOBALS['log']->error('EmailAccount '.$emailAccount->id.' (Import Message): [' . $e->getCode() . '] ' .$e->getMessage());
|
||||
}
|
||||
|
||||
@@ -142,9 +142,9 @@ class InboundEmail extends \Espo\Services\Record
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
public function fetchFromMailServer(Entity $inboundEmail)
|
||||
public function fetchFromMailServer(Entity $emailAccount)
|
||||
{
|
||||
if ($inboundEmail->get('status') != 'Active') {
|
||||
if ($emailAccount->get('status') != 'Active') {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
@@ -152,17 +152,29 @@ class InboundEmail extends \Espo\Services\Record
|
||||
|
||||
$maxSize = $this->getConfig()->get('emailMessageMaxSize');
|
||||
|
||||
$teamId = $inboundEmail->get('teamId');
|
||||
$teamId = $emailAccount->get('teamId');
|
||||
$userId = $this->getUser()->id;
|
||||
if ($inboundEmail->get('assignToUserId')) {
|
||||
$userId = $inboundEmail->get('assignToUserId');
|
||||
if ($emailAccount->get('assignToUserId')) {
|
||||
$userId = $emailAccount->get('assignToUserId');
|
||||
}
|
||||
$teamIds = array();
|
||||
if (!empty($teamId)) {
|
||||
$teamIds[] = $teamId;
|
||||
}
|
||||
|
||||
$fetchData = json_decode($inboundEmail->get('fetchData'), true);
|
||||
$filterCollection = $this->getEntityManager()->getRepository('EmailFilter')->where([
|
||||
'OR' => [
|
||||
[
|
||||
'parentType' => $emailAccount->getEntityType(),
|
||||
'parentId' => $emailAccount->id
|
||||
],
|
||||
[
|
||||
'parentId' => null
|
||||
]
|
||||
]
|
||||
])->find();
|
||||
|
||||
$fetchData = json_decode($emailAccount->get('fetchData'), true);
|
||||
if (empty($fetchData)) {
|
||||
$fetchData = array();
|
||||
}
|
||||
@@ -174,19 +186,19 @@ class InboundEmail extends \Espo\Services\Record
|
||||
}
|
||||
|
||||
$imapParams = array(
|
||||
'host' => $inboundEmail->get('host'),
|
||||
'port' => $inboundEmail->get('port'),
|
||||
'user' => $inboundEmail->get('username'),
|
||||
'password' => $this->getCrypt()->decrypt($inboundEmail->get('password')),
|
||||
'host' => $emailAccount->get('host'),
|
||||
'port' => $emailAccount->get('port'),
|
||||
'user' => $emailAccount->get('username'),
|
||||
'password' => $this->getCrypt()->decrypt($emailAccount->get('password')),
|
||||
);
|
||||
|
||||
if ($inboundEmail->get('ssl')) {
|
||||
if ($emailAccount->get('ssl')) {
|
||||
$imapParams['ssl'] = 'SSL';
|
||||
}
|
||||
|
||||
$storage = new \Espo\Core\Mail\Mail\Storage\Imap($imapParams);
|
||||
|
||||
$monitoredFolders = $inboundEmail->get('monitoredFolders');
|
||||
$monitoredFolders = $emailAccount->get('monitoredFolders');
|
||||
if (empty($monitoredFolders)) {
|
||||
$monitoredFolders = 'INBOX';
|
||||
}
|
||||
@@ -198,7 +210,7 @@ class InboundEmail extends \Espo\Services\Record
|
||||
try {
|
||||
$storage->selectFolder($folder);
|
||||
} catch (\Exception $e) {
|
||||
$GLOBALS['log']->error('InboundEmail '.$inboundEmail->id.' (Select Folder) [' . $e->getCode() . '] ' .$e->getMessage());
|
||||
$GLOBALS['log']->error('InboundEmail '.$emailAccount->id.' (Select Folder) [' . $e->getCode() . '] ' .$e->getMessage());
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -246,26 +258,26 @@ class InboundEmail extends \Espo\Services\Record
|
||||
}
|
||||
if (!$toSkip) {
|
||||
try {
|
||||
$email = $importer->importMessage($message, $userId, $teamIds);
|
||||
$email = $importer->importMessage($message, $userId, $teamIds, $filterCollection);
|
||||
} catch (\Exception $e) {
|
||||
$GLOBALS['log']->error('InboundEmail '.$inboundEmail->id.' (Import Message): [' . $e->getCode() . '] ' .$e->getMessage());
|
||||
$GLOBALS['log']->error('InboundEmail '.$emailAccount->id.' (Import Message): [' . $e->getCode() . '] ' .$e->getMessage());
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$GLOBALS['log']->error('InboundEmail '.$inboundEmail->id.' (Get Message): [' . $e->getCode() . '] ' .$e->getMessage());
|
||||
$GLOBALS['log']->error('InboundEmail '.$emailAccount->id.' (Get Message): [' . $e->getCode() . '] ' .$e->getMessage());
|
||||
}
|
||||
|
||||
if (!empty($email)) {
|
||||
if (!$inboundEmail->get('createCase')) {
|
||||
if (!$emailAccount->get('createCase')) {
|
||||
$this->noteAboutEmail($email);
|
||||
}
|
||||
|
||||
if ($inboundEmail->get('createCase')) {
|
||||
$this->createCase($inboundEmail, $email);
|
||||
if ($emailAccount->get('createCase')) {
|
||||
$this->createCase($emailAccount, $email);
|
||||
} else {
|
||||
if ($inboundEmail->get('reply')) {
|
||||
if ($emailAccount->get('reply')) {
|
||||
$user = $this->getEntityManager()->getEntity('User', $userId);
|
||||
$this->autoReply($inboundEmail, $email, $user);
|
||||
$this->autoReply($emailAccount, $email, $user);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -290,8 +302,8 @@ class InboundEmail extends \Espo\Services\Record
|
||||
$fetchData['lastUID'][$folder] = $lastUID;
|
||||
$fetchData['lastDate'][$folder] = $lastDate;
|
||||
|
||||
$inboundEmail->set('fetchData', json_encode($fetchData));
|
||||
$this->getEntityManager()->saveEntity($inboundEmail, array('silent' => true));
|
||||
$emailAccount->set('fetchData', json_encode($fetchData));
|
||||
$this->getEntityManager()->saveEntity($emailAccount, array('silent' => true));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -135,7 +135,33 @@ Espo.define('acl', [], function () {
|
||||
return model.get('isRemovable');
|
||||
}
|
||||
}
|
||||
return this.check(model.name, action, this.user.isOwner(model), this.user.inTeam(model));
|
||||
return this.check(model.name, action, this.checkIsOwner(model), this.checkInTeam(model));
|
||||
},
|
||||
|
||||
checkIsOwner: function (model) {
|
||||
var result = this.user.id === model.get('assignedUserId') || this.user.id === model.get('createdById');
|
||||
if (!result) {
|
||||
if (!model.hasField('assignedUser') && !model.hasField('createdBy')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
checkInTeam: function (model) {
|
||||
var userTeamIds = this.user.getTeamIds();
|
||||
|
||||
if (model.name == 'Team') {
|
||||
return (userTeamIds.indexOf(model.id) != -1);
|
||||
} else {
|
||||
var teamIds = model.getTeamIds();
|
||||
for (var i in userTeamIds) {
|
||||
if (teamIds.indexOf(i) != -1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
clear: function () {
|
||||
|
||||
@@ -26,28 +26,7 @@ Espo.define('models/user', 'model', function (Dep) {
|
||||
|
||||
isAdmin: function () {
|
||||
return this.get('isAdmin');
|
||||
},
|
||||
|
||||
isOwner: function (model) {
|
||||
return this.id === model.get('assignedUserId') || this.id === model.get('createdById');
|
||||
},
|
||||
|
||||
inTeam: function (model) {
|
||||
|
||||
var userTeamIds = this.getTeamIds();
|
||||
|
||||
if (model.name == 'Team') {
|
||||
return (userTeamIds.indexOf(model.id) != -1);
|
||||
} else {
|
||||
var teamIds = model.getTeamIds();
|
||||
for (var i in userTeamIds) {
|
||||
if (teamIds.indexOf(i) != -1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
<?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 tests\Espo\Core\Mail;
|
||||
|
||||
use tests\ReflectionHelper;
|
||||
|
||||
class FiltersMatcherTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $object;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->object = new \Espo\Core\Mail\FiltersMatcher();
|
||||
|
||||
$this->emailDefs = array(
|
||||
'fields' => array(
|
||||
'from' => array(
|
||||
'type' => 'varchar'
|
||||
),
|
||||
'to' => array(
|
||||
'type' => 'varchar'
|
||||
),
|
||||
'name' => array(
|
||||
'type' => 'varchar'
|
||||
),
|
||||
'subject' => array(
|
||||
'type' => 'varchar'
|
||||
),
|
||||
'body' => array(
|
||||
'type' => 'text'
|
||||
),
|
||||
'bodyPlain' => array(
|
||||
'type' => 'text'
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$this->filterDefs = array(
|
||||
'fields' => array(
|
||||
'from' => array(
|
||||
'type' => 'varchar'
|
||||
),
|
||||
'to' => array(
|
||||
'type' => 'varchar'
|
||||
),
|
||||
'subject' => array(
|
||||
'type' => 'varchar'
|
||||
),
|
||||
'bodyContains' => array(
|
||||
'type' => 'jsonArray'
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
protected function tearDown()
|
||||
{
|
||||
$this->object = NULL;
|
||||
}
|
||||
|
||||
function testMatch()
|
||||
{
|
||||
$email = new \Espo\Entities\Email($this->emailDefs);
|
||||
$email->set('from', 'test@tester');
|
||||
$filter = new \Espo\Entities\EmailFilter($this->filterDefs);
|
||||
$filter->set(array(
|
||||
'from' => 'test@tester'
|
||||
));
|
||||
$filterList = [$filter];
|
||||
$this->assertTrue($this->object->match($email, $filterList));
|
||||
|
||||
$email->set('from', 'test@tester');
|
||||
$email->set('to', 'test@tester;baraka@tester');
|
||||
$filter = new \Espo\Entities\EmailFilter($this->filterDefs);
|
||||
$filter->set(array(
|
||||
'to' => 'baraka@tester'
|
||||
));
|
||||
$filterList = [$filter];
|
||||
$this->assertTrue($this->object->match($email, $filterList));
|
||||
|
||||
$email->set('subject', 'test hello man');
|
||||
$filter = new \Espo\Entities\EmailFilter($this->filterDefs);
|
||||
$filter->set(array(
|
||||
'subject' => '*hello*'
|
||||
));
|
||||
$filterList = [$filter];
|
||||
$this->assertTrue($this->object->match($email, $filterList));
|
||||
|
||||
$email->set('name', 'test hello man');
|
||||
$filter = new \Espo\Entities\EmailFilter($this->filterDefs);
|
||||
$filter->set(array(
|
||||
'subject' => 'hello'
|
||||
));
|
||||
$filterList = [$filter];
|
||||
$this->assertFalse($this->object->match($email, $filterList));
|
||||
|
||||
}
|
||||
|
||||
function testMatchBody()
|
||||
{
|
||||
$email = new \Espo\Entities\Email($this->emailDefs);
|
||||
$email->set('body', 'hello Man tester');
|
||||
$filter = new \Espo\Entities\EmailFilter($this->filterDefs);
|
||||
$filter->set(array(
|
||||
'bodyContains' => ['man', 'red']
|
||||
));
|
||||
$filterList = [$filter];
|
||||
$this->assertTrue($this->object->matchBody($email, $filterList));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user