diff --git a/eo-redmine-mailfilter.sh b/eo-redmine-mailfilter.sh index 0aeaf3a..b983cf0 100755 --- a/eo-redmine-mailfilter.sh +++ b/eo-redmine-mailfilter.sh @@ -6,6 +6,7 @@ fi export REDMINE_KEY=`cat /etc/redmine-key` export REDMINE_URL='https://dev.entrouvert.org' +export ATTACHMENTS_BLACKLIST=/etc/redmine.attachments.blacklist.json export PROJECT=`echo $RECIPIENT | sed 's/support-\([a-z0-9-]*\)@.*/\1/'` diff --git a/mail2redmine.py b/mail2redmine.py index e2c0096..0374116 100644 --- a/mail2redmine.py +++ b/mail2redmine.py @@ -3,6 +3,7 @@ import os import sys import email +import hashlib import tempfile import uuid import smtplib @@ -18,6 +19,7 @@ TRACKER_ID = os.environ.get('REDMINE_TRACKER', '3') PROJECT_ID = os.environ.get('PROJECT') TECH_MANAGER_ROLE_ID = os.environ.get('TECH_MANAGER_ROLE_ID', 10) FALLBACK_EMAIL = os.environ.get('FALLBACK_EMAIL', 'support@entrouvert.com') +ATTACHMENTS_BLACKLIST = os.environ.get('ATTACHMENTS_BLACKLIST', None) class UnknownUser(Exception): @@ -37,7 +39,7 @@ def parse_header(header_text): return u' '.join(headers) -def parse_attachment(data): +def parse_attachment(data, blacklist=None): if data.get('Content-type', '').startswith('multipart/'): return None if data.get('Content-type', '').startswith('text/plain') and not ( @@ -46,6 +48,8 @@ def parse_attachment(data): file_data = data.get_payload(decode=True) if not file_data: return None + if blacklist and hashlib.sha1(file_data).hexdigest() in blacklist.get('sha1sums'): + return None with tempfile.NamedTemporaryFile(delete=False) as attachment: attachment.write(file_data) attachment.flush() @@ -74,13 +78,20 @@ def create_ticket(mail): if not users: raise UnknownUser + blacklist = {'sha1sums': []} + if ATTACHMENTS_BLACKLIST: + try: + blacklist = json.load(open(ATTACHMENTS_BLACKLIST)) + except (IOError, ValueError): + pass + r = Redmine(REDMINE_URL, key=REDMINE_KEY, impersonate=users[0].login) attachments = [] body = u'' for data in mail.walk(): - attachment = parse_attachment(data) + attachment = parse_attachment(data, blacklist) if attachment: attachments.append(attachment) elif data.get_content_type() == "text/plain": diff --git a/test_mail2redmine.py b/test_mail2redmine.py index 0808d35..61f894e 100644 --- a/test_mail2redmine.py +++ b/test_mail2redmine.py @@ -56,6 +56,23 @@ def test_mail_with_two_attachments(message): attachments.append(attachment) assert len(attachments) == 2 +@pytest.mark.parametrize('message', ('mail_dumps/1461591292.25165_17.dor-lomin_2.mail',)) +def test_mail_attachment_blacklist(message): + mail = mail2redmine.email.message_from_file(file(message)) + attachments = [] + blacklist = {'sha1sums': ['ab7c57983551204500d67f8ec3dd54a01e81d75d']} + for data in mail.walk(): + attachment = mail2redmine.parse_attachment(data, blacklist=blacklist) + if attachment: + assert 'path' in attachment + assert 'content_type' in attachment + assert 'filename' in attachment + assert isinstance(attachment['filename'], unicode) + assert attachment['filename'] == u'201601-mise-a-jour-Publik.pdf' + attachments.append(attachment) + assert len(attachments) == 1 + + @mock.patch('mail2redmine.Redmine') def test_ticket_creation_by_unknown_user(mocked_redmine, dump): user = mock.Mock()