Przeglądaj źródła

[Dovecot] Add quota_notify script
[Dovecot] Some minor changes to quarantine notification script to catch more errors

andryyy 6 lat temu
rodzic
commit
c7c1422095

+ 1 - 0
data/Dockerfiles/dovecot/Dockerfile

@@ -119,6 +119,7 @@ COPY docker-entrypoint.sh /
 COPY supervisord.conf /etc/supervisor/supervisord.conf
 COPY stop-supervisor.sh /usr/local/sbin/stop-supervisor.sh
 COPY quarantine_notify.py /usr/local/bin/quarantine_notify.py
+COPY quota_notify.py /usr/local/bin/quota_notify.py
 
 ENTRYPOINT ["/docker-entrypoint.sh"]
 CMD exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf

+ 2 - 1
data/Dockerfiles/dovecot/docker-entrypoint.sh

@@ -165,7 +165,8 @@ chmod +x /usr/local/lib/dovecot/sieve/rspamd-pipe-ham \
   /usr/local/bin/trim_logs.sh \
   /usr/local/bin/sa-rules.sh \
   /usr/local/bin/maildir_gc.sh \
-  /usr/local/sbin/stop-supervisor.sh
+  /usr/local/sbin/stop-supervisor.sh \
+  /usr/local/bin/quota_notify.py
 
 # Setup cronjobs
 echo '* * * * *    root  /usr/local/bin/imapsync_cron.pl 2>&1 | /usr/bin/logger' > /etc/cron.d/imapsync

+ 13 - 1
data/Dockerfiles/dovecot/quarantine_notify.py

@@ -94,9 +94,21 @@ def notify_rcpt(rcpt, msg_count):
 records = query_mysql('SELECT count(id) AS counter, rcpt FROM quarantine WHERE notified = 0 GROUP BY rcpt')
 
 for record in records:
-  last_notification = int(r.hget('Q_LAST_NOTIFIED', record['rcpt']) or 0)
+  attrs = ''
+  attrs_json = ''
+  try:
+    last_notification = int(r.hget('Q_LAST_NOTIFIED', record['rcpt']))
+    if last_notification > time_now:
+      print 'Last notification is > time now, assuming never'
+      last_notification = 0
+  except Exception as ex:
+    print 'Could not determine last notification for %s, assuming never' % (record['rcpt'])
+    last_notification = 0
   attrs_json = query_mysql('SELECT attributes FROM mailbox WHERE username = "%s"' % (record['rcpt']))
   attrs = json.loads(str(attrs_json[0]['attributes']))
+  if attrs['quarantine_notification'] not in ('hourly', 'daily', 'weekly', 'never'):
+    print 'Abnormal quarantine_notification value'
+    continue
   if attrs['quarantine_notification'] == 'hourly':
     if last_notification == 0 or (last_notification + 3600) < time_now:
       print "Notifying %s about %d new items in quarantine" % (record['rcpt'], record['counter'])

+ 70 - 0
data/Dockerfiles/dovecot/quota_notify.py

@@ -0,0 +1,70 @@
+#!/usr/bin/python
+
+import smtplib
+import os
+from email.MIMEMultipart import MIMEMultipart
+from email.MIMEText import MIMEText
+from email.Utils import COMMASPACE, formatdate
+import jinja2
+from jinja2 import Template
+import redis
+import time
+import sys
+from subprocess import Popen, PIPE, STDOUT
+
+if len(sys.argv) > 2:
+  percent = int(sys.argv[1])
+  username = str(sys.argv[2])
+else:
+  print "Args missing"
+  sys.exit(1)
+
+while True:
+  try:
+    r = redis.StrictRedis(host='redis', decode_responses=True, port=6379, db=0)
+    r.ping()
+  except Exception as ex:
+    print '%s - trying again...'  % (ex)
+    time.sleep(3)
+  else:
+    break
+
+if r.get('QW_HTML'):
+  try:
+    template = Template(r.get('QW_HTML'))
+  except:
+    print "Error: Cannot parse quarantine template, falling back to default template."
+    with open('/templates/quota.tpl') as file_:
+      template = Template(file_.read())
+else:
+  with open('/templates/quota.tpl') as file_:
+    template = Template(file_.read())
+
+html = template.render(username=username, percent=percent)
+try:
+  msg = MIMEMultipart('alternative')
+  msg['From'] = r.get('QW_SENDER') or "quota-warning@localhost"
+  msg['Subject'] = r.get('QW_SUBJ') or "Quota warning"
+  msg['Date'] = formatdate(localtime = True)
+  text = "Your mailbox is almost full, currently %d%% are in use. Please consider deleting old messages." % (percent)
+  text_part = MIMEText(text, 'plain', 'utf-8')
+  html_part = MIMEText(html, 'html', 'utf-8')
+  msg.attach(text_part)
+  msg.attach(html_part)
+  msg['To'] = username
+  p = Popen(['/usr/local/libexec/dovecot/dovecot-lda', '-d', username, '-o', '"plugin/quota=maildir:User quota:noenforcing"'], stdout=PIPE, stdin=PIPE, stderr=STDOUT)
+  p.communicate(input=msg.as_string())
+
+except Exception as ex:
+  print 'Failed to send quota notification: %s' % (ex)
+  sys.exit(1)
+
+try:
+  sys.stdout.close()
+except:
+  pass
+
+try:
+  sys.stderr.close()
+except:
+  pass