IMAPmailbox.get_headers() for bounces

This commit is contained in:
Dominik Chilla 2019-01-07 22:01:20 +01:00
parent ff04b9f3e4
commit 8fae189267
5 changed files with 106 additions and 28 deletions

View File

@ -263,14 +263,16 @@ class Gulag:
except(GulagException,GulagDBException) as e: except(GulagException,GulagDBException) as e:
logging.warning(whoami(self) + e.message) logging.warning(whoami(self) + e.message)
raise GulagException(whoami(self) + e.message) from e raise GulagException(whoami(self) + e.message) from e
if 'rfc822_message' not in args: if 'rfc822_message' not in args and 'headers' not in args:
return { return {
'quarmails': qms_db, 'quarmails': qms_db,
'rfc822_messages': {} 'rfc822_messages': {},
'headers': {}
} }
# recognize all IMAP mailboxes to read from # recognize all IMAP mailboxes to read from
# and store rfc822-messages under it # and store rfc822-messages under it
mailboxes = {} mailboxes = {}
headers = {}
for qm in qms_db: for qm in qms_db:
if qm['mailbox_id'] not in mailboxes: if qm['mailbox_id'] not in mailboxes:
mailboxes[qm['mailbox_id']] = {} mailboxes[qm['mailbox_id']] = {}
@ -290,18 +292,29 @@ class Gulag:
for qm_db in qms_db: for qm_db in qms_db:
if qm_db['imap_uid'] not in mailboxes[mailbox_id]: if qm_db['imap_uid'] not in mailboxes[mailbox_id]:
try: try:
if 'rfc822_message' in args:
mailboxes[mailbox_id][qm_db['imap_uid']] = imap_mb.get_message( mailboxes[mailbox_id][qm_db['imap_uid']] = imap_mb.get_message(
qm_db['imap_uid'] qm_db['imap_uid']
).decode("utf-8") ).decode("utf-8")
elif 'headers' in args:
mailboxes[mailbox_id][qm_db['imap_uid']] = imap_mb.get_headers(
qm_db['imap_uid']
).decode("utf-8")
except IMAPmailboxException as e: except IMAPmailboxException as e:
logging.warning(whoami(self) + e.message) logging.warning(whoami(self) + e.message)
raise GulagException(whoami(self) + e.message) from e raise GulagException(whoami(self) + e.message) from e
imap_mb.close() imap_mb.close()
# end for mailboxes # end for mailboxes
if 'rfc822_message' in args:
return { return {
"quarmails": qms_db, "quarmails": qms_db,
"rfc822_messages": mailboxes "rfc822_messages": mailboxes
} }
elif 'headers' in args:
return {
"quarmails": qms_db,
"headers": mailboxes
}
def get_quarmail(self,args): def get_quarmail(self,args):
qm_db = None qm_db = None
@ -312,7 +325,7 @@ class Gulag:
except GulagDBException as e: except GulagDBException as e:
logging.warning(whoami(self) + e.message) logging.warning(whoami(self) + e.message)
raise GulagException(whoami(self) + e.message) from e raise GulagException(whoami(self) + e.message) from e
if 'rfc822_message' not in args: if 'rfc822_message' not in args and 'headers' not in args:
return qm_db return qm_db
# pull full RFC822 message from IMAP mailbox # pull full RFC822 message from IMAP mailbox
mailbox = None mailbox = None
@ -326,29 +339,20 @@ class Gulag:
imap_mb = None imap_mb = None
try: try:
imap_mb = IMAPmailbox(mailbox) imap_mb = IMAPmailbox(mailbox)
if 'rfc822_message' in args:
qm_db['rfc822_message'] = imap_mb.get_message( qm_db['rfc822_message'] = imap_mb.get_message(
qm_db['imap_uid'] qm_db['imap_uid']
).decode("utf-8") ).decode("utf-8")
elif 'headers' in args:
qm_db['headers'] = imap_mb.get_headers(
qmat_db['imap_uid']
)
imap_mb.close() imap_mb.close()
return qm_db return qm_db
except IMAPmailboxException as e: except IMAPmailboxException as e:
logging.warning(whoami(self) + e.message) logging.warning(whoami(self) + e.message)
raise GulagException(whoami(self) + e.message) from e raise GulagException(whoami(self) + e.message) from e
def release_quarmail(self,args):
try:
quarmail = self.get_quarmail({
"quarmail_id": args['quarmail_id'],
"rfc822_message": True
})
#
# TODO: re-send quarmail to original env_rcpt
# TODO: self.delete_quarmail() if arg['purge']
except GulagNotFoundException as e:
raise GulagNotFoundException(whoami(self) + e.message) from e
except GulagException as e:
raise GulagException(whoami(self) + e.message) from e
def delete_quarmail(self, args): def delete_quarmail(self, args):
qm_db = None qm_db = None
try: try:
@ -394,6 +398,44 @@ class Gulag:
imap_mb.close() imap_mb.close()
return return
def release_quarmail(self,args):
try:
quarmail = self.get_quarmail({
"quarmail_id": args['quarmail_id'],
"rfc822_message": True
})
# TODO: re-send quarmail to original env_rcpt
# TODO: self.delete_quarmail() if arg['purge']
except GulagNotFoundException as e:
raise GulagNotFoundException(whoami(self) + e.message) from e
except GulagException as e:
raise GulagException(whoami(self) + e.message) from e
def bounce_quarmail(self,args):
try:
quarmail = self.get_quarmail({
"quarmail_id": args['quarmail_id'],
"rfc822_message": True
})
# TODO: bounce quarmail headers-only to quarmail['env_from']
# TODO: self.delete_quarmail() if arg['purge']
except GulagNotFoundException as e:
raise GulagNotFoundException(whoami(self) + e.message) from e
except GulagException as e:
raise GulagException(whoami(self) + e.message) from e
def forward_quarmail(self,args):
try:
quarmail = self.get_quarmail({
"quarmail_id": args['quarmail_id'],
"rfc822_message": True
})
# TODO: send quarmail to args['env_rcpt']
except GulagNotFoundException as e:
raise GulagNotFoundException(whoami(self) + e.message) from e
except GulagException as e:
raise GulagException(whoami(self) + e.message) from e
def get_quarmail_attachments(self,args): def get_quarmail_attachments(self,args):
try: try:
return self.db.get_quarmail_attachments(args['quarmail_id']) return self.db.get_quarmail_attachments(args['quarmail_id'])

View File

@ -1,6 +1,7 @@
import imaplib import imaplib
import email import email
import email.header import email.header
from email.parser import HeaderParser
import time import time
import re import re
from GulagUtils import whoami from GulagUtils import whoami
@ -103,6 +104,14 @@ class IMAPmailbox:
) )
return True return True
def get_headers(self,imap_uid):
rv, data = self.mailbox.uid('FETCH', str(imap_uid), '(BODY[HEADER])')
if rv != 'OK':
raise IMAPmailboxException(whoami(self) +
"ERROR getting headers: %s", str(imap_uid)
)
return data[0][1]
def get_attachment(self,imap_uid,filename): def get_attachment(self,imap_uid,filename):
msg = email.message_from_bytes(self.get_message(imap_uid)) msg = email.message_from_bytes(self.get_message(imap_uid))
for part in msg.walk(): for part in msg.walk():

View File

@ -71,6 +71,8 @@ class ResQuarMail(GulagResource):
abort(404, message=e.message) abort(404, message=e.message)
except GulagException as e: except GulagException as e:
abort(500, message=e.message) abort(500, message=e.message)
def delete(self,quarmail_id):
pass
def delete(self,quarmail_id): def delete(self,quarmail_id):
args = {"quarmail_id": quarmail_id} args = {"quarmail_id": quarmail_id}
try: try:
@ -93,6 +95,18 @@ class ResQuarMailRelease(GulagResource):
except GulagException as e: except GulagException as e:
abort(500, message=e.message) abort(500, message=e.message)
class ResQuarMailBounce(GulagResource):
def get(self,quarmail_id):
args = {"quarmail_id": quarmail_id}
if(request.args.get('purge')):
args['purge'] = True
try:
return self.gulag.bounce_quarmail(args)
except GulagNotFoundException as e:
abort(404, message=e.message)
except GulagException as e:
abort(500, message=e.message)
class ResQuarMailAttachments(GulagResource): class ResQuarMailAttachments(GulagResource):
def get(self,quarmail_id): def get(self,quarmail_id):
args = {"quarmail_id": quarmail_id} args = {"quarmail_id": quarmail_id}

View File

@ -17,3 +17,5 @@ RUN env; set -ex ; \
&& /bin/mkdir /config /socket /app && /bin/mkdir /config /socket /app
COPY app/*.py /app/ COPY app/*.py /app/
CMD ["/usr/bin/uwsgi","--emperor","/config/vassals"]

View File

@ -50,6 +50,10 @@ paths:
type: string type: string
required: false required: false
description: get full RFC822 email message for each QuarMail object description: get full RFC822 email message for each QuarMail object
- in: query
name: headers
description: get all email headers for each QuarMail object
required: false
- in: query - in: query
name: filters name: filters
type: string type: string
@ -81,9 +85,13 @@ paths:
type: integer type: integer
- in: query - in: query
name: rfc822_message name: rfc822_message
description: if set to a (random) value, full RFC822 email message will be returned as well description: if set to a (random) value, full RFC822 email message will be returned
type: string type: string
required: false required: false
- in: query
name: headers
description: if set to a (random) value, all email headers will be returned
required: false
responses: responses:
200: 200:
description: quarantined email object description: quarantined email object
@ -311,6 +319,9 @@ definitions:
rfc822_message: rfc822_message:
type: string type: string
description: full RFC822 email message description: full RFC822 email message
headers:
type: string
description: email headers
Attachment: Attachment:
type: object type: object
required: required: