serpent/serpent/queue.py

117 lines
3.7 KiB
Python
Raw Normal View History

2016-05-15 11:17:48 +03:00
# -*- coding: utf-8 -*-
from serpent.config import conf
from serpent import dataio, misc, rules
from datetime import datetime, timedelta
from os import path
2016-05-25 18:30:12 +03:00
from DNS import dnslookup
from operator import itemgetter
from smtplib import SMTP
2016-05-15 11:17:48 +03:00
class SmtpQueue(object):
def __init__(self, store, local_delivery):
self.stor = store
self.local_delivery = local_delivery
def add(self, data):
'''Ставит письмо в очередь'''
data['add_time'] = datetime.utcnow()
data['state'] = misc.MSG_ACTIVE
w = self.stor.write(data)
if not w:
return False
return self.__process_(data['id'])
def run(self):
'''Запускает обработку очереди'''
now = datetime.utcnow()
check_delta = timedelta(minutes = conf.smtp_queue_check_period)
expire_delta = timedelta(minutes = conf.smtp_queue_message_ttl)
for mid in self.__list_messages_():
info = self.stor.getinfo(mid)
if (now - info['add_time']) >= expire_delta:
self.stor.delete(mid)
continue
if (now - info['add_time']) >= check_delta:
continue
self.__process_(mid)
return True
def __local_deliver_(self, mid):
message = self.stor.read(mid)
user = rules.username_by_email(message['rcpt'])
return self.local_delivery.deliver(user, message['message'])
def __send_email_(self, mid):
2016-05-25 18:30:12 +03:00
info = self.stor.getinfo(mid)
try:
mail_servers = dnslookup(info['rcpt'][1], 'mx')
except:
return False
mail_servers = sorted(mail_servers, key=itemgetter(0))
for _, mx in mail_servers:
s = SMTP(local_hostname = conf.smtp_hostname)
try:
ret_code, banner = s.connect(mx, 25)
except:
s.quit()
continue
if ret_code != 220:
s.quit()
continue
try:
s.starttls()
except:
if conf.smtp_email_tls_required:
s.quit()
continue
from_addr = conf.smtp_email_delim.join(info['from'])
to_addr = conf.smtp_email_delim.join(info['rcpt'])
message = self.stor.read(mid)
try:
s.sendmail(from_addr, [to_addr], message['message'])
except:
s.quit()
continue
s.quit()
return True
return False
2016-05-15 11:17:48 +03:00
def __freeze_(self, mid):
info = self.stor.getinfo(mid)
if info:
if info['state'] != misc.MSG_FROZEN :
info['state'] = misc.MSG_FROZEN
if self.stor.setinfo(info):
return True
else:
return True
return False
def __process_(self, mid):
info = self.stor.getinfo(mid)
if info:
if info['rcpt'][1] in conf.local_domains:
if self.__local_deliver_(mid):
self.__remove_message_(mid)
return True
else:
return self.__freeze_(mid)
else:
if self.__send_email_(mid):
self.__remove_message_(mid)
return True
else:
return self.__freeze_(mid)
return False
def __list_messages_(self):
return self.stor.list()
def __remove_message_(self, mid):
self.stor.delete(mid)
mailstore = dataio.MailDirStore()
squeue = SmtpQueue(dataio.SmtpFileStore(path.join(conf.app_dir, conf.smtp_queue_dir)),
mailstore)