From ecbb742d46fe982dba256bdc1d150790c887642d Mon Sep 17 00:00:00 2001 From: VG Date: Sun, 12 Jun 2016 14:34:15 +0200 Subject: Make climl work, from receiving to sending to all - add a todo list (in french) for futur evolutions - add a hook to modify emails adding a reply-to - add a traceback trace print for sockets/ssl errors --- .gitignore | 1 + TODO-fr.rst | 8 ++++++++ climl/__init__.py | 6 +----- climl/hooks.py | 29 ++++++++++++++++++++++------- climl/imap.py | 1 + 5 files changed, 33 insertions(+), 12 deletions(-) create mode 100644 TODO-fr.rst diff --git a/.gitignore b/.gitignore index 59446aa..effd51a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ __pycache__ *.pyc *.whl *.egg-info +*-recipients.txt # test suite /.cache diff --git a/TODO-fr.rst b/TODO-fr.rst new file mode 100644 index 0000000..df9fe70 --- /dev/null +++ b/TODO-fr.rst @@ -0,0 +1,8 @@ +- coder step validate_sender pour les listes fermées. +- noter que climl fonctionne avec des copains, il marque juste + les mails answered/unanswerd et un autre outil fera les passes sur les mails + pour descendre ceux qui sont traités ou les archiver suivant l'envie, mais + il faut documenter cette partie. +- écrire note/exemple hook envoi mail admin/sender when discard. +- écrire note/exemple hook qui reformate le mail. +- ajouter des tests unitaires. diff --git a/climl/__init__.py b/climl/__init__.py index e730690..c6f6db4 100644 --- a/climl/__init__.py +++ b/climl/__init__.py @@ -23,8 +23,6 @@ def on_email(content, hooks, conf): print('hook wanted to stop processing for current email') traceback.print_exc() print('◀▬▬▬▬▬▬▬') - print('now, raising exception (for dev purpose only)') - raise interface.HookAbortError('dev purpose abort') def conf_boolean_postprocess(src): @@ -49,15 +47,13 @@ def main(): confpath = os.path.expanduser('~/.config/climl/climl.cfg') conf = conf_postprocess(confparser.read_conf(confpath)) - # TODO: how to load hooks with a dependency tree and sort them accordingly - # to generate hooks list ? - # now try a fixed list ? hooksfuncs = ( hooks.hook_extract_listname, hooks.hook_check_ml_restrictions, # open/private ml hooks.hook_validate_poster, hooks.hook_process_subscribe_queries, hooks.hook_generate_rcpt_list, + hooks.hook_modify_reply_to, hooks.hook_send_all, ) print('starting imap.main loop') diff --git a/climl/hooks.py b/climl/hooks.py index e4a0a8e..027329b 100644 --- a/climl/hooks.py +++ b/climl/hooks.py @@ -5,7 +5,7 @@ from . import interface def hook_extract_listname(context): lines = context['content'].split(b'\n') for line in lines: - if line.startswith(b'Delivered-To: '): + if line.startswith(b'To: '): listname = line.split()[1].decode('ascii') context['listname'] = listname.split('@')[0] context['listaddress'] = listname @@ -26,6 +26,20 @@ def hook_process_subscribe_queries(context): pass +def hook_modify_reply_to(context): + content = context['content'] + listaddress = context['listaddress'].encode('ascii') + try: + index = content.index(b'\r\n\r\n') + context['content'] = b''.join([ + content[0:index], + b'\r\nReply-To: ', listaddress, # same header line + content[index:]]) + except ValueError as e: + raise interface.HookAbortError('bad email, missing header separator') \ + from e + + def hook_generate_rcpt_list(context): listname = context.get('listname', None) if not listname: @@ -51,9 +65,10 @@ def hook_send_all(context): raise interface.HookStopIteration() # TODO: how to send emails here ? - smtp_server = smtplib.SMTP(context['conf']['smtp.server']) - #smtp_server.set_debuglevel(1) - smtp_server.sendmail(listaddress, - context['recipients'], - context['content']) - smtp_server.quit() + print('server_smtp:', context['conf']['smtp.server']) + with smtplib.SMTP('devys.org') as smtp_server: + #smtp_server.set_debuglevel(1) + smtp_server.sendmail(listaddress, + context['recipients'], + context['content'], + mail_options=['SMTPUTF8']) diff --git a/climl/imap.py b/climl/imap.py index c23a006..e2ae36e 100644 --- a/climl/imap.py +++ b/climl/imap.py @@ -156,4 +156,5 @@ def main(callback=None, conf=None): ssl.SSLError, ssl.CertificateError): print('socket/ssl error, retrying in 10s...') + traceback.print_exc() time.sleep(10) # wait between retries -- cgit v1.2.3