multiple smtp

This commit is contained in:
yuri
2016-07-08 16:25:27 +03:00
parent 31c2d1360d
commit 36a56f050f
15 changed files with 297 additions and 27 deletions

View File

@@ -47,8 +47,21 @@ class App extends \Espo\Core\Controllers\Base
$user->loadLinkMultipleField('accounts');
}
$userData = $user->getValues();
$emailAddressList = [];
foreach ($user->get('emailAddresses') as $emailAddress) {
if ($emailAddress->get('invalid')) continue;
if ($user->get('emailAddrses') === $emailAddress->get('name')) continue;
$emailAddressList[] = $emailAddress->get('name');
}
if ($user->get('emailAddrses')) {
array_unshift($emailAddressList, $user->get('emailAddrses'));
}
$userData['emailAddressList'] = $emailAddressList;
return array(
'user' => $user->getValues(),
'user' => $userData,
'acl' => $this->getAcl()->getMap(),
'preferences' => $preferences,
'token' => $this->getUser()->get('token')

View File

@@ -32,6 +32,7 @@ namespace Espo\Controllers;
use \Espo\Core\Exceptions\BadRequest;
use \Espo\Core\Exceptions\Forbidden;
use \Espo\Core\Exceptions\Error;
use \Espo\Core\Exceptions\NotFound;
class Email extends \Espo\Core\Controllers\Record
{
@@ -51,22 +52,48 @@ class Email extends \Espo\Core\Controllers\Record
throw new BadRequest();
}
if (!$this->getAcl()->checkScope('Email')) {
throw new Forbidden();
}
if (is_null($data['password'])) {
if ($data['type'] == 'preferences') {
if (!$this->getUser()->isAdmin() && $data['id'] != $this->getUser()->id) {
if (!$this->getUser()->isAdmin() && $data['id'] !== $this->getUser()->id) {
throw new Forbidden();
}
$preferences = $this->getEntityManager()->getEntity('Preferences', $data['id']);
if (!$preferences) {
throw new Error();
throw new NotFound();
}
$data['password'] = $this->getContainer()->get('crypt')->decrypt($preferences->get('smtpPassword'));
if (is_null($data['password'])) {
$data['password'] = $this->getContainer()->get('crypt')->decrypt($preferences->get('smtpPassword'));
}
} else if ($data['type'] == 'emailAccount') {
if (!$this->getAcl()->checkScope('EmailAccount')) {
throw new Forbidden();
}
if (!empty($data['id'])) {
$emailAccount = $this->getEntityManager()->getEntity('EmailAccount', $data['id']);
if (!$emailAccount) {
throw new NotFound();
}
if (!$this->getUser()->isAdmin()) {
if ($emailAccount->get('assigniedUserId') !== $this->getUser()->id) {
throw new Forbidden();
}
}
if (is_null($data['password'])) {
$data['password'] = $this->getContainer()->get('crypt')->decrypt($emailAccount->get('smtpPassword'));
}
}
} else {
if (!$this->getUser()->isAdmin()) {
throw new Forbidden();
}
$data['password'] = $this->getConfig()->get('smtpPassword');
if (is_null($data['password'])) {
$data['password'] = $this->getConfig()->get('smtpPassword');
}
}
}

View File

@@ -153,6 +153,7 @@ class Email extends \Espo\Core\ORM\Repositories\RDB
if (!empty($ids)) {
$entity->set('fromEmailAddressId', $ids[0]);
$this->addUserByEmailAddressId($entity, $ids[0], true);
$entity->setLinkMultipleColumn('users', 'isRead', $ids[0], true);
if (!$entity->get('sentById')) {
$user = $this->getEntityManager()->getRepository('EmailAddress')->getEntityByAddressId($entity->get('fromEmailAddressId'), 'User');

View File

@@ -13,7 +13,14 @@
"sentFolder": "Sent Folder",
"storeSentEmails": "Store Sent Emails",
"keepFetchedEmailsUnread": "Keep Fetched Emails Unread",
"emailFolder": "Put in Folder"
"emailFolder": "Put in Folder",
"useSmtp": "Use SMTP",
"smtpHost": "SMTP Host",
"smtpPort": "SMTP Port",
"smtpAuth": "SMTP Auth",
"smtpSecurity": "SMTP Security",
"smtpUsername": "SMTP Username",
"smtpPassword": "SMTP Password"
},
"links": {
"filters": "Filters",
@@ -29,7 +36,9 @@
"Create EmailAccount": "Create Email Account",
"IMAP": "IMAP",
"Main": "Main",
"Test Connection": "Test Connection"
"Test Connection": "Test Connection",
"Send Test Email": "Send Test Email",
"SMTP": "SMTP"
},
"messages": {
"couldNotConnectToImap": "Could not connect to IMAP server",

View File

@@ -34,7 +34,20 @@
false, {"name":"sentFolder"}
],
[
{"name": "testConnection", "customLabel": null, "view": "EmailAccount.Fields.TestConnection"}, false
{"name": "testConnection", "customLabel": null, "view": "views/email-account/fields/test-connection"}, false
]
]
},
{
"label":"SMTP",
"rows": [
[{"name": "useSmtp"}, false],
[{"name": "smtpHost"}, {"name": "smtpPort"}],
[{"name": "smtpAuth"}, {"name": "smtpSecurity"}],
[{"name": "smtpUsername"}, false],
[{"name": "smtpPassword"}, false],
[
{"name": "smtpTestSend", "customLabel": null, "view": "views/email-account/fields/test-send"}, false
]
]
}

View File

@@ -19,7 +19,7 @@
],
[{"name": "smtpServer"}, {"name": "smtpPort"}],
[{"name": "smtpAuth"}, {"name": "smtpSecurity"}],
[{"name": "smtpUsername"}, {"name": "testSend", "customLabel": null, "view": "Preferences.Fields.TestSend"}],
[{"name": "smtpUsername"}, {"name": "testSend", "customLabel": null, "view": "views/preferences/fields/test-send"}],
[{"name": "smtpPassword"}, false]
]
},

View File

@@ -79,6 +79,33 @@
"type": "link",
"readOnly": true
},
"useSmtp": {
"type": "bool"
},
"smtpHost": {
"type": "varchar"
},
"smtpPort": {
"type": "int",
"min": 0,
"max": 9999,
"default": 25
},
"smtpAuth": {
"type": "bool",
"default": false
},
"smtpSecurity": {
"type": "enum",
"options": ["", "SSL", "TLS"]
},
"smtpUsername": {
"type": "varchar",
"required": true
},
"smtpPassword": {
"type": "password"
},
"createdBy": {
"type": "link",
"readOnly": true

View File

@@ -86,19 +86,39 @@ class Email extends Record
{
$emailSender = $this->getMailSender();
if (strtolower($this->getUser()->get('emailAddress')) == strtolower($entity->get('from'))) {
$smtpParams = $this->getPreferences()->getSmtpParams();
if (array_key_exists('password', $smtpParams)) {
$smtpParams['password'] = $this->getCrypt()->decrypt($smtpParams['password']);
$userAddressList = [];
foreach ($this->getUser()->get('emailAddresses') as $ea) {
$userAddressList[] = $ea->get('lower');
}
$primaryUserAddress = strtolower($this->getUser()->get('emailAddress'));
$fromAddress = strtolower($entity->get('from'));
if (empty($fromAddress)) {
throw new Error();
}
$smtpParams = null;
if (in_array($fromAddress, $userAddressList)) {
if ($primaryUserAddress === $fromAddress) {
$smtpParams = $this->getPreferences()->getSmtpParams();
}
if (!$smtpParams) {
$smtpParams = $this->getSmtpParamsFromEmailAccount($entity->get('from'), $this->getUser()->id);
}
if ($smtpParams) {
if (array_key_exists('password', $smtpParams)) {
$smtpParams['password'] = $this->getCrypt()->decrypt($smtpParams['password']);
}
$smtpParams['fromName'] = $this->getUser()->get('name');
$emailSender->useSmtp($smtpParams);
}
} else {
}
if (!$smtpParams && $fromAddress === strtolower($this->getConfig()->get('outboundEmailFromAddress'))) {
if (!$this->getConfig()->get('outboundEmailIsShared')) {
throw new Error('Can not use system smtp. outboundEmailIsShared is false.');
throw new Error('Can not use system smtp. System SMTP is not shared.');
}
$emailSender->setParams(array(
'fromName' => $this->getUser()->get('name')
@@ -108,7 +128,6 @@ class Email extends Record
$params = array();
$parent = null;
if ($entity->get('parentType') && $entity->get('parentId')) {
$parent = $this->getEntityManager()->getEntity($entity->get('parentType'), $entity->get('parentId'));
if ($parent) {
@@ -160,6 +179,31 @@ class Email extends Record
$this->getEntityManager()->saveEntity($entity);
}
protected function getSmtpParamsFromEmailAccount($address, $userId)
{
$emailAccount = $this->getEntityManager()->getRepository('EmailAccount')->where([
'emailAddress' => $address,
'assignedUserId' => $userId,
'active' => true,
'useSmtp' => true
])->findOne();
if (!$emailAccount) return;
$smtpParams = array();
$smtpParams['server'] = $emailAccount->get('smtpHost');
if ($smtpParams['server']) {
$smtpParams['port'] = $emailAccount->get('smtpPort');
$smtpParams['auth'] = $emailAccount->get('smtpAuth');
$smtpParams['security'] = $emailAccount->get('smtpSecurity');
$smtpParams['username'] = $emailAccount->get('smtpUsername');
$smtpParams['password'] = $emailAccount->get('smtpPassword');
return $smtpParams;
}
return;
}
protected function getStreamService()
{
if (empty($this->streamService)) {

View File

@@ -37,7 +37,7 @@ use \Zend\Mail\Storage;
class EmailAccount extends Record
{
protected $internalAttributeList = ['password'];
protected $internalAttributeList = ['password', 'smtpPassword'];
protected $readOnlyAttributeList= ['fetchData'];
@@ -65,6 +65,9 @@ class EmailAccount extends Record
if (array_key_exists('password', $data)) {
$data['password'] = $this->getCrypt()->encrypt($data['password']);
}
if (array_key_exists('smtpPassword', $data)) {
$data['smtpPassword'] = $this->getCrypt()->encrypt($data['smtpPassword']);
}
}
public function getFolders($params)

View File

@@ -0,0 +1,70 @@
/************************************************************************
* 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/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
Espo.define('views/email-account/fields/test-send', 'views/outbound-email/fields/test-send', function (Dep) {
return Dep.extend({
checkAvailability: function () {
if (this.model.get('smtpHost')) {
this.$el.find('button').removeClass('hidden');
} else {
this.$el.find('button').addClass('hidden');
}
},
afterRender: function () {
this.checkAvailability();
this.stopListening(this.model, 'change:smtpHost');
this.listenTo(this.model, 'change:smtpHost', function () {
this.checkAvailability();
}, this);
},
getSmtpData: function () {
var data = {
'server': this.model.get('smtpHost'),
'port': this.model.get('smtpPort'),
'auth': this.model.get('smtpAuth'),
'security': this.model.get('smtpSecurity'),
'username': this.model.get('smtpUsername'),
'password': this.model.get('smtpPassword') || null,
'fromName': this.getUser().get('name'),
'fromAddress': this.model.get('emailAddress'),
'type': 'emailAccount',
'id': this.model.id
};
return data;
},
});
});

View File

@@ -32,7 +32,9 @@ Espo.define('views/email-account/record/detail', 'views/record/detail', function
afterRender: function () {
Dep.prototype.afterRender.call(this);
this.initSslFieldListening();
this.initSmtpFieldsControl();
if (this.wasFetched()) {
this.setFieldReadOnly('fetchSince');
@@ -64,7 +66,52 @@ Espo.define('views/email-account/record/detail', 'views/record/detail', function
this.model.set('port', '143');
}
}, this);
}
},
initSmtpFieldsControl: function () {
this.controlSmtpFields();
this.listenTo(this.model, 'change:useSmtp', this.controlSmtpFields, this);
this.listenTo(this.model, 'change:smtpAuth', this.controlSmtpAuthField, this);
},
controlSmtpFields: function () {
if (this.model.get('useSmtp')) {
this.showField('smtpHost');
this.showField('smtpPort');
this.showField('smtpAuth');
this.showField('smtpSecurity');
this.showField('smtpTestSend');
this.setFieldRequired('smtpHost');
this.setFieldRequired('smtpPort');
this.controlSmtpAuthField();
} else {
this.hideField('smtpHost');
this.hideField('smtpPort');
this.hideField('smtpAuth');
this.hideField('smtpUsername');
this.hideField('smtpPassword');
this.hideField('smtpSecurity');
this.hideField('smtpTestSend');
this.setFieldNotRequired('smtpHost');
this.setFieldNotRequired('smtpPort');
this.setFieldNotRequired('smtpUsername');
}
},
controlSmtpAuthField: function () {
if (this.model.get('smtpAuth')) {
this.showField('smtpUsername');
this.showField('smtpPassword');
this.setFieldRequired('smtpUsername');
} else {
this.hideField('smtpUsername');
this.hideField('smtpPassword');
this.setFieldNotRequired('smtpUsername');
}
},
});

View File

@@ -34,6 +34,7 @@ Espo.define('views/email-account/record/edit', ['views/record/edit', 'views/emai
Dep.prototype.afterRender.call(this);
Detail.prototype.initSslFieldListening.call(this);
Detail.prototype.initSmtpFieldsControl.call(this);
if (Detail.prototype.wasFetched.call(this)) {
this.setFieldReadOnly('fetchSince');
@@ -47,6 +48,14 @@ Espo.define('views/email-account/record/edit', ['views/record/edit', 'views/emai
fieldView.render();
}
}
},
controlSmtpFields: function () {
Detail.prototype.controlSmtpFields.call(this);
},
controlSmtpAuthField: function () {
Detail.prototype.controlSmtpAuthField.call(this);
}
});

View File

@@ -42,12 +42,20 @@ Espo.define('views/email/fields/compose-from-address', 'views/fields/base', func
Dep.prototype.setup.call(this);
this.list = [];
if (this.getUser().get('emailAddress') && this.getPreferences().get('smtpServer')) {
/*if (this.getUser().get('emailAddress') && this.getPreferences().get('smtpServer')) {
this.list.push(this.getUser().get('emailAddress'));
}
}*/
var emailAddressList = this.getUser().get('emailAddressList') || [];
emailAddressList.forEach(function (item) {
this.list.push(item);
}, this);
if (this.getConfig().get('outboundEmailIsShared') && this.getConfig().get('outboundEmailFromAddress')) {
this.list.push(this.getConfig().get('outboundEmailFromAddress'));
var address = this.getConfig().get('outboundEmailFromAddress');
if (!~this.list.indexOf(address)) {
this.list.push(this.getConfig().get('outboundEmailFromAddress'));
}
}
},
});

View File

@@ -26,7 +26,7 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
Espo.define('Views.OutboundEmail.Fields.TestSend', 'Views.Fields.Base', function (Dep) {
Espo.define('views/outbound-email/fields/test-send', 'views/fields/base', function (Dep) {
return Dep.extend({
@@ -79,7 +79,7 @@ Espo.define('Views.OutboundEmail.Fields.TestSend', 'Views.Fields.Base', function
send: function () {
var data = this.getSmtpData();
this.createView('popup', 'OutboundEmail.Modals.TestSend', {
this.createView('popup', 'views/outbound-email/modals/test-send', {
emailAddress: this.getUser().get('emailAddress')
}, function (view) {
view.render();

View File

@@ -26,15 +26,15 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
Espo.define('Views.Preferences.Fields.TestSend', 'Views.OutboundEmail.Fields.TestSend', function (Dep) {
Espo.define('views/preferences/fields/test-send', 'views/outbound-email/fields/test-send', function (Dep) {
return Dep.extend({
checkAvailability: function () {
if (this.model.get('smtpServer')) {
this.$el.find('button').removeClass('disabled');
this.$el.find('button').removeClass('hidden');
} else {
this.$el.find('button').addClass('disabled');
this.$el.find('button').addClass('hidden');
}
},
@@ -42,7 +42,6 @@ Espo.define('Views.Preferences.Fields.TestSend', 'Views.OutboundEmail.Fields.Tes
this.checkAvailability();
this.stopListening(this.model, 'change:smtpServer');
this.listenTo(this.model, 'change:smtpServer', function () {
this.checkAvailability();
}, this);