mirror of
https://github.com/espocrm/espocrm.git
synced 2026-06-28 06:56:05 +00:00
multiple smtp
This commit is contained in:
@@ -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')
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
@@ -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]
|
||||
]
|
||||
},
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
70
client/src/views/email-account/fields/test-send.js
Normal file
70
client/src/views/email-account/fields/test-send.js
Normal 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;
|
||||
},
|
||||
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@@ -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'));
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user