From 1f36ae28d4595b20f668e838e842cce66f4fd031 Mon Sep 17 00:00:00 2001 From: andryyy Date: Tue, 15 Sep 2020 11:02:53 +0200 Subject: [PATCH] [Postfix, Web] Feature: Show last SMTP login --- data/Dockerfiles/postfix/Dockerfile | 3 +++ data/Dockerfiles/postfix/smtpd_last_login.sh | 20 ++++++++++++++++++++ data/conf/postfix/main.cf | 1 + data/conf/postfix/master.cf | 8 +++++++- data/web/css/site/mailbox.css | 12 +++++++++--- data/web/inc/functions.mailbox.inc.php | 5 +++++ data/web/js/site/mailbox.js | 7 ++++--- 7 files changed, 49 insertions(+), 7 deletions(-) create mode 100755 data/Dockerfiles/postfix/smtpd_last_login.sh diff --git a/data/Dockerfiles/postfix/Dockerfile b/data/Dockerfiles/postfix/Dockerfile index 012635de..8b913af4 100644 --- a/data/Dockerfiles/postfix/Dockerfile +++ b/data/Dockerfiles/postfix/Dockerfile @@ -25,6 +25,7 @@ RUN groupadd -g 102 postfix \ postfix \ postfix-mysql \ postfix-pcre \ + redis-tools \ sasl2-bin \ sudo \ supervisor \ @@ -44,6 +45,7 @@ COPY postfix.sh /opt/postfix.sh COPY rspamd-pipe-ham /usr/local/bin/rspamd-pipe-ham COPY rspamd-pipe-spam /usr/local/bin/rspamd-pipe-spam COPY whitelist_forwardinghosts.sh /usr/local/bin/whitelist_forwardinghosts.sh +COPY smtpd_last_login.sh /usr/local/bin/smtpd_last_login.sh COPY stop-supervisor.sh /usr/local/sbin/stop-supervisor.sh COPY docker-entrypoint.sh /docker-entrypoint.sh @@ -51,6 +53,7 @@ RUN chmod +x /opt/postfix.sh \ /usr/local/bin/rspamd-pipe-ham \ /usr/local/bin/rspamd-pipe-spam \ /usr/local/bin/whitelist_forwardinghosts.sh \ + /usr/local/bin/smtpd_last_login.sh \ /usr/local/sbin/stop-supervisor.sh RUN rm -rf /tmp/* /var/tmp/* diff --git a/data/Dockerfiles/postfix/smtpd_last_login.sh b/data/Dockerfiles/postfix/smtpd_last_login.sh new file mode 100755 index 00000000..7f8c6ec8 --- /dev/null +++ b/data/Dockerfiles/postfix/smtpd_last_login.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +# Do not attempt to write to slave +if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then + REDIS_CMDLINE="redis-cli -h ${REDIS_SLAVEOF_IP} -p ${REDIS_SLAVEOF_PORT}" +else + REDIS_CMDLINE="redis-cli -h redis -p 6379" +fi + +while read QUERY; do + QUERY=($QUERY) + # If nothing matched, end here - Postfix last line will be empty + if [[ -z "$(echo ${QUERY[0]} | tr -d '\040\011\012\015')" ]]; then + echo -ne "action=dunno\n\n" + # We found a username, log and return + elif [[ "${QUERY[0]}" =~ sasl_username ]]; then + ${REDIS_CMDLINE} SET "last-login/smtp/$(echo ${QUERY[0]#sasl_username=})" "$(date +%s)" + echo -ne "action=dunno\n\n" + fi +done diff --git a/data/conf/postfix/main.cf b/data/conf/postfix/main.cf index 7bde2b89..6943d6d6 100644 --- a/data/conf/postfix/main.cf +++ b/data/conf/postfix/main.cf @@ -189,6 +189,7 @@ smtp_sasl_auth_soft_bounce = no postscreen_discard_ehlo_keywords = silent-discard, dsn compatibility_level = 2 smtputf8_enable = no +smtpd_last_auth = check_policy_service inet:127.0.0.1:10028 # Define protocols for SMTPS and submission service submission_smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 smtps_smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 diff --git a/data/conf/postfix/master.cf b/data/conf/postfix/master.cf index 0bb445d8..d4f4b24b 100644 --- a/data/conf/postfix/master.cf +++ b/data/conf/postfix/master.cf @@ -16,6 +16,7 @@ smtps inet n - n - - smtpd -o smtpd_tls_mandatory_protocols=$smtps_smtpd_tls_mandatory_protocols -o tls_preempt_cipherlist=yes -o syslog_name=postfix/smtps + -o smtpd_end_of_data_restrictions=$smtpd_last_auth 10465 inet n - n - - smtpd -o smtpd_upstream_proxy_protocol=haproxy -o smtpd_tls_wrappermode=yes @@ -23,6 +24,7 @@ smtps inet n - n - - smtpd -o smtpd_tls_mandatory_protocols=$smtps_smtpd_tls_mandatory_protocols -o tls_preempt_cipherlist=yes -o syslog_name=postfix/smtps-haproxy + -o smtpd_end_of_data_restrictions=$smtpd_last_auth # smtpd with starttls on 587/tcp # TLS protocol can be modified by setting submission_smtpd_tls_mandatory_protocols in extra.cf @@ -33,6 +35,7 @@ submission inet n - n - - smtpd -o smtpd_tls_mandatory_protocols=$submission_smtpd_tls_mandatory_protocols -o tls_preempt_cipherlist=yes -o syslog_name=postfix/submission + -o smtpd_end_of_data_restrictions=$smtpd_last_auth 10587 inet n - n - - smtpd -o smtpd_upstream_proxy_protocol=haproxy -o smtpd_client_restrictions=permit_mynetworks,permit_sasl_authenticated,reject @@ -41,6 +44,7 @@ submission inet n - n - - smtpd -o smtpd_tls_mandatory_protocols=$submission_smtpd_tls_mandatory_protocols -o tls_preempt_cipherlist=yes -o syslog_name=postfix/submission-haproxy + -o smtpd_end_of_data_restrictions=$smtpd_last_auth # used by SOGo # smtpd_sender_restrictions should match main.cf, but with check_sasl_access prepended for login-as-mailbox-user function @@ -49,6 +53,7 @@ submission inet n - n - - smtpd -o smtpd_tls_auth_only=no -o smtpd_sender_restrictions=check_sasl_access,regexp:/opt/postfix/conf/allow_mailcow_local.regexp,reject_authenticated_sender_login_mismatch,permit_mynetworks,permit_sasl_authenticated,reject_unlisted_sender,reject_unknown_sender_domain -o syslog_name=postfix/sogo + -o smtpd_end_of_data_restrictions=$smtpd_last_auth # used to reinject quarantine mails 590 inet n - n - - smtpd @@ -58,13 +63,13 @@ submission inet n - n - - smtpd -o smtpd_milters= -o non_smtpd_milters= -o syslog_name=postfix/quarantine + -o smtpd_end_of_data_restrictions=$smtpd_last_auth # enforced smtp connector smtp_enforced_tls unix - - n - - smtp -o smtp_tls_security_level=encrypt -o syslog_name=enforced-tls-smtp -o smtp_delivery_status_filter=pcre:/opt/postfix/conf/smtp_dsn_filter - # smtp connector used, when a transport map matched # this helps to have different sasl maps than we have with sender dependent transport maps smtp_via_transport_maps unix - - n - - smtp @@ -100,6 +105,7 @@ maildrop unix - n n - - pipe flags=DRhu # start whitelist_fwd 127.0.0.1:10027 inet n n n - 0 spawn user=nobody argv=/usr/local/bin/whitelist_forwardinghosts.sh +127.0.0.1:10028 inet n n n - 0 spawn user=nobody argv=/usr/local/bin/smtpd_last_login.sh # end whitelist_fwd # start watchdog-specific diff --git a/data/web/css/site/mailbox.css b/data/web/css/site/mailbox.css index 9fe695c0..56fe4f8f 100644 --- a/data/web/css/site/mailbox.css +++ b/data/web/css/site/mailbox.css @@ -57,7 +57,13 @@ table tbody tr { table tbody tr td input[type="checkbox"] { cursor: pointer; } -.label-last { - color: #c7254e !important; - background-color: #f9f2f4 !important; +.label-last-in { + line-height: 2.5; + color: #4a4a4a!important; + background-color: #ececec!important; +} +.label-last-out { + line-height: 2.5; + color: #ececec!important; + background-color: #a0a0a0!important; } \ No newline at end of file diff --git a/data/web/inc/functions.mailbox.inc.php b/data/web/inc/functions.mailbox.inc.php index 1206d27e..33061c26 100644 --- a/data/web/inc/functions.mailbox.inc.php +++ b/data/web/inc/functions.mailbox.inc.php @@ -3345,10 +3345,14 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $mailboxdata = array(); $rl = ratelimit('get', 'mailbox', $_data); $last_imap_login = $redis->Get('last-login/imap/' . $_data); + $last_smtp_login = $redis->Get('last-login/smtp/' . $_data); $last_pop3_login = $redis->Get('last-login/pop3/' . $_data); if ($last_imap_login === false || $GLOBALS['SHOW_LAST_LOGIN'] === false) { $last_imap_login = '0'; } + if ($last_smtp_login === false || $GLOBALS['SHOW_LAST_LOGIN'] === false) { + $last_smtp_login = '0'; + } if ($last_pop3_login === false || $GLOBALS['SHOW_LAST_LOGIN'] === false) { $last_pop3_login = '0'; } @@ -3416,6 +3420,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $mailboxdata['is_relayed'] = $row['backupmx']; $mailboxdata['name'] = $row['name']; $mailboxdata['last_imap_login'] = $last_imap_login; + $mailboxdata['last_smtp_login'] = $last_smtp_login; $mailboxdata['last_pop3_login'] = $last_pop3_login; $mailboxdata['active'] = $row['active']; $mailboxdata['active_int'] = $row['active_int']; diff --git a/data/web/js/site/mailbox.js b/data/web/js/site/mailbox.js index 36c1b30d..311131c5 100644 --- a/data/web/js/site/mailbox.js +++ b/data/web/js/site/mailbox.js @@ -363,8 +363,9 @@ jQuery(function($){ }, "formatter": function(value){ res = value.split("/"); - return '
IMAP @ ' + unix_time_format(Number(res[0])) + '
' + - '
POP3 @ ' + unix_time_format(Number(res[1])) + '
'; + return '
IMAP @ ' + unix_time_format(Number(res[0])) + '

' + + '
POP3 @ ' + unix_time_format(Number(res[1])) + '

' + + '
SMTP @ ' + unix_time_format(Number(res[2])) + '
'; }}, {"name":"quarantine_notification","filterable": false,"title":lang.quarantine_notification,"breakpoints":"all"}, {"name":"in_use","filterable": false,"type":"html","title":lang.in_use,"sortValue": function(value){ @@ -388,7 +389,7 @@ jQuery(function($){ $.each(data, function (i, item) { item.quota = item.quota_used + "/" + item.quota; item.max_quota_for_mbox = humanFileSize(item.max_quota_for_mbox); - item.last_mail_login = item.last_imap_login + '/' + item.last_pop3_login; + item.last_mail_login = item.last_imap_login + '/' + item.last_pop3_login + '/' + item.last_smtp_login; if (!item.rl) { item.rl = '∞'; } else {