From cb572e1509a9207ad1af1220304d8e1b13cee9b4 Mon Sep 17 00:00:00 2001
From: Patrick Cernko <pcernko@mpi-klsb.mpg.de>
Date: Fri, 12 Jan 2024 16:19:03 +0100
Subject: [PATCH] fix: renamed blacklist to blocklist use special template
 mailman2sympa to set much more settings also set 'info' based on 'advertised'
 improved migration of subscribe_policy, added support for unsubscribe_policy
 support for mapping private_roster to 'review' support for anonymous_list,
 max_message_size and digestable added comment about ignored/unsupported
 mailman settings write list info into given info file

---
 gen_config.py | 116 +++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 97 insertions(+), 19 deletions(-)

diff --git a/gen_config.py b/gen_config.py
index 9275509..145cff1 100755
--- a/gen_config.py
+++ b/gen_config.py
@@ -6,38 +6,54 @@ import sys
 import argparse
 import xml.etree.ElementTree as ET
 
+
 parser = argparse.ArgumentParser(description='import mailman list to sympa')
 parser.add_argument('input')
 parser.add_argument('output')
-parser.add_argument('blacklist')
+parser.add_argument('info')
+parser.add_argument('blocklist')
 parser.add_argument('whitelist')
 args = parser.parse_args()
 
+
 old_vars = {}
 with open(args.input) as fd:
     exec(fd.read(), old_vars)
 
+
 xml = ET.Element("list")
 
 ET.SubElement(xml, "listname").text = old_vars['new_listname']
 ET.SubElement(xml, "status").text = 'open'
-ET.SubElement(xml, "type").text = 'private_working_group'
 ET.SubElement(xml, "topic").text = 'other'
+ET.SubElement(xml, "type").text = 'mailman2sympa'
+
 # subject is required in sympa
 if old_vars['description']:
     ET.SubElement(xml, "subject").text = old_vars['description']
 else:
     ET.SubElement(xml, "subject").text = old_vars['real_name']
+
 ET.SubElement(xml, "custom_subject").text = old_vars['subject_prefix'].strip().replace('[', '').replace(']', '')
+
 if old_vars['advertised']:
     ET.SubElement(xml, "visibility").text = 'noconceal'
+    ET.SubElement(xml, "info").text = 'open'
 else:
     ET.SubElement(xml, "visibility").text = 'conceal'
+    ET.SubElement(xml, "info").text = 'conceal'
 
-if old_vars['subscribe_policy'] == 1:
-    ET.SubElement(xml, "subscribe").text = 'auth'
-else:
+if old_vars['subscribe_policy'] == 0:
     ET.SubElement(xml, "subscribe").text = 'owner'
+elif old_vars['subscribe_policy'] == 1:
+    ET.SubElement(xml, "subscribe").text = 'auth_notify'
+else:
+    ET.SubElement(xml, "subscribe").text = 'auth_owner'
+
+if old_vars['unsubscribe_policy']:
+    ET.SubElement(xml, "unsubscribe").text = 'owner'
+else:
+    ET.SubElement(xml, "unsubscribe").text = 'open_notify'
 
 if old_vars['archive']:
     ET.SubElement(xml, "process_archive").text = 'on'
@@ -62,12 +78,21 @@ elif old_vars['reply_goes_to_list'] == 2:
     else:
         ET.SubElement(xml, 'value').text = 'other_email'
         ET.SubElement(xml, 'other_email').text = old_vars['reply_to_address']
-
 if old_vars['first_strip_reply_to']:
     ET.SubElement(r, 'apply').text = 'forced'
 else:
     ET.SubElement(r, 'apply').text = 'respect'
 
+if old_vars['private_roster'] == 0:
+    ET.SubElement(xml, 'review').text = 'public'
+elif old_vars['private_roster'] == 1:
+    ET.SubElement(xml, 'review').text = 'private'
+else:
+    ET.SubElement(xml, 'review').text = 'owner'
+
+if old_vars['anonymous_list']:
+    ET.SubElement(xml, 'anonymous_sender').text = old_vars['new_listname'] + '@' + old_vars['robot']
+
 # send
 if old_vars['generic_nonmember_action'] == 0: # accept
     ET.SubElement(xml, 'send').text = 'public'
@@ -77,10 +102,55 @@ elif old_vars['generic_nonmember_action'] >= 1: # hold, reject, discard
     else:
         ET.SubElement(xml, 'send').text = 'privateoreditorkey'
 
-# privateoreditorkey
-# public
-# private
+if old_vars['max_message_size'] == 0:
+    # if unlimited is requested, we set 100MB (in kB) as sympa does not support unlimited
+    old_vars['max_message_size'] = 100*1024
+if old_vars['max_message_size']*1024 > 5242880:
+    ET.SubElement(xml, 'max_size').text = str(old_vars['max_message_size']*1024) # sympa used bytes not kB
 
+if old_vars['digestable']:
+    ET.SubElement(xml, "digest").text = 'true'
+else:
+    ET.SubElement(xml, "digest").text = 'false'
+
+
+# send_welcome_msg not used, already handled in 'subscribe'
+# send_goodbye_msg not usable
+# admin_immed_notify ignored, we should always notify immediately
+# admin_notify_mchanges ignored, only used in d2-seminar
+# respond_to_post_requests unsupported
+# new_member_options unsupported
+# administrivia not used
+# nondigestable unsupported
+# scrub_nondigest not used
+# regular_exclude_lists not used
+# regular_exclude_ignore not used
+# regular_include_lists not used
+# digest_is_default not used
+# mime_is_default_digest not used
+# digest_size_threshhold unsupported
+# digest_send_periodic unsupported
+# digest_volume_frequency unsupported
+# obscure_addresses unsupported
+# dmarc_moderation_action not used
+# forward_auto_discards unsupported
+# require_explicit_destination unsupported
+# acceptable_aliases unsupported
+# max_num_recipients unsupported
+# header_filter_rules unsupported
+# bounce_processing not used
+# filter_mime_types not used
+# pass_mime_types not used
+# filter_filename_extensions not used
+# from_is_list unsupported with dmarc
+# umbrella_member_suffix not used
+# send_reminders unsupported for specific lists
+# goodbye_msg not used
+# digest_header not used
+# digest_footer not used
+
+
+# XXX: does this work?
 for owner in old_vars['owner']:
     o = ET.SubElement(xml, "owner", attrib={'multiple':'1'})
     ET.SubElement(o, "email").text = owner
@@ -89,20 +159,26 @@ for mod in old_vars['moderator']:
     o = ET.SubElement(xml, "editor", attrib={'multiple':'1'})
     ET.SubElement(o, "email").text = mod
 
-tree = ET.ElementTree(xml)
-tree.write(args.output, encoding='utf-8', xml_declaration=True)
 
-blacklist = []
-for black in sorted(set(old_vars['ban_list'] + old_vars['discard_these_nonmembers'])):
+tree = ET.ElementTree(xml)
+try:
+    tree.write(args.output, encoding='utf-8', xml_declaration=True)
+except Exception as e:
+    print(f'Failed to write XML for sympa: {e}', file=sys.stderr)
+    exit(1)
+
+blocklist = []
+for black in sorted(set(old_vars['ban_list'] + old_vars['hold_these_nonmembers'] + old_vars['reject_these_nonmembers'] + old_vars['discard_these_nonmembers'])):
     for char in '*^$':
         if char in black:
-            print(f"blacklist entry '{black}' contains regexp char '{char}', this won't work!", file=sys.stderr)
-    blacklist.append(black)
-if blacklist:
+            print(f"blocklist entry '{black}' contains regexp char '{char}', this won't work!", file=sys.stderr)
+            break
+    blocklist.append(black)
+if blocklist:
     # ensure non-empty file ends with newline
-    blacklist.append('')
-with open(args.blacklist, mode='w') as fd:
-    fd.write('\n'.join(blacklist))
+    blocklist.append('')
+with open(args.blocklist, mode='w') as fd:
+    fd.write('\n'.join(blocklist))
 
 whitelist = []
 for white in sorted(set(old_vars['accept_these_nonmembers'])):
@@ -116,3 +192,5 @@ if whitelist:
 with open(args.whitelist, mode='w') as fd:
     fd.write('\n'.join(whitelist))
 
+with open(args.info, mode='w') as fd:
+    fd.write(old_vars['info'])
-- 
GitLab