Manage dovecot sieve scripts too

This commit is contained in:
Antonio J. Delgado 2024-09-30 11:37:04 +03:00
parent 768eaf3675
commit 7358e3bb50
4 changed files with 44 additions and 10 deletions

View file

@ -13,14 +13,14 @@ import imaplib
import email
from signal import signal, SIGINT
import json
from yaml import load, dump
try:
from yaml import CLoader as Loader, CDumper as Dumper
except ImportError:
from yaml import Loader, Dumper
import re
import codecs
import time
from yaml import load
try:
from yaml import CLoader as Loader
except ImportError:
from yaml import Loader
import click
import click_config_file
@ -64,6 +64,8 @@ class ImapFilter:
def _process_filters(self):
matches = 0
for mailbox in self.config['mailboxes']:
if mailbox['mailbox'] == 'INBOX' and self.config['sieve_scripts_path']:
self._create_sieve_script(mailbox['filters'])
self._log.debug(
"Processing mailbox '%s'...",
mailbox['mailbox']
@ -132,6 +134,32 @@ class ImapFilter:
)
return True
def _create_sieve_script(self, filters):
if os.path.exists(self.config['sieve_scripts_path']):
with open(self.config['sieve_scripts_path'], 'r', encoding='UTF-8') as sieve_script:
content = sieve_script.read()
else:
content = '# Managed by imap_filter. Some lines might get replaced if the match with rule name from imap_filter'
for mfilter in filters:
if 'field' in mfilter:
field = mfilter['field']
else:
field = 'From'
if 'regexp' in mfilter:
condition = f'allof (header :contains "{field}" "{mfilter['regexp']}")'
else:
condition = f'allof (header :contains "{field}" ["{'", "'.join(mfilter['words'])}"])'
search = f'^.* # imap_filter: rule name \'imap_filter_INBOX_{mfilter['name']}\''
replacement = f'if {condition} {{ fileinto "{mfilter['destination']}"; stop;}} # imap_filter: rule name \'imap_filter_INBOX_{mfilter['name']}\''
new_content = re.sub(search, replacement, content)
if content == new_content:
content += f"{replacement}\n"
else:
content = f"{new_content}\n"
with open(self.config['sieve_scripts_path'], 'w', encoding='UTF-8') as sieve_script:
sieve_script.write(content)
return True
def _process_message(self, message_id, data, mfilter):
'''Process a mail message'''
if isinstance(data[1], int):
@ -403,6 +431,11 @@ class ImapFilter:
'--filters-file', '-F', required=True,
help='JSON or YAML file containing a list of dictionaries with the filter rules.'
)
@click.option(
'--sieve-scripts-path',
'-P',
help='Path to create sieve scripts.'
)
@click_config_file.configuration_option()
def __main__(**kwargs):
return ImapFilter(**kwargs)

View file

@ -3,14 +3,14 @@ requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"
[project.urls]
Homepage = "__url__"
Homepage = "https://repos.susurrando.com/adelgado/imap_filter.git"
[project]
name = "imap_filter"
version = "0.0.1"
description = "IMAP filter tool"
readme = "README.md"
authors = [{ name = "Antonio J. Delgado", email = "" }]
authors = [{ name = "Antonio J. Delgado", email = "ad@susurrando.com" }]
license = { file = "LICENSE" }
classifiers = [
"License :: OSI Approved :: GPLv3 License",
@ -22,4 +22,4 @@ dependencies = [
"click",
"click_config_file",
]
requires-python = ">=3"
requires-python = ">=3"

View file

@ -1,2 +1,3 @@
click
click_config_file
click_config_file
pyyaml

View file

@ -13,7 +13,7 @@ setuptools.setup(
author="Antonio J. Delgado",
version=config['metadata']['version'],
name=config['metadata']['name'],
author_email="",
author_email="ad@susurrando.com",
url="__url__",
description="IMAP filter tool",
long_description="README.md",