class_smtpServer quality fixes

This commit is contained in:
lakshyacis 2019-11-04 20:21:54 +05:30
parent 9923e97279
commit 4a54c200d4
No known key found for this signature in database
GPG Key ID: D2C539C8EC63E9EB
1 changed files with 33 additions and 14 deletions

View File

@ -1,3 +1,6 @@
"""
SMTP server thread
"""
import asyncore import asyncore
import base64 import base64
import email import email
@ -22,10 +25,13 @@ SMTPDOMAIN = "bmaddr.lan"
LISTENPORT = 8425 LISTENPORT = 8425
logger = logging.getLogger('default') logger = logging.getLogger('default')
# pylint: disable=attribute-defined-outside-init
class smtpServerChannel(smtpd.SMTPChannel): class smtpServerChannel(smtpd.SMTPChannel):
"""Asyncore channel for SMTP protocol (server)"""
def smtp_EHLO(self, arg): def smtp_EHLO(self, arg):
"""Process an EHLO"""
if not arg: if not arg:
self.push('501 Syntax: HELO hostname') self.push('501 Syntax: HELO hostname')
return return
@ -33,14 +39,16 @@ class smtpServerChannel(smtpd.SMTPChannel):
self.push('250 AUTH PLAIN') self.push('250 AUTH PLAIN')
def smtp_AUTH(self, arg): def smtp_AUTH(self, arg):
"""Process AUTH"""
if not arg or arg[0:5] not in ["PLAIN"]: if not arg or arg[0:5] not in ["PLAIN"]:
self.push('501 Syntax: AUTH PLAIN') self.push('501 Syntax: AUTH PLAIN')
return return
authstring = arg[6:] authstring = arg[6:]
try: try:
decoded = base64.b64decode(authstring) decoded = base64.b64decode(authstring)
correctauth = "\x00" + BMConfigParser().safeGet("bitmessagesettings", "smtpdusername", "") + \ correctauth = "\x00" + BMConfigParser().safeGet(
"\x00" + BMConfigParser().safeGet("bitmessagesettings", "smtpdpassword", "") "bitmessagesettings", "smtpdusername", "") + "\x00" + BMConfigParser().safeGet(
"bitmessagesettings", "smtpdpassword", "")
logger.debug('authstring: %s / %s', correctauth, decoded) logger.debug('authstring: %s / %s', correctauth, decoded)
if correctauth == decoded: if correctauth == decoded:
self.auth = True self.auth = True
@ -51,6 +59,7 @@ class smtpServerChannel(smtpd.SMTPChannel):
self.push('501 Authentication fail') self.push('501 Authentication fail')
def smtp_DATA(self, arg): def smtp_DATA(self, arg):
"""Process DATA"""
if not hasattr(self, "auth") or not self.auth: if not hasattr(self, "auth") or not self.auth:
self.push('530 Authentication required') self.push('530 Authentication required')
return return
@ -58,15 +67,18 @@ class smtpServerChannel(smtpd.SMTPChannel):
class smtpServerPyBitmessage(smtpd.SMTPServer): class smtpServerPyBitmessage(smtpd.SMTPServer):
"""Asyncore SMTP server class"""
def handle_accept(self): def handle_accept(self):
"""Accept a connection"""
pair = self.accept() pair = self.accept()
if pair is not None: if pair is not None:
conn, addr = pair conn, addr = pair
# print >> DEBUGSTREAM, 'Incoming connection from %s' % repr(addr) # print >> DEBUGSTREAM, 'Incoming connection from %s' % repr(addr)
self.channel = smtpServerChannel(self, conn, addr) self.channel = smtpServerChannel(self, conn, addr)
def send(self, fromAddress, toAddress, subject, message): def send(self, fromAddress, toAddress, subject, message): # pylint: disable=arguments-differ
status, addressVersionNumber, streamNumber, ripe = decodeAddress(toAddress) """Send a bitmessage"""
streamNumber, ripe = decodeAddress(toAddress)[2:]
stealthLevel = BMConfigParser().safeGetInt('bitmessagesettings', 'ackstealthlevel') stealthLevel = BMConfigParser().safeGetInt('bitmessagesettings', 'ackstealthlevel')
ackdata = genAckPayload(streamNumber, stealthLevel) ackdata = genAckPayload(streamNumber, stealthLevel)
sqlExecute( sqlExecute(
@ -78,19 +90,21 @@ class smtpServerPyBitmessage(smtpd.SMTPServer):
subject, subject,
message, message,
ackdata, ackdata,
int(time.time()), # sentTime (this will never change) int(time.time()), # sentTime (this will never change)
int(time.time()), # lastActionTime int(time.time()), # lastActionTime
0, # sleepTill time. This will get set when the POW gets done. 0, # sleepTill time. This will get set when the POW gets done.
'msgqueued', 'msgqueued',
0, # retryNumber 0, # retryNumber
'sent', # folder 'sent', # folder
2, # encodingtype 2, # encodingtype
min(BMConfigParser().getint('bitmessagesettings', 'ttl'), 86400 * 2) # not necessary to have a TTL higher than 2 days # not necessary to have a TTL higher than 2 days
min(BMConfigParser().getint('bitmessagesettings', 'ttl'), 86400 * 2)
) )
queues.workerQueue.put(('sendmessage', toAddress)) queues.workerQueue.put(('sendmessage', toAddress))
def decode_header(self, hdr): def decode_header(self, hdr):
"""Email header decoding"""
ret = [] ret = []
for h in decode_header(self.msg_headers[hdr]): for h in decode_header(self.msg_headers[hdr]):
if h[1]: if h[1]:
@ -100,7 +114,9 @@ class smtpServerPyBitmessage(smtpd.SMTPServer):
return ret return ret
def process_message(self, peer, mailfrom, rcpttos, data): def process_message(self, peer, mailfrom, rcpttos, data): # pylint: disable=too-many-locals, too-many-branches
"""Process an email"""
# print 'Receiving message from:', peer
p = re.compile(".*<([^>]+)>") p = re.compile(".*<([^>]+)>")
if not hasattr(self.channel, "auth") or not self.channel.auth: if not hasattr(self.channel, "auth") or not self.channel.auth:
logger.error('Missing or invalid auth') logger.error('Missing or invalid auth')
@ -158,7 +174,8 @@ class smtpServerPyBitmessage(smtpd.SMTPServer):
class smtpServer(StoppableThread): class smtpServer(StoppableThread):
def __init__(self, parent=None): """SMTP server thread"""
def __init__(self, _=None):
super(smtpServer, self).__init__(name="smtpServerThread") super(smtpServer, self).__init__(name="smtpServerThread")
self.server = smtpServerPyBitmessage(('127.0.0.1', LISTENPORT), None) self.server = smtpServerPyBitmessage(('127.0.0.1', LISTENPORT), None)
@ -171,7 +188,8 @@ class smtpServer(StoppableThread):
asyncore.loop(1) asyncore.loop(1)
def signals(signal, frame): def signals(_, __):
"""Signal handler"""
logger.warning('Got signal, terminating') logger.warning('Got signal, terminating')
for thread in threading.enumerate(): for thread in threading.enumerate():
if thread.isAlive() and isinstance(thread, StoppableThread): if thread.isAlive() and isinstance(thread, StoppableThread):
@ -179,6 +197,7 @@ def signals(signal, frame):
def runServer(): def runServer():
"""Run SMTP server as a standalone python process"""
logger.warning('Running SMTPd thread') logger.warning('Running SMTPd thread')
smtpThread = smtpServer() smtpThread = smtpServer()
smtpThread.start() smtpThread.start()