From 9e32573ce74dd6a36b0019225038deae9ec7fee6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amadeusz=20=C5=BBo=C5=82nowski?= Date: Mon, 27 Nov 2017 23:31:47 +0000 Subject: [PATCH] Add filter verifing DKIM signature Filter tags e-mail having DKIM header with either `dkim-ok` or `dkim-fail`. --- afew/filters/DKIMValidityFilter.py | 39 ++++++++++++++++++++++++++++++ afew/tests/test_settings.py | 1 + setup.py | 2 ++ 3 files changed, 42 insertions(+) create mode 100644 afew/filters/DKIMValidityFilter.py diff --git a/afew/filters/DKIMValidityFilter.py b/afew/filters/DKIMValidityFilter.py new file mode 100644 index 0000000..76f8fcb --- /dev/null +++ b/afew/filters/DKIMValidityFilter.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +# SPDX-License-Identifier: ISC +# Copyright (c) Amadeusz Zolnowski + +from __future__ import print_function, absolute_import, unicode_literals + +import dkim + +from .BaseFilter import Filter + + +def verify_dkim(path): + ''' + Verify DKIM signature of an e-mail file. + + :param path: Path to the e-mail file. + :returns: Whether DKIM signature is valid or not. + ''' + with open(path, 'rb') as message_file: + message_bytes = message_file.read() + + return dkim.verify(message_bytes) + + +class DKIMValidityFilter(Filter): + ''' + Verifies DKIM signature of an e-mail which has DKIM header. + ''' + message = 'Verify DKIM signature' + header = 'DKIM-Signature' + + def __init__(self, database, ok_tag='dkim-ok', fail_tag='dkim-fail'): + super(DKIMValidityFilter, self).__init__(database) + self.dkim_tag = {True: ok_tag, False: fail_tag} + + def handle_message(self, message): + if message.get_header(self.header): + dkim_ok = all(map(verify_dkim, message.get_filenames())) + self.add_tags(message, self.dkim_tag[dkim_ok]) diff --git a/afew/tests/test_settings.py b/afew/tests/test_settings.py index f1127ad..570e8f5 100644 --- a/afew/tests/test_settings.py +++ b/afew/tests/test_settings.py @@ -27,6 +27,7 @@ def test_all_builtin_FilterRegistrys_exist(self): from afew import FilterRegistry self.assertEqual(sorted(['FolderNameFilter', 'ArchiveSentMailsFilter', + 'DKIMValidityFilter', 'DMARCReportInspectionFilter', 'InboxFilter', 'SpamFilter', diff --git a/setup.py b/setup.py index 7ee11b6..56dd0a7 100755 --- a/setup.py +++ b/setup.py @@ -11,6 +11,7 @@ def get_requires(): if os.environ.get('TRAVIS') != 'true': yield 'notmuch' yield 'chardet' + yield 'dkimpy' setup( name='afew', @@ -30,6 +31,7 @@ def get_requires(): 'afew.filter': [ 'Filter = afew.filters.BaseFilter:Filter', 'ArchiveSentMailsFilter = afew.filters.ArchiveSentMailsFilter:ArchiveSentMailsFilter', + 'DKIMValidityFilter = afew.filters.DKIMValidityFilter:DKIMValidityFilter', 'DMARCReportInspectionFilter = afew.filters.DMARCReportInspectionFilter:DMARCReportInspectionFilter', 'FolderNameFilter = afew.filters.FolderNameFilter:FolderNameFilter', 'HeaderMatchingFilter = afew.filters.HeaderMatchingFilter:HeaderMatchingFilter',