diff --git a/app/Gulag.py b/app/Gulag.py index 112bd24..1c5c975 100644 --- a/app/Gulag.py +++ b/app/Gulag.py @@ -25,28 +25,17 @@ class Gulag: raise GulagException("CONFIG-FILE-Exception: " + str(sys.exc_info())) try: - self.db = GulagDB( - self.config['db']['server'], - self.config['db']['user'], - self.config['db']['password'], - self.config['db']['name'], - self.config['uri_prefixes'] - ) + self.db = GulagDB(self.config['db'],self.config['uri_prefixes']) except GulagDBException as e: raise GulagException(e.message) from e # Iterate through all mailboxes, extract metadata - # from all unseen mails and import them into database + # from all unseen mails and pump them into database def import_quarmails(self): for mailbox in self.db.get_mailboxes(): imap_mb = None try: - imap_mb = IMAPmailbox( - mailbox['imap_server'], - mailbox['imap_user'], - mailbox['imap_pass'], - mailbox['imap_mailbox'] - ) + imap_mb = IMAPmailbox(mailbox) except IMAPmailboxException as e: print(e.message) continue @@ -57,6 +46,9 @@ class Gulag: msg = unseen['msg'] msg_size = len(str(msg)) r5321_from = email.header.decode_header(msg['Return-Path'])[0][0] + if(r5321_from is not '<>'): + r5321_from = r5321_from.replace("<","") + r5321_from = r5321_from.replace(">","") r5321_rcpts = None try: r5321_rcpts = email.header.decode_header(msg['X-Envelope-To-Blocked'])[0][0] @@ -149,6 +141,30 @@ class Gulag: except GulagDBException as e: raise GulagException("GulagDBException: " + e.message) from e + def get_quarmail(self,args): + qm_db = None + try: + qm_db = self.db.get_quarmail({ + "id": args['id'] + }) + except GulagDBException as e: + raise GulagException("GulagDBException: " + e.message) from e + if 'rfc822_message' not in args: + return qm_db + mailbox = None + try: + mailbox = self.db.get_mailbox(qm_db['mailbox_id']) + except GulagDBException as e: + raise GulagException(e.message) from e + imap_mb = None + try: + imap_mb = IMAPmailbox(mailbox) + qm_db['rfc822_message'] = imap_mb.get_message(qm_db['imap_uid']) + return qm_db + except IMAPmailboxException as e: + print(e.message) + raise GulagException(e.message) from e + def rspamd_http2imap(self,mailbox_id): mailbox = None try: @@ -180,12 +196,7 @@ class Gulag: # Use IMAP“s APPEND command to store the message into mailbox imap_mb = None try: - imap_mb = IMAPmailbox( - mailbox['imap_server'], - mailbox['imap_user'], - mailbox['imap_pass'], - mailbox['imap_mailbox'] - ) + imap_mb = IMAPmailbox(mailbox) imap_mb.append_message(msg) except IMAPmailboxException as e: raise GulagException(e.message) from e diff --git a/app/GulagDB.py b/app/GulagDB.py index 6cd59eb..c453ced 100644 --- a/app/GulagDB.py +++ b/app/GulagDB.py @@ -10,15 +10,25 @@ class GulagDB: conn = None uri_prefixes = None - def __init__(self, server, user, password, name, uri_prefixes): +# def __init__(self, server, user, password, name, uri_prefixes): + def __init__(self, args, uri_prefixes): try: - self.conn = mariadb.connect( - host=server, - user=user, - password=password, - database=name, - autocommit=True - ) + if 'unix_socket' in args: + self.conn = mariadb.connect( + unix_socket=args['unix_socket'], + user=args['user'], + password=args['password'], + database=args['name'], + autocommit=True + ) + else: + self.conn = mariadb.connect( + host=args['server'], + user=args['user'], + password=args['password'], + database=args['name'], + autocommit=True + ) self.uri_prefixes = uri_prefixes except mariadb.Error as e: raise GulagDBException(e) from e @@ -32,8 +42,8 @@ class GulagDB: cursor.execute("select * from Mailboxes;") results = [] data = cursor.fetchall() - if data == None: - return results + if not data: + raise GulagDBException("No mailboxes found in DB!") desc = cursor.description for tuple in data: dict = {} @@ -56,7 +66,7 @@ class GulagDB: "select * from Mailboxes where email_address='" + mailbox_id + "' limit 1;" ) data = cursor.fetchall() - if data == None: + if not data: raise GulagDBException("Mailbox '" + mailbox_id + "' does not exist!") desc = cursor.description tuple = data[0] @@ -101,19 +111,14 @@ class GulagDB: except mariadb.Error as e: raise GulagDBException(e) from e -# def get_quarmails(self,mailbox_id): def get_quarmails(self): try: cursor = self.conn.cursor() -# cursor.execute( -# "select * from QuarMails where mailbox_id='%s';", -# (mailbox_id) -# ) cursor.execute("select * from QuarMails;") results = [] data = cursor.fetchall() - if data == None: - return results + if not data: + raise GulagDBException("No Quarmails found in DB!") desc = cursor.description cursor.close() for tuple in data: @@ -129,6 +134,29 @@ class GulagDB: except mariadb.Error as e: raise GulagDBException(e) from e + def get_quarmail(self,args): + try: + cursor = self.conn.cursor() + # TODO: build SQL query by args + query = "select * from QuarMails where id='" + args['id'] + "';" + cursor.execute(query) + data = cursor.fetchall() + if not data: + raise GulagDBException("Quarmail with id '"+ args['id'] + "' does not exist!") + desc = cursor.description + cursor.close() + tuple = data[0] + dict = {} + for (name, value) in zip(desc, tuple): + if(name[0] == 'ctime'): + dict[name[0]] = value.strftime('%Y-%m-%d %H:%M:%S') + else: + dict[name[0]] = value + dict['href'] = self.uri_prefixes['quarmails'] + str(dict['id']) + return QuarMail(dict).__dict__ + except mariadb.Error as e: + raise GulagDBException(e) from e + def get_deprecated_mails(self,retention_period): try: cursor = self.conn.cursor() @@ -136,7 +164,7 @@ class GulagDB: cursor.execute(query) results = [] data = cursor.fetchall() - if data == None: + if not data: return results desc = cursor.description for tuple in data: diff --git a/app/GulagMailbox.py b/app/GulagMailbox.py index f8f29d6..45dfbd1 100644 --- a/app/GulagMailbox.py +++ b/app/GulagMailbox.py @@ -15,11 +15,11 @@ class IMAPmailbox: imap_mailbox = None mailbox = None - def __init__(self, imap_server, imap_user, imap_pass, imap_mailbox): - self.imap_server = imap_server - self.imap_user = imap_user - self.imap_pass = imap_pass - self.imap_mailbox = imap_mailbox + def __init__(self, mb_ref): + self.imap_server = mb_ref['imap_server'] + self.imap_user = mb_ref['imap_user'] + self.imap_pass = mb_ref['imap_pass'] + self.imap_mailbox = mb_ref['imap_mailbox'] try: self.mailbox = imaplib.IMAP4(self.imap_server) rv, data = self.mailbox.login(self.imap_user, self.imap_pass) @@ -59,14 +59,14 @@ class IMAPmailbox: return results def get_message(self,imap_uid): - rv, data = self.mailbox.uid('FETCH', imap_uid, '(RFC822)') + rv, data = self.mailbox.uid('FETCH', str(imap_uid), '(RFC822)') if rv != 'OK': raise IMAPmailboxException("ERROR getting message: %s", str(imap_uid)) - return email.message_from_bytes(data[0][1]) + return data[0][1].decode("utf-8") def get_attachments(self,imap_uid): results = [] - rv, data = self.mailbox.uid('FETCH', imap_uid, '(RFC822)') + rv, data = self.mailbox.uid('FETCH', str(imap_uid), '(RFC822)') if rv != 'OK': raise IMAPmailboxException("ERROR getting message: %s", str(imap_uid)) msg = email.message_from_bytes(data[0][1]) @@ -96,5 +96,8 @@ class IMAPmailbox: str(message).encode('utf-8') ) if rv != 'OK': - raise IMAPmailboxException("ERROR appending message!") + raise IMAPmailboxException("ERROR appending message: " + rv) + + def expunge_message(self,imap_uid): + return True diff --git a/app/Resources.py b/app/Resources.py index fff525e..882265e 100644 --- a/app/Resources.py +++ b/app/Resources.py @@ -1,4 +1,4 @@ -#from flask import request +from flask import request from flask_restful import Resource, abort, reqparse from Gulag import GulagException @@ -47,11 +47,17 @@ class ResQuarMails(GulagResource): try: return self.gulag.get_quarmails() except GulagException as e: - abort(500, message=e.message) + abort(400, message=e.message) class ResQuarMail(GulagResource): def get(self,id): - return {"resource": "QuarMail by ID"} + args = {"id": id} + try: + if(request.args.get('rfc822_message')): + args['rfc822_message'] = True + return self.gulag.get_quarmail(args) + except GulagException as e: + abort(400, message=e.message) class ResAttachments(GulagResource): def get(self): diff --git a/app/__pycache__/Gulag.cpython-35.pyc b/app/__pycache__/Gulag.cpython-35.pyc deleted file mode 100644 index df7ccbd..0000000 Binary files a/app/__pycache__/Gulag.cpython-35.pyc and /dev/null differ diff --git a/app/__pycache__/GulagDB.cpython-35.pyc b/app/__pycache__/GulagDB.cpython-35.pyc deleted file mode 100644 index 3a80b36..0000000 Binary files a/app/__pycache__/GulagDB.cpython-35.pyc and /dev/null differ diff --git a/app/__pycache__/GulagMailbox.cpython-35.pyc b/app/__pycache__/GulagMailbox.cpython-35.pyc deleted file mode 100644 index 6cac5b4..0000000 Binary files a/app/__pycache__/GulagMailbox.cpython-35.pyc and /dev/null differ diff --git a/app/__pycache__/Resources.cpython-35.pyc b/app/__pycache__/Resources.cpython-35.pyc deleted file mode 100644 index ce7be94..0000000 Binary files a/app/__pycache__/Resources.cpython-35.pyc and /dev/null differ diff --git a/app/gulag_server.py b/app/gulag_server.py index 934df8e..fc74a53 100755 --- a/app/gulag_server.py +++ b/app/gulag_server.py @@ -4,8 +4,10 @@ import argparse,sys from flask import Flask from flask_restful import Api from Gulag import Gulag,GulagException -from Resources import ResRoot,ResMailboxes,ResQuarMails,ResAttachments,ResRSPAMDImporter - +from Resources import (ResRoot,ResMailboxes, + ResQuarMails,ResQuarMail,ResAttachments, + ResRSPAMDImporter +) parser = argparse.ArgumentParser() parser.add_argument('--config', required=True, help="Path to config file") args = parser.parse_args() @@ -29,6 +31,10 @@ try: '/api/v1/quarmails/', resource_class_kwargs={'gulag_object': gulag} ) + api.add_resource(ResQuarMail, + '/api/v1/quarmails/', + resource_class_kwargs={'gulag_object': gulag} + ) api.add_resource(ResAttachments, '/api/v1/attachments/', resource_class_kwargs={'gulag_object': gulag} @@ -38,8 +44,8 @@ try: resource_class_kwargs={'gulag_object': gulag} ) if __name__ == '__main__': + # following code snippet will be intercepted by uwsgi! app.run(debug=False, - # will be overriden by uwsgi.ini host=gulag.config['daemon']['listen_host'], port=gulag.config['daemon']['listen_port'] ) diff --git a/config/gulag-config.json b/config/gulag-config.json index db16f69..b07b300 100644 --- a/config/gulag-config.json +++ b/config/gulag-config.json @@ -17,13 +17,13 @@ } }, "uri_prefixes": { - "root": "https:///api/v1/", - "mailboxes": "https:///api/v1/mailboxes/", - "quarmails": "https:///api/v1/quarmails/", - "attachments": "https:///api/v1/attachments/" + "root": "https://gulag.example.org/api/v1/", + "mailboxes": "https://gulag.example.org/api/v1/mailboxes/", + "quarmails": "https://gulag.example.org/api/v1/quarmails/", + "attachments": "https://gulag.example.org/api/v1/attachments/" }, "db":{ - "server": "127.0.0.1", + "unix_socket": "/mysqld/mysqld.sock", "user": "root", "password": "", "name": "Gulag" diff --git a/config/vassals/gulag_server.ini b/config/vassals/gulag_server.ini index efa0ddc..a3fea90 100644 --- a/config/vassals/gulag_server.ini +++ b/config/vassals/gulag_server.ini @@ -7,4 +7,5 @@ plugin = python3 python-path = /app wsgi-file = /app/uwsgi.py pyargv = --config /config/gulag-config.json -socket = /socket/uwsgi-gulag_server.sock +socket = /socket/gulag_uwsgi.sock +http-socket = :9090