NobGit
public nobgit read

NobMail

Based on mailcow: dockerized

Languages

Repository composition by tracked source files.

PHP
PHP 49% JavaScript 35% HTML 9% CSS 4% Shell 2% Python 1% Lua 0% Perl 0% Ruby 0% SCSS 0%
Create file Wiki Documentation
Clone
https://nobgit.com/orgs/nobgit/nobmail.git
ssh://[email protected]:2222/orgs/nobgit/nobmail.git

Commit

[Postfix, Web] Feature: Show last SMTP login

1f36ae28
andryyy <[email protected]> 6 years ago
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

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 '<div class="label label-last">IMAP @ ' + unix_time_format(Number(res[0])) + '</div> ' +
-            '<div class="label label-last">POP3 @ ' + unix_time_format(Number(res[1])) + '</div>';
+          return '<div class="label label-last-in">IMAP @ ' + unix_time_format(Number(res[0])) + '</div><br>' +
+            '<div class="label label-last-in">POP3 @ ' + unix_time_format(Number(res[1])) + '</div><br>' + 
+            '<div class="label label-last-out">SMTP @ ' + unix_time_format(Number(res[2])) + '</div>';
         }},
         {"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 {