2019-09-13 20:14:30 +02:00
|
|
|
#!/usr/bin/python3
|
2019-02-05 01:00:22 +02:00
|
|
|
|
|
|
|
import smtplib
|
|
|
|
import os
|
2019-09-13 20:14:30 +02:00
|
|
|
from email.mime.multipart import MIMEMultipart
|
|
|
|
from email.mime.text import MIMEText
|
|
|
|
from email.utils import COMMASPACE, formatdate
|
2019-02-05 01:00:22 +02:00
|
|
|
import jinja2
|
|
|
|
from jinja2 import Template
|
|
|
|
import redis
|
|
|
|
import time
|
2021-05-23 09:49:36 +02:00
|
|
|
import json
|
2019-02-05 01:00:22 +02:00
|
|
|
import sys
|
2019-02-05 11:38:28 +02:00
|
|
|
import html2text
|
2019-02-05 01:00:22 +02:00
|
|
|
from subprocess import Popen, PIPE, STDOUT
|
|
|
|
|
|
|
|
if len(sys.argv) > 2:
|
|
|
|
percent = int(sys.argv[1])
|
|
|
|
username = str(sys.argv[2])
|
|
|
|
else:
|
2019-09-13 20:14:30 +02:00
|
|
|
print("Args missing")
|
2019-02-05 01:00:22 +02:00
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
while True:
|
|
|
|
try:
|
|
|
|
r = redis.StrictRedis(host='redis', decode_responses=True, port=6379, db=0)
|
|
|
|
r.ping()
|
|
|
|
except Exception as ex:
|
2019-09-13 20:14:30 +02:00
|
|
|
print('%s - trying again...' % (ex))
|
2019-02-05 01:00:22 +02:00
|
|
|
time.sleep(3)
|
|
|
|
else:
|
|
|
|
break
|
|
|
|
|
|
|
|
if r.get('QW_HTML'):
|
|
|
|
try:
|
|
|
|
template = Template(r.get('QW_HTML'))
|
|
|
|
except:
|
2019-09-13 20:14:30 +02:00
|
|
|
print("Error: Cannot parse quarantine template, falling back to default template.")
|
2019-02-05 01:00:22 +02:00
|
|
|
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)
|
2019-02-05 11:38:28 +02:00
|
|
|
text = html2text.html2text(html)
|
|
|
|
|
2019-02-05 01:00:22 +02:00
|
|
|
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_part = MIMEText(text, 'plain', 'utf-8')
|
|
|
|
html_part = MIMEText(html, 'html', 'utf-8')
|
|
|
|
msg.attach(text_part)
|
|
|
|
msg.attach(html_part)
|
|
|
|
msg['To'] = username
|
2023-04-26 10:37:20 +02:00
|
|
|
p = Popen(['/usr/libexec/dovecot/dovecot-lda', '-d', username, '-o', '"plugin/quota=maildir:User quota:noenforcing"'], stdout=PIPE, stdin=PIPE, stderr=STDOUT)
|
2019-09-13 20:14:30 +02:00
|
|
|
p.communicate(input=bytes(msg.as_string(), 'utf-8'))
|
2019-02-05 01:00:22 +02:00
|
|
|
|
2021-05-23 09:49:36 +02:00
|
|
|
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
|
2021-05-24 11:09:33 +02:00
|
|
|
server = smtplib.SMTP('postfix', 588, 'quotanotification')
|
2021-05-23 09:49:36 +02:00
|
|
|
server.ehlo()
|
|
|
|
server.sendmail(msg['From'], str(rcpt), msg.as_string())
|
|
|
|
server.quit()
|
|
|
|
|
2019-02-05 01:00:22 +02:00
|
|
|
except Exception as ex:
|
2019-09-13 20:14:30 +02:00
|
|
|
print('Failed to send quota notification: %s' % (ex))
|
2019-02-05 01:00:22 +02:00
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
try:
|
|
|
|
sys.stdout.close()
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
|
|
|
|
try:
|
|
|
|
sys.stderr.close()
|
|
|
|
except:
|
2021-05-24 11:09:33 +02:00
|
|
|
pass
|