public
nobgit
read
NobMail
Based on mailcow: dockerized
Languages
Repository composition by tracked source files.
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
[Dovecot] Quota notifications: Allow to send to external address (BCC via mailcow UI)
beda649e
data/Dockerfiles/dovecot/quota_notify.py | 24 ++++++++++++++++++++++-
data/web/css/build/006-footable.bootstrap.min.css | 6 +++---
data/web/css/build/008-mailcow.css | 6 ++++++
data/web/debug.php | 2 +-
data/web/inc/header.inc.php | 4 ++--
data/web/js/site/mailbox.js | 2 +-
6 files changed, 36 insertions(+), 8 deletions(-)
Diff
diff --git a/data/Dockerfiles/dovecot/quota_notify.py b/data/Dockerfiles/dovecot/quota_notify.py
index fdfda304..419f80d4 100755
--- a/data/Dockerfiles/dovecot/quota_notify.py
+++ b/data/Dockerfiles/dovecot/quota_notify.py
@@ -9,6 +9,7 @@ import jinja2
from jinja2 import Template
import redis
import time
+import json
import sys
import html2text
from subprocess import Popen, PIPE, STDOUT
@@ -57,6 +58,27 @@ try:
p = Popen(['/usr/lib/dovecot/dovecot-lda', '-d', username, '-o', '"plugin/quota=maildir:User quota:noenforcing"'], stdout=PIPE, stdin=PIPE, stderr=STDOUT)
p.communicate(input=bytes(msg.as_string(), 'utf-8'))
+ domain = username.split("@")[-1]
+ if domain and r.hget('QW_BCC', domain):
+ bcc_data = json.loads(r.hget('QW_BCC', domain))
+ bcc_rcpts = bcc_data['bcc_rcpts']
+ if bcc_data['active'] == 1:
+ for rcpt in bcc_rcpts:
+ msg = MIMEMultipart('alternative')
+ msg['From'] = username
+ subject = r.get('QW_SUBJ') or "Quota warning"
+ msg['Subject'] = subject + ' (' + username + ')'
+ msg['Date'] = formatdate(localtime = True)
+ text_part = MIMEText(text, 'plain', 'utf-8')
+ html_part = MIMEText(html, 'html', 'utf-8')
+ msg.attach(text_part)
+ msg.attach(html_part)
+ msg['To'] = rcpt
+ server = smtplib.SMTP('postfix', 588, 'quarantine')
+ server.ehlo()
+ server.sendmail(msg['From'], str(rcpt), msg.as_string())
+ server.quit()
+
except Exception as ex:
print('Failed to send quota notification: %s' % (ex))
sys.exit(1)
@@ -69,4 +91,4 @@ except:
try:
sys.stderr.close()
except:
- pass
+ pass
\ No newline at end of file
diff --git a/data/web/css/build/006-footable.bootstrap.min.css b/data/web/css/build/006-footable.bootstrap.min.css
index 2a533ab1..670eab25 100644
--- a/data/web/css/build/006-footable.bootstrap.min.css
+++ b/data/web/css/build/006-footable.bootstrap.min.css
@@ -104,7 +104,7 @@ table.footable > tbody > tr.footable-empty > th {
}
.fooicon {
position: relative;
- top: 1px;
+ top: 0px;
display: inline-block;
font-family: "bootstrap-icons" !important;
font-style: normal;
@@ -123,10 +123,10 @@ table.footable > tbody > tr.footable-empty > th {
content: "\f130";
}
.fooicon-plus:before {
- content: "\f64d";
+ content: "\f4fc";
}
.fooicon-minus:before {
- content: "\f63b";
+ content: "\f2e8";
}
.fooicon-search:before {
content: "\f52a";
diff --git a/data/web/css/build/008-mailcow.css b/data/web/css/build/008-mailcow.css
index 04212d40..8bd703fd 100644
--- a/data/web/css/build/008-mailcow.css
+++ b/data/web/css/build/008-mailcow.css
@@ -230,3 +230,9 @@ table.footable>tbody>tr.footable-empty>td {
font-style:italic;
font-size: 1rem;
}
+.navbar-nav > li {
+ font-size: 1rem !important;
+}
+.dropdown-menu > li > a {
+ font-size: 1rem !important;
+}
\ No newline at end of file
diff --git a/data/web/debug.php b/data/web/debug.php
index 6e7c9889..a935ea20 100644
--- a/data/web/debug.php
+++ b/data/web/debug.php
@@ -83,7 +83,7 @@ $xmpp_status = xmpp_control('status');
<p><?=$lang['debug']['started_at'];?>: <span class="parse_date"><?=$solr_status['status']['dovecot-fts']['startTime'];?></span></p>
<p><?=$lang['debug']['last_modified'];?>: <span class="parse_date"><?=$solr_status['status']['dovecot-fts']['index']['lastModified'];?></span></p>
<p><?=$lang['debug']['size'];?>: <?=$solr_status['status']['dovecot-fts']['index']['size'];?></p>
- <p><?=$lang['debug']['docs'];?>: <?=$solr_status['status']['dovecot-fts']['index']['numDocs'];?></p>
+ <p><i class="bi bi-file-text"></i> <?=$lang['debug']['docs'];?>: <?=$solr_status['status']['dovecot-fts']['index']['numDocs'];?></p>
<?php
else:
?>
diff --git a/data/web/inc/header.inc.php b/data/web/inc/header.inc.php
index fdcbb078..794c365c 100644
--- a/data/web/inc/header.inc.php
+++ b/data/web/inc/header.inc.php
@@ -127,9 +127,9 @@
</ul>
</li>
<?php } if (!isset($_SESSION['dual-login']) && isset($_SESSION['mailcow_cc_username'])) { ?>
- <li class="logged-in-as"><a href="#" onclick="logout.submit()"><b class="username-lia"><?= htmlspecialchars($_SESSION['mailcow_cc_username']); ?></b> <i class="bi bi-door-open"></i></a></li>
+ <li class="logged-in-as"><a href="#" onclick="logout.submit()"><b class="username-lia"><?= htmlspecialchars($_SESSION['mailcow_cc_username']); ?></b> <i class="bi bi-x-circle"></i></a></li>
<?php } elseif (isset($_SESSION['dual-login'])) { ?>
- <li class="logged-in-as"><a href="#" onclick="logout.submit()"><b class="username-lia"><?= htmlspecialchars($_SESSION['mailcow_cc_username']); ?> <span class="text-info">(<?= htmlspecialchars($_SESSION['dual-login']['username']); ?>)</span> </b><i class="bi bi-door-open"></i></a></li>
+ <li class="logged-in-as"><a href="#" onclick="logout.submit()"><b class="username-lia"><?= htmlspecialchars($_SESSION['mailcow_cc_username']); ?> <span class="text-info">(<?= htmlspecialchars($_SESSION['dual-login']['username']); ?>)</span> </b><i class="bi bi-x-circle"></i></a></li>
<?php } if (!preg_match('/y|yes/i', getenv('MASTER'))) { ?>
<li class="text-warning slave-info">[ slave ]</li>
<?php } ?>
diff --git a/data/web/js/site/mailbox.js b/data/web/js/site/mailbox.js
index 3b2c948f..6397bb98 100644
--- a/data/web/js/site/mailbox.js
+++ b/data/web/js/site/mailbox.js
@@ -291,7 +291,7 @@ jQuery(function($){
else {
item.action += '<a href="/edit/domain/' + encodeURIComponent(item.domain_name) + '" class="btn btn-xs btn-default"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>';
}
- item.action += '<a href="#dnsInfoModal" class="btn btn-xs btn-info" data-toggle="modal" data-domain="' + encodeURIComponent(item.domain_name) + '"><i class="bi bi-question-lg"></i> DNS</a></div>';
+ item.action += '<a href="#dnsInfoModal" class="btn btn-xs btn-info" data-toggle="modal" data-domain="' + encodeURIComponent(item.domain_name) + '"><i class="bi bi-globe2"></i> DNS</a></div>';
if (item.backupmx == 1) {
if (item.relay_unknown_only == 1) {
item.domain_name = '<div class="label label-info">Relay Non-Local</div> ' + item.domain_name;