180 lines
6.1 KiB
Python
180 lines
6.1 KiB
Python
import textwrap
|
|
import os
|
|
|
|
from django.utils import timezone
|
|
from django.utils.translation import ugettext_lazy as _
|
|
|
|
from orchestra.apps.orchestration import ServiceController
|
|
from orchestra.apps.resources import ServiceMonitor
|
|
|
|
from . import settings
|
|
from .models import Address
|
|
|
|
|
|
class MailSystemUserBackend(ServiceController):
|
|
verbose_name = _("Mail system user")
|
|
model = 'mails.Mailbox'
|
|
# TODO related_models = ('resources__content_type') ?? needed for updating disk usage from resource.data
|
|
|
|
DEFAULT_GROUP = 'postfix'
|
|
|
|
def create_user(self, context):
|
|
self.append(textwrap("""
|
|
if [[ $( id %(username)s ) ]]; then
|
|
usermod -p '%(password)s' %(username)s
|
|
else
|
|
useradd %(username)s --password '%(password)s' --shell /dev/null
|
|
fi""" % context
|
|
))
|
|
self.append("mkdir -p %(home)s" % context)
|
|
self.append("chown %(username)s.%(group)s %(home)s" % context)
|
|
|
|
def generate_filter(self, mailbox, context):
|
|
now = timezone.now().strftime("%B %d, %Y, %H:%M")
|
|
context['filtering'] = (
|
|
"# Sieve Filter\n"
|
|
"# Generated by Orchestra %s\n\n" % now
|
|
)
|
|
if mailbox.custom_filtering:
|
|
context['filtering'] += mailbox.custom_filtering
|
|
else:
|
|
context['filtering'] += settings.EMAILS_DEFAUL_FILTERING
|
|
context['filter_path'] = os.path.join(context['home'], '.orchestra.sieve')
|
|
self.append("echo '%(filtering)s' > %(filter_path)s" % context)
|
|
|
|
def set_quota(self, mailbox, context):
|
|
if not hasattr(mailbox, 'resources'):
|
|
return
|
|
context.update({
|
|
'maildir_path': '~%(username)s/Maildir' % context,
|
|
'maildirsize_path': '~%(username)s/Maildir/maildirsize' % context,
|
|
'quota': mailbox.resources.disk.allocated*1000*1000,
|
|
})
|
|
self.append("mkdir -p %(maildir_path)s" % context)
|
|
self.append(textwrap("""
|
|
sed -i '1s/.*/%(quota)s,S/' %(maildirsize_path)s || {
|
|
echo '%(quota)s,S' > %(maildirsize_path)s &&
|
|
chown %(username)s %(maildirsize_path)s;
|
|
}""" % context
|
|
))
|
|
|
|
def save(self, mailbox):
|
|
context = self.get_context(mailbox)
|
|
self.create_user(context)
|
|
self.set_quota(mailbox, context)
|
|
self.generate_filter(mailbox, context)
|
|
|
|
def delete(self, mailbox):
|
|
context = self.get_context(mailbox)
|
|
self.append("{ sleep 2 && killall -u %(username)s -s KILL; } &" % context)
|
|
self.append("killall -u %(username)s" % context)
|
|
self.append("userdel %(username)s" % context)
|
|
self.append("rm -fr %(home)s" % context)
|
|
|
|
def get_context(self, mailbox):
|
|
context = {
|
|
'name': mailbox.name,
|
|
'username': mailbox.name,
|
|
'password': mailbox.password if mailbox.is_active else '*%s' % mailbox.password,
|
|
'group': self.DEFAULT_GROUP
|
|
}
|
|
context['home'] = settings.EMAILS_HOME % context
|
|
return context
|
|
|
|
|
|
class PostfixAddressBackend(ServiceController):
|
|
verbose_name = _("Postfix address")
|
|
model = 'mails.Address'
|
|
|
|
def include_virtdomain(self, context):
|
|
self.append(
|
|
'[[ $(grep "^\s*%(domain)s\s*$" %(virtdomains)s) ]]'
|
|
' || { echo "%(domain)s" >> %(virtdomains)s; UPDATED=1; }' % context
|
|
)
|
|
|
|
def exclude_virtdomain(self, context):
|
|
domain = context['domain']
|
|
if not Address.objects.filter(domain=domain).exists():
|
|
self.append('sed -i "s/^%(domain)s//" %(virtdomains)s' % context)
|
|
|
|
def update_virtusertable(self, context):
|
|
self.append(textwrap("""
|
|
LINE="%(email)s\t%(destination)s"
|
|
if [[ ! $(grep "^%(email)s\s" %(virtusertable)s) ]]; then
|
|
echo "$LINE" >> %(virtusertable)s
|
|
UPDATED=1
|
|
else
|
|
if [[ ! $(grep "^${LINE}$" %(virtusertable)s) ]]; then
|
|
sed -i "s/^%(email)s\s.*$/${LINE}/" %(virtusertable)s
|
|
UPDATED=1
|
|
fi
|
|
fi""" % context
|
|
))
|
|
|
|
def exclude_virtusertable(self, context):
|
|
self.append(textwrap("""
|
|
if [[ $(grep "^%(email)s\s") ]]; then
|
|
sed -i "s/^%(email)s\s.*$//" %(virtusertable)s
|
|
UPDATED=1
|
|
fi"""
|
|
))
|
|
|
|
def save(self, address):
|
|
context = self.get_context(address)
|
|
self.include_virtdomain(context)
|
|
self.update_virtusertable(context)
|
|
|
|
def delete(self, address):
|
|
context = self.get_context(address)
|
|
self.exclude_virtdomain(context)
|
|
self.exclude_virtusertable(context)
|
|
|
|
def commit(self):
|
|
context = self.get_context_files()
|
|
self.append(textwrap("""
|
|
[[ $UPDATED == 1 ]] && {
|
|
postmap %(virtdomains)s
|
|
postmap %(virtusertable)s
|
|
}""" % context
|
|
))
|
|
|
|
def get_context_files(self):
|
|
return {
|
|
'virtdomains': settings.EMAILS_VIRTDOMAINS_PATH,
|
|
'virtusertable': settings.EMAILS_VIRTUSERTABLE_PATH,
|
|
}
|
|
|
|
def get_context(self, address):
|
|
context = self.get_context_files()
|
|
context.update({
|
|
'domain': address.domain,
|
|
'email': address.email,
|
|
'destination': address.destination,
|
|
})
|
|
return context
|
|
|
|
|
|
class AutoresponseBackend(ServiceController):
|
|
verbose_name = _("Mail autoresponse")
|
|
model = 'mail.Autoresponse'
|
|
|
|
|
|
class MaildirDisk(ServiceMonitor):
|
|
model = 'mails.Mailbox'
|
|
resource = ServiceMonitor.DISK
|
|
verbose_name = _("Maildir disk usage")
|
|
|
|
def monitor(self, mailbox):
|
|
context = self.get_context(mailbox)
|
|
self.append(
|
|
"SIZE=$(sed -n '2p' %(maildir_path)s | cut -d' ' -f1)\n"
|
|
"echo %(object_id)s ${SIZE:-0}" % context
|
|
)
|
|
|
|
def get_context(self, mailbox):
|
|
context = MailSystemUserBackend().get_context(mailbox)
|
|
context['home'] = settings.EMAILS_HOME % context
|
|
context['rr_path'] = os.path.join(context['home'], 'Maildir/maildirsize')
|
|
context['object_id'] = mailbox.pk
|
|
return context
|