HTTP2SMTP relay for Rspamd :)

This commit is contained in:
Dominik Chilla 2018-11-18 23:56:38 +01:00
parent 6c23eda022
commit 71d6b0b200
6 changed files with 103 additions and 6 deletions

View File

@ -9,12 +9,18 @@ class Mailbox:
email_address = None
name = None
imap_server = None
imap_port = None
imap_security = None
imap_user = None
imap_pass = None
imap_mailbox = None
imap_mailbox_fp = None
imap_separator = None
smtp_server = None
smtp_port = None
smtp_security = None
smtp_user = None
smtp_pass = None
comment = None
href = None
@ -37,6 +43,8 @@ class Mailbox:
)
else:
raise MailboxException("'imap_security' is a mandatory!")
if 'imap_port' in mb_ref:
self.imap_port = mb_ref['imap_port']
if 'imap_user' not in mb_ref:
raise MailboxException("'imap_user' is mandatory!")
self.imap_user = mb_ref['imap_user']
@ -52,6 +60,16 @@ class Mailbox:
if 'imap_separator' not in mb_ref:
raise MailboxException("'imap_separator' is mandatory!")
self.imap_seperator = mb_ref['imap_separator']
if 'smtp_server' in mb_ref:
self.smtp_server = mb_ref['smtp_server']
if 'smtp_port' in mb_ref:
self.smtp_port = mb_ref['smtp_port']
if 'smtp_security' in mb_ref:
self.smtp_security = mb_ref['smtp_security']
if 'smtp_user' in mb_ref:
self.smtp_user = mb_ref['smtp_user']
if 'smtp_pass' in mb_ref:
self.smtp_pass = mb_ref['smtp_pass']
if 'comment' in mb_ref:
self.comment = mb_ref['comment']
if 'href' in mb_ref:

View File

@ -1,5 +1,7 @@
import json,sys
import email,email.header
import email,email.header,email.message
from flask import request
from smtplib import SMTP
from GulagDB import GulagDB,GulagDBException
from GulagMailbox import IMAPmailbox,IMAPmailboxException
@ -139,4 +141,41 @@ class Gulag:
return self.db.get_quarmails()
except GulagDBException as e:
raise GulagException("GulagDBException: " + e.message) from e
def rspamd_http2smtp(self,mailbox_id):
mailbox = None
try:
mailbox = self.db.get_mailbox(mailbox_id)
except GulagDBException as e:
raise GulagException(e.message) from e
if(request.headers.get('X-Rspamd-From') == None):
raise GulagException("Missing Rspamd-specific headers (e.g. X-Rspamd-From)!")
# recompose rejected mail that will be sent to quarantine mailbox
#FIXME: print("mx_queue_id: " + request.headers.get('X-Rspamd-Qid'))
msg = None
try:
msg = email.message_from_string(request.get_data(as_text=True))
rcpts_hdr = str(request.headers.get('X-Rspamd-Rcpt'))
# FIXME: special chars []" rausstrippen! -> JSON!!!
print("RCPTs neu: " + rcpts_hdr)
msg.add_header("X-Envelope-To-Blocked", rcpts_hdr)
msg.add_header("X-Spam-Status", request.headers.get('X-Rspamd-Symbols'))
# except email.errors.* as e:
except:
raise GulagException(str(sys.exc_info()))
try:
with SMTP(host=mailbox['smtp_server'],port=mailbox['smtp_port']) as smtp:
try:
smtp.sendmail(
request.headers.get('X-Rspamd-From'),
mailbox_id,
msg.as_string()
)
except (SMTPRecipientsRefused,SMTPHeloError,SMTPSenderRefused,SMTPDataError) as e:
raise GulagException(str(e)) from e
except TimeoutError as e:
raise GulagException(str(e)) from e

View File

@ -49,6 +49,28 @@ class GulagDB:
except mariadb.Error as e:
raise GulagDBException(e) from e
def get_mailbox(self,mailbox_id):
try:
cursor = self.conn.cursor()
cursor.execute(
"select * from Mailboxes where email_address='" + mailbox_id + "' limit 1;"
)
data = cursor.fetchall()
if data == None:
raise GulagDBException("Mailbox '" + mailbox_id + "' does not exist!")
desc = cursor.description
tuple = data[0]
dict = {}
for (name, value) in zip(desc, tuple):
dict[name[0]] = value
dict['href'] = self.uri_prefixes['mailboxes'] + dict['email_address']
try:
return Mailbox(dict).__dict__
except MailboxException as e:
raise GulagDBException(e.message) from e
except mariadb.Error as e:
raise GulagDBException(e) from e
def add_quarmail(self, quarmail):
try:
cursor = self.conn.cursor()
@ -121,7 +143,7 @@ class GulagDB:
dict = {}
for (name, value) in zip(desc, tuple):
dict[name[0]] = value
results.append(QuarMail(dict).__dict__)
results.append(dict)
return results
except mariadb.Error as e:
raise GulagDBException(e) from e

View File

@ -1,6 +1,5 @@
from flask import request
from flask_restful import Resource, abort
from Entities import Mailbox,MailboxException,QuarMail,QuarMailException,Attachment,AttachmentException
#from flask import request
from flask_restful import Resource, abort, reqparse
from Gulag import GulagException
class GulagResource(Resource):
@ -62,3 +61,12 @@ class ResAttachment(GulagResource):
def get(self,id):
return {"resource": "Attachment by ID"}
class ResRSPAMDImporter(GulagResource):
def post(self,mailbox_id):
try:
self.gulag.rspamd_http2smtp(mailbox_id)
# TODO: Response mit Location-Header?
return {"resource: ": "HTTP2SMTP for RSPAMD"}
except GulagException as e:
abort(400, message=e.message)

View File

@ -4,7 +4,7 @@ import argparse,sys
from flask import Flask
from flask_restful import Api
from Gulag import Gulag,GulagException
from Resources import ResRoot,ResMailboxes,ResQuarMails,ResAttachments
from Resources import ResRoot,ResMailboxes,ResQuarMails,ResAttachments,ResRSPAMDImporter
parser = argparse.ArgumentParser()
parser.add_argument('--config', required=True, help="Path to config file")
@ -33,6 +33,10 @@ try:
'/api/v1/attachments/',
resource_class_kwargs={'gulag_object': gulag}
)
api.add_resource(ResRSPAMDImporter,
'/api/v1/mailboxes/<string:mailbox_id>/rspamdimporter/',
resource_class_kwargs={'gulag_object': gulag}
)
if __name__ == '__main__':
app.run(debug=False,
# will be overriden by uwsgi.ini

View File

@ -6,12 +6,18 @@ create table Mailboxes(
email_address varchar(767) not null primary key collate 'ascii_general_ci',
name varchar(256) not null,
imap_server varchar(256) not null default '127.0.0.1',
imap_port smallint unsigned not null default 143,
imap_security varchar(32) not null default 'plain',
imap_user varchar(256) not null,
imap_pass varchar(256) not null,
imap_mailbox varchar(256) not null default 'INBOX',
imap_mailbox_fp varchar(256) not null default 'false-positives',
imap_separator varchar(4) not null default '/',
smtp_server varchar(256) default null,
smtp_port smallint unsigned not null default 25,
smtp_security varchar(32) not null default 'plain',
smtp_user varchar(256) default null,
smtp_pass varchar(2048) default null,
comment varchar(256) default null
)ENGINE = InnoDB;
insert into Mailboxes (email_address,name,imap_user,imap_pass)