#!/usr/bin/ensim-python

# This script is used to make sure that mail that could not be
# initially delivered will be delivered at some later time.
#
# There are a few operations that this script performs, and they
# are dependent on whether MailScanner is running or not.
#
# Here are the directories where mail can be encountered:
# (1) /home/virtual/FILESYSTEMTEMPLATE/services/sendmail/mqueue
# (2) /home/virtual/FILESYSTEMTEMPLATE/services/sendmail/mqueue.scanned
# (3) /home/virtual/site<n>/fst/var/spool/mqueue
# (4) /home/virtual/site<n>/fst/var/spool/mqueue.site
#
# If mail is being delivered to this server from outside, then two things
# may happen:
# - if SMTP AUTH is used, the mail will be queued in (3)
# - if SMTP AUTH is not used, the mail will be queued in (1)
#
# If MailScanner is not running, then delivery will be attempted immediately,
# in which case the mail may be moved to (4), although it may remain in
# (1) or (3), if it cannot be moved to (4). (1) is monitored by the main
# sendmail daemon, so MailQueueCleaner does not need to do anything. (3) and
# (4) are not monitored, by the main daemon, so MailQueueCleaner must attend
# to these.
#
# If MailScanner is running, the mail will be picked up from either (1) or (3),
# scanned, and placed in (2), where either a sendmail process kicked off by
# MailScanner will then deliver it, or a second daemonized sendmail process
# that is monitoring this queue will attempt the delivery. If delivery is not
# successful, the mail will be placed in (4) if possble, otherwise it will be
# left where it is. In this case, MailQueueCleaner only needs to take care of (4).
#
# The last trick is that we need to deal with MailScanner being turned on and off.
# If turned off, there may be mail left in (2), so MailQueueCleaner needs to
# scan this location as well, in order to take care of lingering email.

from vh3.virthost import *
from quota import *
import cmdlnpopen
import os
import pwd
import re
import smtplib
import sys
import traceback

dev = getqcarg("/home/virtual")

message = """From: %s
To: %s
Subject: URGENT: MailQueueCleaner failure report

This is a report generated by the hourly run of MailQueueCleaner. Some
sites on this server have problems which prevent the processing of
their email queues. UNTIL YOU RESOLVE THE PROBLEMS, THESE SITES WILL
NOT BE ABLE TO RECEIVE EMAIL. A summary of the problems is included
below.

%s"""

errors = ""

# Check whether or not we've been turned off
if os.path.exists("/var/appliance/MailQueueCleaner_off"):
    sys.exit(0)

mailscanner_enabled = 0
site_sendmail_args = ""
if os.path.exists("/var/appliance/mailscanner"):
    mailscanner_enabled = 1
    site_sendmail_args = "-ODeliveryMode=background -OQueueDirectory=/var/spool/mqueue.site"

for site in get_domain_list():
    try:
        domain = get_domain_from_site(site)
        path = domainfs_path(site)

	gid = pwd.getpwnam(get_site_adminN(site))[3]
	d = {}
	quotactl(qcmd(Q_GETQUOTA, GRPQUOTA), dev, gid, d)
        d['curspace'] = d['curspace'] / 1024
        if d['bhardlimit'] > 0 and d['curspace'] > d['bhardlimit']:
            errors += domain + ":\tover disk quota, " + \
                      "usage: %dK, " % d['curspace'] + \
                      "quota: %dK\n" % d['bhardlimit']
            continue
        # Process <fst>/var/spool/mqueue.site        
        if not os.path.isdir(path + "/var/spool/mqueue.site") or \
           not os.access(path + "/usr/sbin/sendmail", os.X_OK):
            # probably doesn't have sendmail enabled
            print "skipping %s" % domain
        else:
            out, err, ret = cmdlnpopen.cmd3("/usr/sbin/chroot " + path +
                                            " /usr/sbin/sendmail -q %s" % \
                                            site_sendmail_args)
            if ret != 0:
                errors += domain + ":\tsendmail error, " + \
                          "stdout: %s, " % out + \
                          "stderr: %s, " % err + \
                          "exit code: %d\n" % ret

        # Process <fst>/var/spool/clientmqueue
        clientmqueue_path = "/var/spool/clientmqueue" 
        if not os.path.isdir(clientmqueue_path) or \
           not os.access(path + "/usr/sbin/sendmail", os.X_OK):
            # probably doesn't have sendmail enabled
            print "skipping %s" % domain
        else:
            out, err, ret = cmdlnpopen.cmd3("/usr/sbin/chroot %s"
                                            " /usr/sbin/sendmail -q -OQueueDirectory=%s" % 
                                            (path, clientmqueue_path))
            if ret != 0:
                errors += domain + ":\tsendmail error, " + \
                          "stdout: %s, " % out + \
                          "stderr: %s, " % err + \
                          "exit code: %d\n" % ret


        if not mailscanner_enabled and os.path.isdir(path + "/var/spool/mqueue"):
            out, err, ret = cmdlnpopen.cmd3("/usr/sbin/sendmail -q -OQueueDirectory="
                                            "%s/var/spool/mqueue" % path)
            if ret != 0:
                errors += domain + ":\tsendmail error, " + \
                          "stdout: %s, " % out + \
                          "stderr: %s, " % err + \
                          "exit code: %d\n" % ret                

    except:
        type, value, tb = sys.exc_info()
        lines = traceback.format_exception(type, value, tb)
        errors += domain + ":\tpython exception, traceback: %s\n" % lines

if os.path.isdir("/home/virtual/FILESYSTEMTEMPLATE/services/sendmail/mqueue.scanned") \
   and not mailscanner_enabled:
    out, err, ret = cmdlnpopen.cmd3("/usr/sbin/sendmail -q -OQueueDirectory"
                                    "=/home/virtual/FILESYSTEMTEMPLATE"
                                    "/services/sendmail/mqueue.scanned")
    if ret != 0:
        errors += domain + ":\tsendmail error, " + \
                  "stdout: %s, " % out + \
                  "stderr: %s, " % err + \
                  "exit code: %d\n" % ret

if errors != "":
    server = smtplib.SMTP('localhost')
    email = get_appl_admin()
    server.sendmail(email, email, message % (email, email, errors))
    server.quit()

sys.exit(0)
