mirror of
https://github.com/the-djmaze/snappymail.git
synced 2024-12-25 00:21:29 +08:00
Added counters of unread messages for additional accounts (#377)
This commit is contained in:
parent
abddb3d828
commit
79233ad83c
19 changed files with 333 additions and 93 deletions
|
@ -494,15 +494,23 @@
|
|||
|
||||
AppUser.prototype.accountsCounts = function ()
|
||||
{
|
||||
AccountStore.accounts.loading(true);
|
||||
|
||||
Remote.accountsCounts(function (sResult, oData) {
|
||||
|
||||
AccountStore.accounts.loading(false);
|
||||
|
||||
if (Enums.StorageResultType.Success === sResult && oData.Result && oData.Result['Counts'])
|
||||
{
|
||||
var aAcounts = AccountStore.collection();
|
||||
var
|
||||
sEmail = Data.accountEmail(),
|
||||
aAcounts = AccountStore.accounts()
|
||||
;
|
||||
|
||||
_.each(oData.Result['Counts'], function (oItem) {
|
||||
|
||||
var oAccount = _.find(aAcounts, function (oAccount) {
|
||||
return oAccount && oItem[0] === oAccount.email;
|
||||
return oAccount && oItem[0] === oAccount.email && sEmail !== oAccount.email;
|
||||
});
|
||||
|
||||
if (oAccount)
|
||||
|
@ -518,12 +526,12 @@
|
|||
{
|
||||
var self = this;
|
||||
|
||||
AccountStore.loading(true);
|
||||
AccountStore.accounts.loading(true);
|
||||
IdentityStore.identities.loading(true);
|
||||
|
||||
Remote.accountsAndIdentities(function (sResult, oData) {
|
||||
|
||||
AccountStore.loading(false);
|
||||
AccountStore.accounts.loading(false);
|
||||
IdentityStore.identities.loading(false);
|
||||
|
||||
if (Enums.StorageResultType.Success === sResult && oData.Result)
|
||||
|
@ -538,20 +546,26 @@
|
|||
|
||||
if (Utils.isArray(oData.Result['Accounts']))
|
||||
{
|
||||
_.each(AccountStore.collection(), function (oAccount) {
|
||||
_.each(AccountStore.accounts(), function (oAccount) {
|
||||
aCounts[oAccount.email] = oAccount.count();
|
||||
});
|
||||
|
||||
Utils.delegateRunOnDestroy(AccountStore.collection());
|
||||
Utils.delegateRunOnDestroy(AccountStore.accounts());
|
||||
|
||||
AccountStore.collection(_.map(oData.Result['Accounts'], function (sValue) {
|
||||
AccountStore.accounts(_.map(oData.Result['Accounts'], function (sValue) {
|
||||
return new AccountModel(sValue, sValue !== sParentEmail, aCounts[sValue] || 0);
|
||||
}));
|
||||
}
|
||||
|
||||
if (Utils.isUnd(bBoot) ? false : !!bBoot)
|
||||
{
|
||||
self.accountsCounts();
|
||||
_.delay(function () {
|
||||
self.accountsCounts();
|
||||
}, 1000 * 5);
|
||||
|
||||
Events.sub('interval.10m-after5m', function () {
|
||||
self.accountsCounts();
|
||||
});
|
||||
}
|
||||
|
||||
if (Utils.isArray(oData.Result['Identities']))
|
||||
|
|
|
@ -48,7 +48,10 @@
|
|||
{
|
||||
if (null === this.selectedItem())
|
||||
{
|
||||
this.selectedItem.valueHasMutated();
|
||||
if (this.selectedItem.valueHasMutated)
|
||||
{
|
||||
this.selectedItem.valueHasMutated();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
2
dev/External/ko.js
vendored
2
dev/External/ko.js
vendored
|
@ -828,7 +828,7 @@
|
|||
oTarget('');
|
||||
}
|
||||
}
|
||||
})
|
||||
}).extend({'notify': 'always'})
|
||||
;
|
||||
|
||||
oResult(oTarget());
|
||||
|
|
|
@ -127,7 +127,7 @@
|
|||
}
|
||||
},
|
||||
'owner': this
|
||||
});
|
||||
}).extend({'notify': 'always'});
|
||||
|
||||
this.messageCountUnread = ko.computed({
|
||||
'read': this.privateMessageCountUnread,
|
||||
|
@ -142,7 +142,7 @@
|
|||
}
|
||||
},
|
||||
'owner': this
|
||||
});
|
||||
}).extend({'notify': 'always'});
|
||||
|
||||
this.printableUnreadCount = ko.computed(function () {
|
||||
var
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
Events = require('Common/Events'),
|
||||
Translator = require('Common/Translator'),
|
||||
|
||||
AccountStore = require('Stores/User/Account'),
|
||||
SettingsStore = require('Stores/User/Settings'),
|
||||
|
||||
Data = require('Storage/User/Data'),
|
||||
|
@ -111,8 +112,18 @@
|
|||
SettingsStore.layout.valueHasMutated();
|
||||
}, 50);
|
||||
|
||||
Events.sub('mailbox.inbox-unread-count', function (nCount) {
|
||||
Data.foldersInboxUnreadCount(nCount);
|
||||
Events.sub('mailbox.inbox-unread-count', function (iCount) {
|
||||
|
||||
Data.foldersInboxUnreadCount(iCount);
|
||||
|
||||
var sEmail = Data.accountEmail();
|
||||
|
||||
_.each(AccountStore.accounts(), function (oItem) {
|
||||
if (oItem && sEmail === oItem.email)
|
||||
{
|
||||
oItem.count(iCount);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Data.foldersInboxUnreadCount.subscribe(function () {
|
||||
|
|
|
@ -96,7 +96,7 @@
|
|||
this.contactsType.valueHasMutated();
|
||||
}
|
||||
}
|
||||
});
|
||||
}).extend({'notify': 'always'});
|
||||
|
||||
this.contactsType.subscribe(function () {
|
||||
this.testContactsSuccess(false);
|
||||
|
|
|
@ -22,10 +22,10 @@
|
|||
*/
|
||||
function AccountsUserSettings()
|
||||
{
|
||||
this.accounts = AccountStore.collection;
|
||||
this.accounts = AccountStore.accounts;
|
||||
|
||||
this.processText = ko.computed(function () {
|
||||
return AccountStore.loading() ? Translator.i18n('SETTINGS_ACCOUNTS/LOADING_PROCESS') : '';
|
||||
return AccountStore.accounts.loading() ? Translator.i18n('SETTINGS_ACCOUNTS/LOADING_PROCESS') : '';
|
||||
}, this);
|
||||
|
||||
this.visibility = ko.computed(function () {
|
||||
|
|
|
@ -238,8 +238,7 @@
|
|||
*/
|
||||
RemoteUserStorage.prototype.accountsCounts = function (fCallback)
|
||||
{
|
||||
return !!fCallback; // TODO
|
||||
// this.defaultRequest(fCallback, 'AccountsCounts');
|
||||
this.defaultRequest(fCallback, 'AccountsCounts');
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -15,28 +15,43 @@
|
|||
*/
|
||||
function AccountUserStore()
|
||||
{
|
||||
this.loading = ko.observable(false).extend({'throttle': 100});
|
||||
this.accounts = ko.observableArray([]);
|
||||
this.accounts.loading = ko.observable(false).extend({'throttle': 100});
|
||||
|
||||
this.collection = ko.observableArray([]);
|
||||
this.collectionEmailNames = ko.observableArray([]).extend({'throttle': 1000});
|
||||
this.collectionEmailNames.skipFirst = true;
|
||||
this.accountsEmailNames = ko.observableArray([]).extend({'throttle': 1000});
|
||||
this.accountsEmailNames.skipFirst = true;
|
||||
|
||||
this.collection.subscribe(function (aList) {
|
||||
this.collectionEmailNames(_.compact(_.map(aList, function (oItem) {
|
||||
this.accounts.subscribe(function (aList) {
|
||||
this.accountsEmailNames(_.compact(_.map(aList, function (oItem) {
|
||||
return oItem ? oItem.email : null;
|
||||
})));
|
||||
}, this);
|
||||
|
||||
this.collectionEmailNames.subscribe(function (aList) {
|
||||
if (this.collectionEmailNames.skipFirst)
|
||||
this.accountsEmailNames.subscribe(function (aList) {
|
||||
if (this.accountsEmailNames.skipFirst)
|
||||
{
|
||||
this.collectionEmailNames.skipFirst = false;
|
||||
this.accountsEmailNames.skipFirst = false;
|
||||
}
|
||||
else if (aList && 1 < aList.length)
|
||||
{
|
||||
Remote.accountSortOrder(null, aList);
|
||||
}
|
||||
}, this);
|
||||
|
||||
this.accountsUnreadCount = ko.computed(function () {
|
||||
|
||||
var iResult = 0;
|
||||
|
||||
_.each(this.accounts(), function (oItem) {
|
||||
if (oItem)
|
||||
{
|
||||
iResult += oItem.count();
|
||||
}
|
||||
});
|
||||
|
||||
return iResult;
|
||||
|
||||
}, this);
|
||||
}
|
||||
|
||||
module.exports = new AccountUserStore();
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
|
||||
return iResult;
|
||||
|
||||
}, this);
|
||||
}, this).extend({'notify': 'always'});
|
||||
|
||||
this.enableDesktopNotification = ko.computed({
|
||||
'owner': this,
|
||||
|
@ -117,7 +117,7 @@
|
|||
this.allowDesktopNotification(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}).extend({'notify': 'always'});
|
||||
|
||||
if (!this.enableDesktopNotification.valueHasMutated)
|
||||
{
|
||||
|
@ -150,7 +150,8 @@
|
|||
this.soundNotificationIsSupported(true);
|
||||
|
||||
this.buzz = new buzz.sound(Links.sound('new-mail'), {
|
||||
formats: ['ogg', 'mp3']
|
||||
'preload': 'none',
|
||||
'formats': ['mp3', 'ogg']
|
||||
});
|
||||
}
|
||||
else
|
||||
|
|
|
@ -41,9 +41,6 @@
|
|||
color: #fff;
|
||||
text-shadow: 0 1px 0 #000;
|
||||
|
||||
position: absolute;
|
||||
top: 11px;
|
||||
right: 70px;
|
||||
display: inline-block;
|
||||
height: 28px;
|
||||
max-width: 250px;
|
||||
|
@ -55,6 +52,7 @@
|
|||
text-overflow: ellipsis;
|
||||
border-radius: 4px;
|
||||
font-weight: bold;
|
||||
margin-right: 5px;
|
||||
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
|
|
@ -29,18 +29,14 @@
|
|||
{
|
||||
AbstractView.call(this, 'Right', 'SystemDropDown');
|
||||
|
||||
this.accounts = AccountStore.collection;
|
||||
this.accountEmail = Data.accountEmail;
|
||||
this.accountsLoading = AccountStore.loading;
|
||||
|
||||
this.accounts = AccountStore.accounts;
|
||||
this.accountsUnreadCount = AccountStore.accountsUnreadCount;
|
||||
|
||||
this.accountMenuDropdownTrigger = ko.observable(false);
|
||||
|
||||
this.capaAdditionalAccounts = ko.observable(Settings.capa(Enums.Capa.AdditionalAccounts));
|
||||
|
||||
this.loading = ko.computed(function () {
|
||||
return this.accountsLoading();
|
||||
}, this);
|
||||
|
||||
this.accountClick = _.bind(this.accountClick, this);
|
||||
}
|
||||
|
||||
|
@ -50,10 +46,10 @@
|
|||
{
|
||||
if (oAccount && oEvent && !Utils.isUnd(oEvent.which) && 1 === oEvent.which)
|
||||
{
|
||||
var self = this;
|
||||
this.accountsLoading(true);
|
||||
AccountStore.accounts.loading(true);
|
||||
|
||||
_.delay(function () {
|
||||
self.accountsLoading(false);
|
||||
AccountStore.accounts.loading(false);
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"name": "RainLoop",
|
||||
"title": "RainLoop Webmail",
|
||||
"version": "1.7.3",
|
||||
"release": "241",
|
||||
"release": "243",
|
||||
"description": "Simple, modern & fast web-based email client",
|
||||
"homepage": "http://rainloop.net",
|
||||
"main": "gulpfile.js",
|
||||
|
|
|
@ -337,11 +337,11 @@ class Http
|
|||
}
|
||||
|
||||
/**
|
||||
* @param bool $bCheckProxy = true
|
||||
* @param bool $bCheckProxy = false
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function GetClientIp($bCheckProxy = true)
|
||||
public function GetClientIp($bCheckProxy = false)
|
||||
{
|
||||
$sIp = '';
|
||||
if ($bCheckProxy && null !== $this->GetServer('HTTP_CLIENT_IP', null))
|
||||
|
|
|
@ -44,8 +44,10 @@ class Logger extends \MailSo\Base\Collection
|
|||
|
||||
/**
|
||||
* @access protected
|
||||
*
|
||||
* @param bool $bRegPhpErrorHandler = false
|
||||
*/
|
||||
protected function __construct()
|
||||
protected function __construct($bRegPhpErrorHandler = true)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
|
@ -55,16 +57,22 @@ class Logger extends \MailSo\Base\Collection
|
|||
$this->bShowSecter = false;
|
||||
$this->bHideErrorNotices = false;
|
||||
|
||||
\set_error_handler(array(&$this, '__phpErrorHandler'));
|
||||
if ($bRegPhpErrorHandler)
|
||||
{
|
||||
\set_error_handler(array(&$this, '__phpErrorHandler'));
|
||||
}
|
||||
|
||||
\register_shutdown_function(array(&$this, '__loggerShutDown'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bRegPhpErrorHandler = false
|
||||
*
|
||||
* @return \MailSo\Log\Logger
|
||||
*/
|
||||
public static function NewInstance()
|
||||
public static function NewInstance($bRegPhpErrorHandler = false)
|
||||
{
|
||||
return new self();
|
||||
return new self($bRegPhpErrorHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -869,6 +869,24 @@ class MailClient
|
|||
return self::GenerateHash($sFolderName, $iCount, $iUnseenCount, $sUidNext);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*
|
||||
* @throws \MailSo\Net\Exceptions\Exception
|
||||
* @throws \MailSo\Imap\Exceptions\Exception
|
||||
*/
|
||||
public function InboxUnreadCount()
|
||||
{
|
||||
$aFolderStatus = $this->oImapClient->FolderStatus('INBOX', array(
|
||||
\MailSo\Imap\Enumerations\FolderResponseStatus::UNSEEN
|
||||
));
|
||||
|
||||
$iResult = isset($aFolderStatus[\MailSo\Imap\Enumerations\FolderResponseStatus::UNSEEN]) ?
|
||||
(int) $aFolderStatus[\MailSo\Imap\Enumerations\FolderResponseStatus::UNSEEN] : 0;
|
||||
|
||||
return 0 < $iResult ? $iResult : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sSearch
|
||||
* @param bool $bDetectGmail = true
|
||||
|
|
|
@ -40,6 +40,11 @@ class Actions
|
|||
*/
|
||||
private $oLogger;
|
||||
|
||||
/**
|
||||
* @var \MailSo\Log\Logger
|
||||
*/
|
||||
private $oLoggerAuth;
|
||||
|
||||
/**
|
||||
* @var \RainLoop\Social
|
||||
*/
|
||||
|
@ -359,60 +364,119 @@ class Actions
|
|||
}
|
||||
|
||||
/**
|
||||
* @param string $sLine
|
||||
* @param \RainLoop\Model\Account $oAccount = null
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function compileLogFileName()
|
||||
private function compileLogParams($sLine, $oAccount = null)
|
||||
{
|
||||
$sFileName = (string) $this->Config()->Get('logs', 'filename', '');
|
||||
|
||||
if (false !== \strpos($sFileName, '{date:'))
|
||||
if (false !== \strpos($sLine, '{date:'))
|
||||
{
|
||||
$sFileName = \preg_replace_callback('/\{date:([^}]+)\}/', function ($aMatch) {
|
||||
$sLine = \preg_replace_callback('/\{date:([^}]+)\}/', function ($aMatch) {
|
||||
return \gmdate($aMatch[1]);
|
||||
}, $sFileName);
|
||||
}, $sLine);
|
||||
|
||||
$sFileName = \preg_replace('/\{date:([^}]*)\}/', 'date', $sFileName);
|
||||
$sLine = \preg_replace('/\{date:([^}]*)\}/', 'date', $sLine);
|
||||
}
|
||||
|
||||
if (false !== \strpos($sFileName, '{user:'))
|
||||
if (false !== \strpos($sLine, '{imap:') || false !== \strpos($sLine, '{smtp:'))
|
||||
{
|
||||
if (false !== \strpos($sFileName, '{user:uid}'))
|
||||
if (!$oAccount)
|
||||
{
|
||||
$sFileName = \str_replace('{user:uid}',
|
||||
$this->ParseQueryAuthString();
|
||||
$oAccount = $this->getAccountFromToken(false);
|
||||
}
|
||||
|
||||
if ($oAccount)
|
||||
{
|
||||
$sLine = \str_replace('{imap:login}', $oAccount->IncLogin(), $sLine);
|
||||
$sLine = \str_replace('{imap:host}', $oAccount->DomainIncHost(), $sLine);
|
||||
$sLine = \str_replace('{imap:port}', $oAccount->DomainIncPort(), $sLine);
|
||||
|
||||
$sLine = \str_replace('{smtp:login}', $oAccount->OutLogin(), $sLine);
|
||||
$sLine = \str_replace('{smtp:host}', $oAccount->DomainOutHost(), $sLine);
|
||||
$sLine = \str_replace('{smtp:port}', $oAccount->DomainOutPort(), $sLine);
|
||||
}
|
||||
|
||||
$sLine = \preg_replace('/\{imap:([^}]*)\}/i', 'imap', $sLine);
|
||||
$sLine = \preg_replace('/\{smtp:([^}]*)\}/i', 'imap', $sLine);
|
||||
}
|
||||
|
||||
if (false !== \strpos($sLine, '{request:'))
|
||||
{
|
||||
if (false !== \strpos($sLine, '{request:ip}'))
|
||||
{
|
||||
$sLine = \str_replace('{request:ip}', $this->Http()->GetClientIp(
|
||||
$this->Config()->Get('labs', 'http_client_ip_check_proxy', false)), $sLine);
|
||||
}
|
||||
|
||||
$sLine = \preg_replace('/\{request:([^}]*)\}/i', 'request', $sLine);
|
||||
}
|
||||
|
||||
if (false !== \strpos($sLine, '{user:'))
|
||||
{
|
||||
if (false !== \strpos($sLine, '{user:uid}'))
|
||||
{
|
||||
$sLine = \str_replace('{user:uid}',
|
||||
\base_convert(\sprintf('%u', \crc32(\md5(\RainLoop\Utils::GetConnectionToken()))), 10, 32),
|
||||
$sFileName
|
||||
$sLine
|
||||
);
|
||||
}
|
||||
|
||||
if (false !== \strpos($sFileName, '{user:ip}'))
|
||||
if (false !== \strpos($sLine, '{user:ip}'))
|
||||
{
|
||||
$sFileName = \str_replace('{user:ip}', $this->Http()->GetClientIp(), $sFileName);
|
||||
$sLine = \str_replace('{user:ip}', $this->Http()->GetClientIp(
|
||||
$this->Config()->Get('labs', 'http_client_ip_check_proxy', false)), $sLine);
|
||||
}
|
||||
|
||||
if (\preg_match('/\{user:(email|login|domain)\}/i', $sFileName))
|
||||
if (\preg_match('/\{user:(email|login|domain)\}/i', $sLine))
|
||||
{
|
||||
$this->ParseQueryAuthString();
|
||||
if (!$oAccount)
|
||||
{
|
||||
$this->ParseQueryAuthString();
|
||||
$oAccount = $this->getAccountFromToken(false);
|
||||
}
|
||||
|
||||
$oAccount = $this->getAccountFromToken(false);
|
||||
if ($oAccount)
|
||||
{
|
||||
$sEmail = $oAccount->Email();
|
||||
$sFileName = \str_replace('{user:email}', $sEmail, $sFileName);
|
||||
$sFileName = \str_replace('{user:login}', \MailSo\Base\Utils::GetAccountNameFromEmail($sEmail), $sFileName);
|
||||
$sFileName = \str_replace('{user:domain}', \MailSo\Base\Utils::GetDomainFromEmail($sEmail), $sFileName);
|
||||
$sLine = \str_replace('{user:email}', $sEmail, $sLine);
|
||||
$sLine = \str_replace('{user:login}', \MailSo\Base\Utils::GetAccountNameFromEmail($sEmail), $sLine);
|
||||
$sLine = \str_replace('{user:domain}', \MailSo\Base\Utils::GetDomainFromEmail($sEmail), $sLine);
|
||||
}
|
||||
}
|
||||
|
||||
$sFileName = \preg_replace('/\{user:([^}]*)\}/i', 'unknown', $sFileName);
|
||||
$sLine = \preg_replace('/\{user:([^}]*)\}/i', 'unknown', $sLine);
|
||||
}
|
||||
|
||||
if (false !== \strpos($sFileName, '{labs:'))
|
||||
if (false !== \strpos($sLine, '{labs:'))
|
||||
{
|
||||
$sFileName = \preg_replace_callback('/\{labs:rand:([1-9])\}/', function ($aMatch) {
|
||||
$sLine = \preg_replace_callback('/\{labs:rand:([1-9])\}/', function ($aMatch) {
|
||||
return \rand(\pow(10, $aMatch[1] - 1), \pow(10, $aMatch[1]) - 1);
|
||||
}, $sFileName);
|
||||
}, $sLine);
|
||||
|
||||
$sFileName = \preg_replace('/\{labs:([^}]*)\}/', 'labs', $sFileName);
|
||||
$sLine = \preg_replace('/\{labs:([^}]*)\}/', 'labs', $sLine);
|
||||
}
|
||||
|
||||
return $sLine;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sFileName
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function compileLogFileName($sFileName)
|
||||
{
|
||||
$sFileName = \trim($sFileName);
|
||||
|
||||
if (0 !== \strlen($sFileName))
|
||||
{
|
||||
$sFileName = $this->compileLogParams($sFileName);
|
||||
|
||||
$sFileName = \preg_replace('/[\/]+/', '/', \preg_replace('/[.]+/', '.', $sFileName));
|
||||
$sFileName = \preg_replace('/[^a-zA-Z0-9@_+=\-\.\/!()\[\]]/', '', $sFileName);
|
||||
}
|
||||
|
||||
if (0 === \strlen($sFileName))
|
||||
|
@ -420,9 +484,6 @@ class Actions
|
|||
$sFileName = 'rainloop-log.txt';
|
||||
}
|
||||
|
||||
$sFileName = \preg_replace('/[\/]+/', '/', \preg_replace('/[.]+/', '.', $sFileName));
|
||||
$sFileName = \preg_replace('/[^a-zA-Z0-9@_+=\-\.\/!()\[\]]/', '', $sFileName);
|
||||
|
||||
return $sFileName;
|
||||
}
|
||||
|
||||
|
@ -775,11 +836,13 @@ class Actions
|
|||
{
|
||||
$this->oLogger = \MailSo\Log\Logger::SingletonInstance();
|
||||
|
||||
if (!!$this->Config()->Get('logs', 'enable', true))
|
||||
if (!!$this->Config()->Get('logs', 'enable', false))
|
||||
{
|
||||
$this->oLogger->SetShowSecter(!$this->Config()->Get('logs', 'hide_passwords', true));
|
||||
|
||||
$sLogFileFullPath = \APP_PRIVATE_DATA.'logs/'.$this->compileLogFileName();
|
||||
$sLogFileFullPath = \APP_PRIVATE_DATA.'logs/'.$this->compileLogFileName(
|
||||
$this->Config()->Get('logs', 'filename', ''));
|
||||
|
||||
$sLogFileDir = \dirname($sLogFileFullPath);
|
||||
|
||||
if (!@is_dir($sLogFileDir))
|
||||
|
@ -804,7 +867,8 @@ class Actions
|
|||
$oHttp = $this->Http();
|
||||
|
||||
$this->oLogger->Write('[DATE:'.\gmdate('d.m.y').'][RL:'.APP_VERSION.'][PHP:'.PHP_VERSION.'][IP:'.
|
||||
$oHttp->GetClientIp().'][PID:'.(\MailSo\Base\Utils::FunctionExistsAndEnabled('getmypid') ? \getmypid() : 'unknown').']['.
|
||||
$oHttp->GetClientIp($this->Config()->Get('labs', 'http_client_ip_check_proxy', false)).'][PID:'.
|
||||
(\MailSo\Base\Utils::FunctionExistsAndEnabled('getmypid') ? \getmypid() : 'unknown').']['.
|
||||
$oHttp->GetServer('SERVER_SOFTWARE', '~').']['.
|
||||
(\MailSo\Base\Utils::FunctionExistsAndEnabled('php_sapi_name') ? \php_sapi_name() : '~' ).']'
|
||||
);
|
||||
|
@ -829,6 +893,40 @@ class Actions
|
|||
return $this->oLogger;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \MailSo\Log\Logger
|
||||
*/
|
||||
public function LoggerAuth()
|
||||
{
|
||||
if (null === $this->oLoggerAuth)
|
||||
{
|
||||
$this->oLoggerAuth = \MailSo\Log\Logger::NewInstance(false);
|
||||
|
||||
if (!!$this->Config()->Get('logs', 'auth_logging', false))
|
||||
{
|
||||
$sAuthLogFileFullPath = \APP_PRIVATE_DATA.'logs/'.$this->compileLogFileName(
|
||||
$this->Config()->Get('logs', 'auth_logging_filename', ''));
|
||||
|
||||
$sLogFileDir = \dirname($sAuthLogFileFullPath);
|
||||
|
||||
if (!@is_dir($sLogFileDir))
|
||||
{
|
||||
@mkdir($sLogFileDir, 0755, true);
|
||||
}
|
||||
|
||||
$this->oLoggerAuth->AddForbiddenType(\MailSo\Log\Enumerations\Type::MEMORY);
|
||||
$this->oLoggerAuth->AddForbiddenType(\MailSo\Log\Enumerations\Type::TIME);
|
||||
$this->oLoggerAuth->AddForbiddenType(\MailSo\Log\Enumerations\Type::TIME_DELTA);
|
||||
|
||||
$this->oLoggerAuth->Add(
|
||||
\MailSo\Log\Drivers\File::NewInstance($sAuthLogFileFullPath)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->oLoggerAuth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
|
@ -1524,10 +1622,11 @@ class Actions
|
|||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
* @param bool $bAuthLog = false
|
||||
*
|
||||
* @throws \RainLoop\Exceptions\ClientException
|
||||
*/
|
||||
public function CheckMailConnection($oAccount)
|
||||
public function CheckMailConnection($oAccount, $bAuthLog = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -1543,6 +1642,16 @@ class Actions
|
|||
}
|
||||
catch (\MailSo\Imap\Exceptions\LoginBadCredentialsException $oException)
|
||||
{
|
||||
if ($bAuthLog)
|
||||
{
|
||||
$sLine = $this->Config()->Get('logs', 'auth_logging_format', '');
|
||||
if (!empty($sLine))
|
||||
{
|
||||
$this->LoggerAuth()->Write($this->compileLogParams($sLine, $oAccount),
|
||||
\MailSo\Log\Enumerations\Type::WARNING, 'IMAP');
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->Config()->Get('labs', 'imap_show_login_alert', true))
|
||||
{
|
||||
throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::AuthError,
|
||||
|
@ -1724,7 +1833,7 @@ class Actions
|
|||
|
||||
try
|
||||
{
|
||||
$this->CheckMailConnection($oAccount);
|
||||
$this->CheckMailConnection($oAccount, true);
|
||||
}
|
||||
catch (\Exception $oException)
|
||||
{
|
||||
|
@ -2373,6 +2482,40 @@ class Actions
|
|||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sHash
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @throws \MailSo\Base\Exceptions\Exception
|
||||
*/
|
||||
public function getAccountUnredCountFromHash($sHash)
|
||||
{
|
||||
$iResult = 0;
|
||||
|
||||
$oAccount = $this->GetAccountFromCustomToken($sHash, false);
|
||||
if ($oAccount)
|
||||
{
|
||||
try
|
||||
{
|
||||
$oMailClient = \MailSo\Mail\MailClient::NewInstance();
|
||||
$oMailClient->SetLogger($this->Logger());
|
||||
|
||||
$oAccount->IncConnectAndLoginHelper($this->Plugins(),$oMailClient, $this->Config());
|
||||
|
||||
$iResult = $oMailClient->InboxUnreadCount();
|
||||
|
||||
$oMailClient->LogoutAndDisconnect();
|
||||
}
|
||||
catch (\Exception $oException)
|
||||
{
|
||||
$this->Logger()->WriteException($oException);
|
||||
}
|
||||
}
|
||||
|
||||
return $iResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*
|
||||
|
@ -2382,13 +2525,32 @@ class Actions
|
|||
{
|
||||
$oAccount = $this->getAccountFromToken();
|
||||
|
||||
$bComplete = true;
|
||||
$aCounts = array();
|
||||
|
||||
if ($this->Config()->Get('webmail', 'allow_additional_accounts', true))
|
||||
{
|
||||
$iLimit = 7;
|
||||
$mAccounts = $this->GetAccounts($oAccount);
|
||||
foreach ($mAccounts as $sEmail => $sHash)
|
||||
if (\is_array($mAccounts) && 0 < \count($mAccounts))
|
||||
{
|
||||
$aCounts[] = array(\MailSo\Base\Utils::IdnToUtf8($sEmail), 0);
|
||||
if ($iLimit > \count($mAccounts))
|
||||
{
|
||||
$mAccounts = \array_slice($mAccounts, 0, $iLimit);
|
||||
}
|
||||
else
|
||||
{
|
||||
$bComplete = false;
|
||||
}
|
||||
|
||||
if (0 < \count($mAccounts))
|
||||
{
|
||||
foreach ($mAccounts as $sEmail => $sHash)
|
||||
{
|
||||
$aCounts[] = array(\MailSo\Base\Utils::IdnToUtf8($sEmail),
|
||||
$oAccount->Email() === $sEmail ? 0 : $this->getAccountUnredCountFromHash($sHash));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -2397,7 +2559,7 @@ class Actions
|
|||
}
|
||||
|
||||
return $this->DefaultResponse(__FUNCTION__, array(
|
||||
'Complete' => true,
|
||||
'Complete' => $bComplete,
|
||||
'Counts' => $aCounts
|
||||
));
|
||||
}
|
||||
|
|
|
@ -188,12 +188,22 @@ Patterns:
|
|||
{user:domain} - Replaced by user\'s domain name (the domain part of an email)
|
||||
If user is not logged in, value is set to "unknown"
|
||||
{user:uid} - Replaced by user\'s UID regardless of account currently used
|
||||
{user:ip} - Replaced by user\'s IP address
|
||||
|
||||
{user:ip}
|
||||
{request:ip} - Replaced by user\'s IP address
|
||||
|
||||
Others:
|
||||
{imap:login} {imap:host} {imap:port}
|
||||
{smtp:login} {smtp:host} {smtp:port}
|
||||
|
||||
Examples:
|
||||
filename = "log-{date:Y-m-d}.txt"
|
||||
filename = "{date:Y-m-d}/{user:domain}/{user:email}_{user:uid}.log"
|
||||
filename = "{user:email}-{date:Y-m-d}.txt"')
|
||||
filename = "{user:email}-{date:Y-m-d}.txt"'),
|
||||
|
||||
'auth_logging' => array(false, 'Enable auth logging in a separate file (for fail2ban)'),
|
||||
'auth_logging_filename' => array('fail2ban/auth-{date:Y-m-d}.txt'),
|
||||
'auth_logging_format' => array('Auth failed: ip={request:ip} user={imap:login} host={imap:host} port={imap:port}')
|
||||
),
|
||||
|
||||
'debug' => array(
|
||||
|
@ -287,6 +297,7 @@ Enables caching in the system'),
|
|||
'allow_external_login' => array(false),
|
||||
'allow_external_sso' => array(false),
|
||||
'external_sso_key' => array(''),
|
||||
'http_client_ip_check_proxy' => array(false),
|
||||
'fast_cache_memcache_host' => array('127.0.0.1'),
|
||||
'fast_cache_memcache_port' => array(11211),
|
||||
'fast_cache_memcache_expire' => array(43200),
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
<div class="b-system-drop-down g-ui-user-select-none">
|
||||
<div class="b-toolbar">
|
||||
<div class="btn-toolbar">
|
||||
<div class="accountPlace" data-bind="text: emailTitle()"></div>
|
||||
<div class="btn-group pull-right dropdown colored-toggle" data-bind="registrateBootstrapDropdown: true, openDropdownTrigger: accountMenuDropdownTrigger">
|
||||
<a id="top-system-dropdown-id" href="#" tabindex="-1" class="btn btn-ellipsis btn-block dropdown-toggle system-dropdown" data-toggle="dropdown">
|
||||
<i data-bind="css: {'icon-user': !loading(), 'icon-spinner animated': loading()}"
|
||||
></i> <span class="caret"></span>
|
||||
<i data-bind="css: {'icon-user': !accounts.loading(), 'icon-spinner animated': accounts.loading()}"
|
||||
></i>
|
||||
|
||||
<b data-bind="text: accountsUnreadCount, visible: 100 > accountsUnreadCount() && 0 < accountsUnreadCount()"></b>
|
||||
<b data-bind="visible: 99 < accountsUnreadCount()">99+</b>
|
||||
|
||||
<span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu g-ui-menu" tabindex="-1" role="menu" aria-labelledby="top-system-dropdown-id">
|
||||
|
||||
|
@ -21,7 +25,7 @@
|
|||
<i class="icon-ok"></i>
|
||||
<i class="icon-user"></i>
|
||||
|
||||
<span class="email-title" data-bind="text: email"></span>
|
||||
<span class="email-title" data-bind="text: email, attr: {title: email}"></span>
|
||||
</a>
|
||||
</li>
|
||||
<!-- /ko -->
|
||||
|
@ -59,9 +63,9 @@
|
|||
<span class="i18n" data-i18n-text="TOP_TOOLBAR/BUTTON_LOGOUT"></span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
<div class="accountPlace pull-right" data-bind="text: emailTitle()"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
Loading…
Reference in a new issue