Change creation of mail users to dynamic
authorChristian Herdtweck <christian.herdtweck@intra2net.com>
Mon, 2 Dec 2019 12:08:24 +0000 (13:08 +0100)
committerChristian Herdtweck <christian.herdtweck@intra2net.com>
Thu, 19 May 2022 09:13:27 +0000 (11:13 +0200)
This is more easily extendable and avoids old bad habit of passing down
huge param dicts to very specific functions like this one.

User creation is hard to test, so there is no unittest for this yet. Manual
tests succeeded. Have to adapt QA tests and test there further.

Additionally to the original conversion, default mail users don't have
to be administrators.

src/mail_utils.py

index e3339a1..f07cf76 100644 (file)
@@ -42,6 +42,7 @@ from email.utils import parsedate_to_datetime
 from email.parser import BytesParser
 from email import policy
 
+from .simple_cnf import SimpleCnf
 # outsourced source, import required for compatiblity
 from .imap_mailbox import ImapMailbox           # pylint: disable=unused-import
 from .mail_validator import *                   # pylint: disable=unused-import
@@ -80,43 +81,59 @@ def prep_email_header(email_file, value, regex=None, criterion="envelopeto"):
                          % criterion)
 
 
-def create_users(usernames, config_file, params):
+def create_users(usernames, **extra_params):
     """
-    Create cyrus users from an absolute path to a user configuration file.
+    Create users for sending / receiving mail.
 
-    :param usernames: usernames of the created users
-    :type usernames: [str]
-    :param str config_file: template config file to use for each user
-                            configuration
-    :param params: template config file to use for each user configuration
-    :type params: {str, str}
-    :raises: :py:class:`RuntimeError` if the user exists already or cannot be
-              created
-    """
-    log.info("Creating new cyrus users %s", ", ".join(usernames))
-    cyrus_user_path = params.get("cyrus_user_path",
-                                 "/datastore/imap-mails/user/")
-
-    # check for existence round
-    for username in usernames:
-        if os.path.exists(os.path.join(cyrus_user_path,
-                                       username.replace(".", "^"))):
-            raise RuntimeError("The user %s was already created" % username)
+    The created user settings are complete with spamfilter settings and
+    groupare folders. User is per default member in groups 1 (admins) and
+    2 (all). This cannot yet be changed.
 
-    for username in usernames:
-        params["user"] = '%i: "%s"' % (-1, username)
-        params["user_fullname"] = username
-        params_regex = {"user": r'%s,(-?\d+: ".*")'}
-        arnied_wrapper.set_cnf_semidynamic([config_file],
-                                           params, params_regex)
+    :param usernames: Names of users to create
+    :type usernames: [str]
 
+    All other params are forwarded to user config
+    """
+    if isinstance(usernames, str):
+        usernames = [usernames,]
+    default_cnf = dict(
+        user_disabled="0",
+        user_locale="",
+        user_password="1234test",
+        user_spamfilter_blacklist="",
+        user_spamfilter_potential_spam_action="FOLDER",
+        user_spamfilter_potential_spam_action_destaddr="",
+        user_spamfilter_potential_spam_action_folder="Spamverdacht",
+        # TODO: this doesn't handle situations where the child variable should not be defined
+        user_spamfilter_potential_spam_threshold="1050",
+        user_spamfilter_spam_action="FOLDER",
+        user_spamfilter_spam_action_destaddr="",
+        user_spamfilter_spam_action_folder="Spam",
+        user_spamfilter_spam_deletedays="",
+        # TODO: this doesn't handle situations where the child variable should not be defined
+        user_spamfilter_spam_threshold="1080",
+        user_spamfilter_whitelist="",
+        user_groupware_folder_drafts="INBOX/Entwürfe",
+        user_groupware_folder_outbox="INBOX/Gesendete Elemente",
+        user_groupware_folder_trash="INBOX/Gelöschte Elemente",
+    )
+
+    cnf = SimpleCnf()
     for username in usernames:
-        if not os.path.exists(os.path.join(cyrus_user_path,
-                                           username.replace(".", "^"))):
-            raise RuntimeError("The user %s could not be created" % username)
-        else:
-            log.info("Added new user %s", username)
-    log.info("%s users successfully created!", len(usernames))
+        curr_cnf = default_cnf.copy()
+        curr_cnf['user_fullname'] = username
+        curr_cnf.update(extra_params)
+        children = SimpleCnf()
+        for key, value in curr_cnf.items():
+            if isinstance(value, dict):
+                children.add(key, children=value)
+            if not isinstance(value, str):
+                raise ValueError('Invalid value type for key "{}": {}'
+                                 .format(key, type(value)))
+            children.add(key, value)
+        children.add('user_group_member_ref', "2")
+        cnf.add('user', username, children=children, instance=-1)
+    cnf.apply()
 
 
 def parse_mail_file(file_name, headers_only=True, attachment_filenames=False,