Skip to content

Commit 775bc59

Browse files
author
Till Brehm
committed
Merge branch '5374-mail-last-accessed-backend-cron' into 'develop'
Parse the dovecot/postfix logs to update the last login time for mail_user's. #5374 See merge request ispconfig/ispconfig3!1865
2 parents 80a1bd4 + 25d4d32 commit 775bc59

File tree

2 files changed

+123
-4
lines changed

2 files changed

+123
-4
lines changed
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
<?php
2+
3+
/*
4+
Copyright (c) 2024, Herman van Rink, Initfour websolutions
5+
All rights reserved.
6+
7+
Redistribution and use in source and binary forms, with or without modification,
8+
are permitted provided that the following conditions are met:
9+
10+
* Redistributions of source code must retain the above copyright notice,
11+
this list of conditions and the following disclaimer.
12+
* Redistributions in binary form must reproduce the above copyright notice,
13+
this list of conditions and the following disclaimer in the documentation
14+
and/or other materials provided with the distribution.
15+
* Neither the name of ISPConfig nor the names of its contributors
16+
may be used to endorse or promote products derived from this software without
17+
specific prior written permission.
18+
19+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22+
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23+
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24+
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
26+
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28+
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29+
*/
30+
31+
class cronjob_mailbox_stats_hourly extends cronjob {
32+
33+
// job schedule
34+
protected $_schedule = '0 * * * *';
35+
protected $mailbox_traffic = array();
36+
protected $mail_boxes = array();
37+
protected $mail_rewrites = array();
38+
39+
/* this function is optional if it contains no custom code */
40+
public function onPrepare() {
41+
global $app;
42+
43+
parent::onPrepare();
44+
}
45+
46+
/* this function is optional if it contains no custom code */
47+
public function onBeforeRun() {
48+
global $app;
49+
50+
return parent::onBeforeRun();
51+
}
52+
53+
public function onRunJob() {
54+
global $app, $conf;
55+
56+
// Skip if no last access info needs to be shown.
57+
$mail_config = $app->getconf->get_global_config('mail');
58+
if (!isset($mail_config['mailbox_show_last_access']) || $mail_config['mailbox_show_last_access'] != 'y') {
59+
return;
60+
}
61+
62+
$sql = "SELECT mailuser_id FROM mail_user WHERE server_id = ?";
63+
$records = $app->db->queryAllRecords($sql, $conf['server_id']);
64+
if(count($records) > 0) {
65+
$this->update_last_mail_login();
66+
}
67+
68+
parent::onRunJob();
69+
}
70+
71+
/* this function is optional if it contains no custom code */
72+
public function onAfterRun() {
73+
global $app;
74+
75+
parent::onAfterRun();
76+
}
77+
78+
// Parse the dovecot/postfix logs to update the last login time for mail_user's.
79+
private function update_last_mail_login() {
80+
global $app;
81+
82+
// used for all monitor cronjobs
83+
$app->load('monitor_tools');
84+
$this->_tools = new monitor_tools();
85+
86+
// Get the data of the log
87+
$log_lines = $this->_tools->_getLogData('log_mail', 10000000);
88+
89+
$updatedUsers = [];
90+
91+
// Loop over all lines.
92+
$line = strtok($log_lines, PHP_EOL);
93+
while ($line !== FALSE) {
94+
$matches = [];
95+
// Match pop3/imap logings, or alternately smtp logins.
96+
if (preg_match('/(.*) (imap|pop3)-login: Login: user=\<([\w\.@-]+)\>/', $line, $matches) || preg_match('/(.*) sasl_method=PLAIN, sasl_username=([\w\.@-]+)/', $line, $matches)) {
97+
$user = $matches[3] ?? $matches[2];
98+
$updatedUsers[] = $user;
99+
}
100+
101+
// get the next line
102+
$line = strtok(PHP_EOL);
103+
}
104+
105+
$uniqueUsers = array_unique($updatedUsers);
106+
107+
$app->log('Updating last_access stats for ' . count($uniqueUsers) . ' mail users', LOGLEVEL_DEBUG);
108+
109+
// Date/time rounded to hours.
110+
$now = time() - (time() % (60 * 60 * 24));
111+
$nowFormatted = date('Y-m-d H:i:s', $now);
112+
$sqlStatement = "UPDATE mail_user SET last_access=? WHERE email=?";
113+
114+
// Save to master db.
115+
foreach ($uniqueUsers as $user) {
116+
$ret = $app->dbmaster->query($sqlStatement, $now, $user);
117+
}
118+
}
119+
}

server/lib/classes/monitor_tools.inc.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -681,14 +681,14 @@ public function _getLogData($log, $max_lines = 100) {
681681
$log = 'Logfile path error.';
682682
} else {
683683
if (is_readable($logfile)) {
684-
$log = $this->_getOutputFromExecCommand('tail -n '.intval($max_lines).' ' . escapeshellarg($logfile));
684+
$log = $this->_getOutputFromExecCommand('tail -n '.intval($max_lines).' ' . escapeshellarg($logfile), $max_lines);
685685
} else {
686686
$log = 'Unable to read ' . $logfile;
687687
}
688688
}
689689
} else {
690690
if($journalmatch != ''){
691-
$log = $this->_getOutputFromExecCommand('journalctl -n '.intval($max_lines).' --no-pager ' . escapeshellcmd($journalmatch));
691+
$log = $this->_getOutputFromExecCommand('journalctl -n '.intval($max_lines).' --no-pager ' . escapeshellcmd($journalmatch), $max_lines);
692692
}else{
693693
$log = 'Unable to read logfile';
694694
}
@@ -698,15 +698,15 @@ public function _getLogData($log, $max_lines = 100) {
698698
return $log;
699699
}
700700

701-
private function _getOutputFromExecCommand ($command) {
701+
private function _getOutputFromExecCommand ($command, $max4k = 1000) {
702702
$log = '';
703703
$fd = popen($command, 'r');
704704
if ($fd) {
705705
$n = 0;
706706
while (!feof($fd)) {
707707
$log .= fgets($fd, 4096);
708708
$n++;
709-
if ($n > 1000)
709+
if ($n > $max4k)
710710
break;
711711
}
712712
fclose($fd);

0 commit comments

Comments
 (0)