We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Small feature - add mailu version in the admin UI 
Add mailu version in the admin UI 
I think it would nice to be able to see which version of mailu we are running, unless there is other simple way?

Thanks

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `core/admin/mailu/configuration.py`
Content:
```
1 import os
2 
3 from datetime import timedelta
4 import ipaddress
5 
6 DEFAULT_CONFIG = {
7     # Specific to the admin UI
8     'DOCKER_SOCKET': 'unix:///var/run/docker.sock',
9     'BABEL_DEFAULT_LOCALE': 'en',
10     'BABEL_DEFAULT_TIMEZONE': 'UTC',
11     'BOOTSTRAP_SERVE_LOCAL': True,
12     'RATELIMIT_STORAGE_URL': '',
13     'DEBUG': False,
14     'DEBUG_PROFILER': False,
15     'DEBUG_TB_INTERCEPT_REDIRECTS': False,
16     'DEBUG_ASSETS': '',
17     'DOMAIN_REGISTRATION': False,
18     'TEMPLATES_AUTO_RELOAD': True,
19     'MEMORY_SESSIONS': False,
20     'FETCHMAIL_ENABLED': True,
21     # Database settings
22     'DB_FLAVOR': None,
23     'DB_USER': 'mailu',
24     'DB_PW': None,
25     'DB_HOST': 'database',
26     'DB_NAME': 'mailu',
27     'SQLITE_DATABASE_FILE': 'data/main.db',
28     'SQLALCHEMY_DATABASE_URI': 'sqlite:////data/main.db',
29     'SQLALCHEMY_TRACK_MODIFICATIONS': False,
30     # Statistics management
31     'INSTANCE_ID_PATH': '/data/instance',
32     'STATS_ENDPOINT': '19.{}.stats.mailu.io',
33     # Common configuration variables
34     'SECRET_KEY': 'changeMe',
35     'DOMAIN': 'mailu.io',
36     'HOSTNAMES': 'mail.mailu.io,alternative.mailu.io,yetanother.mailu.io',
37     'POSTMASTER': 'postmaster',
38     'WILDCARD_SENDERS': '',
39     'TLS_FLAVOR': 'cert',
40     'INBOUND_TLS_ENFORCE': False,
41     'DEFER_ON_TLS_ERROR': True,
42     'AUTH_RATELIMIT_IP': '60/hour',
43     'AUTH_RATELIMIT_IP_V4_MASK': 24,
44     'AUTH_RATELIMIT_IP_V6_MASK': 56,
45     'AUTH_RATELIMIT_USER': '100/day',
46     'AUTH_RATELIMIT_EXEMPTION': '',
47     'AUTH_RATELIMIT_EXEMPTION_LENGTH': 86400,
48     'DISABLE_STATISTICS': False,
49     # Mail settings
50     'DMARC_RUA': None,
51     'DMARC_RUF': None,
52     'WELCOME': False,
53     'WELCOME_SUBJECT': 'Dummy welcome topic',
54     'WELCOME_BODY': 'Dummy welcome body',
55     'DKIM_SELECTOR': 'dkim',
56     'DKIM_PATH': '/dkim/{domain}.{selector}.key',
57     'DEFAULT_QUOTA': 1000000000,
58     'MESSAGE_RATELIMIT': '200/day',
59     'MESSAGE_RATELIMIT_EXEMPTION': '',
60     'RECIPIENT_DELIMITER': '',
61     # Web settings
62     'SITENAME': 'Mailu',
63     'WEBSITE': 'https://mailu.io',
64     'ADMIN': 'none',
65     'WEB_ADMIN': '/admin',
66     'WEB_WEBMAIL': '/webmail',
67     'WEBMAIL': 'none',
68     'RECAPTCHA_PUBLIC_KEY': '',
69     'RECAPTCHA_PRIVATE_KEY': '',
70     'LOGO_URL': None,
71     'LOGO_BACKGROUND': None,
72     # Advanced settings
73     'API': False,
74     'WEB_API': '/api',
75     'API_TOKEN': None,
76     'LOG_LEVEL': 'WARNING',
77     'SESSION_KEY_BITS': 128,
78     'SESSION_TIMEOUT': 3600,
79     'PERMANENT_SESSION_LIFETIME': 30*24*3600,
80     'SESSION_COOKIE_SECURE': None,
81     'CREDENTIAL_ROUNDS': 12,
82     'TLS_PERMISSIVE': True,
83     'TZ': 'Etc/UTC',
84     'DEFAULT_SPAM_THRESHOLD': 80,
85     'PROXY_AUTH_WHITELIST': '',
86     'PROXY_AUTH_HEADER': 'X-Auth-Email',
87     'PROXY_AUTH_CREATE': False,
88     'SUBNET': '192.168.203.0/24',
89     'SUBNET6': None,
90 }
91 
92 class ConfigManager:
93     """ Naive configuration manager that uses environment only
94     """
95 
96     DB_TEMPLATES = {
97         'sqlite': 'sqlite:////{SQLITE_DATABASE_FILE}',
98         'postgresql': 'postgresql://{DB_USER}:{DB_PW}@{DB_HOST}/{DB_NAME}',
99         'mysql': 'mysql+mysqlconnector://{DB_USER}:{DB_PW}@{DB_HOST}/{DB_NAME}',
100     }
101 
102     def __init__(self):
103         self.config = dict()
104 
105     def __get_env(self, key, value):
106         key_file = key + "_FILE"
107         if key_file in os.environ:
108             with open(os.environ.get(key_file)) as file:
109                 value_from_file = file.read()
110             return value_from_file.strip()
111         else:
112             return os.environ.get(key, value)
113 
114     def __coerce_value(self, value):
115         if isinstance(value, str) and value.lower() in ('true','yes'):
116             return True
117         elif isinstance(value, str) and value.lower() in ('false', 'no'):
118             return False
119         return value
120 
121     def init_app(self, app):
122         # get current app config
123         self.config.update(app.config)
124         # get environment variables
125         for key in os.environ:
126             if key.endswith('_ADDRESS'):
127                 self.config[key] = os.environ[key]
128 
129         self.config.update({
130             key: self.__coerce_value(self.__get_env(key, value))
131             for key, value in DEFAULT_CONFIG.items()
132         })
133 
134         # automatically set the sqlalchemy string
135         if self.config['DB_FLAVOR']:
136             template = self.DB_TEMPLATES[self.config['DB_FLAVOR']]
137             self.config['SQLALCHEMY_DATABASE_URI'] = template.format(**self.config)
138 
139         if not self.config.get('RATELIMIT_STORAGE_URL'):
140             self.config['RATELIMIT_STORAGE_URL'] = f'redis://{self.config["REDIS_ADDRESS"]}/2'
141 
142         self.config['SESSION_STORAGE_URL'] = f'redis://{self.config["REDIS_ADDRESS"]}/3'
143         self.config['SESSION_COOKIE_SAMESITE'] = 'Strict'
144         self.config['SESSION_COOKIE_HTTPONLY'] = True
145         if self.config['SESSION_COOKIE_SECURE'] is None:
146             self.config['SESSION_COOKIE_SECURE'] = self.config['TLS_FLAVOR'] != 'notls'
147         self.config['SESSION_PERMANENT'] = True
148         self.config['SESSION_TIMEOUT'] = int(self.config['SESSION_TIMEOUT'])
149         self.config['SESSION_KEY_BITS'] = int(self.config['SESSION_KEY_BITS'])
150         self.config['PERMANENT_SESSION_LIFETIME'] = int(self.config['PERMANENT_SESSION_LIFETIME'])
151         self.config['AUTH_RATELIMIT_IP_V4_MASK'] = int(self.config['AUTH_RATELIMIT_IP_V4_MASK'])
152         self.config['AUTH_RATELIMIT_IP_V6_MASK'] = int(self.config['AUTH_RATELIMIT_IP_V6_MASK'])
153         self.config['AUTH_RATELIMIT_EXEMPTION'] = set(ipaddress.ip_network(cidr, False) for cidr in (cidr.strip() for cidr in self.config['AUTH_RATELIMIT_EXEMPTION'].split(',')) if cidr)
154         self.config['MESSAGE_RATELIMIT_EXEMPTION'] = set([s for s in self.config['MESSAGE_RATELIMIT_EXEMPTION'].lower().replace(' ', '').split(',') if s])
155         hostnames = [host.strip() for host in self.config['HOSTNAMES'].split(',')]
156         self.config['HOSTNAMES'] = ','.join(hostnames)
157         self.config['HOSTNAME'] = hostnames[0]
158         self.config['DEFAULT_SPAM_THRESHOLD'] = int(self.config['DEFAULT_SPAM_THRESHOLD'])
159         self.config['PROXY_AUTH_WHITELIST'] = set(ipaddress.ip_network(cidr, False) for cidr in (cidr.strip() for cidr in self.config['PROXY_AUTH_WHITELIST'].split(',')) if cidr)
160 
161         # update the app config
162         app.config.update(self.config)
163
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/core/admin/mailu/configuration.py b/core/admin/mailu/configuration.py
--- a/core/admin/mailu/configuration.py
+++ b/core/admin/mailu/configuration.py
@@ -18,6 +18,7 @@
     'TEMPLATES_AUTO_RELOAD': True,
     'MEMORY_SESSIONS': False,
     'FETCHMAIL_ENABLED': True,
+    'MAILU_VERSION': 'unknown',
     # Database settings
     'DB_FLAVOR': None,
     'DB_USER': 'mailu',
@@ -157,6 +158,10 @@
         self.config['HOSTNAME'] = hostnames[0]
         self.config['DEFAULT_SPAM_THRESHOLD'] = int(self.config['DEFAULT_SPAM_THRESHOLD'])
         self.config['PROXY_AUTH_WHITELIST'] = set(ipaddress.ip_network(cidr, False) for cidr in (cidr.strip() for cidr in self.config['PROXY_AUTH_WHITELIST'].split(',')) if cidr)
+        try:
+            self.config['MAILU_VERSION'] = open('/version', 'r').read()
+        except FileNotFoundError:
+            pass
 
         # update the app config
         app.config.update(self.config)

{"golden_diff": "diff --git a/core/admin/mailu/configuration.py b/core/admin/mailu/configuration.py\n--- a/core/admin/mailu/configuration.py\n+++ b/core/admin/mailu/configuration.py\n@@ -18,6 +18,7 @@\n     'TEMPLATES_AUTO_RELOAD': True,\n     'MEMORY_SESSIONS': False,\n     'FETCHMAIL_ENABLED': True,\n+    'MAILU_VERSION': 'unknown',\n     # Database settings\n     'DB_FLAVOR': None,\n     'DB_USER': 'mailu',\n@@ -157,6 +158,10 @@\n         self.config['HOSTNAME'] = hostnames[0]\n         self.config['DEFAULT_SPAM_THRESHOLD'] = int(self.config['DEFAULT_SPAM_THRESHOLD'])\n         self.config['PROXY_AUTH_WHITELIST'] = set(ipaddress.ip_network(cidr, False) for cidr in (cidr.strip() for cidr in self.config['PROXY_AUTH_WHITELIST'].split(',')) if cidr)\n+        try:\n+            self.config['MAILU_VERSION'] = open('/version', 'r').read()\n+        except FileNotFoundError:\n+            pass\n \n         # update the app config\n         app.config.update(self.config)\n", "issue": "Small feature - add mailu version in the admin UI \nAdd mailu version in the admin UI \r\nI think it would nice to be able to see which version of mailu we are running, unless there is other simple way?\r\n\r\nThanks\n", "before_files": [{"content": "import os\n\nfrom datetime import timedelta\nimport ipaddress\n\nDEFAULT_CONFIG = {\n    # Specific to the admin UI\n    'DOCKER_SOCKET': 'unix:///var/run/docker.sock',\n    'BABEL_DEFAULT_LOCALE': 'en',\n    'BABEL_DEFAULT_TIMEZONE': 'UTC',\n    'BOOTSTRAP_SERVE_LOCAL': True,\n    'RATELIMIT_STORAGE_URL': '',\n    'DEBUG': False,\n    'DEBUG_PROFILER': False,\n    'DEBUG_TB_INTERCEPT_REDIRECTS': False,\n    'DEBUG_ASSETS': '',\n    'DOMAIN_REGISTRATION': False,\n    'TEMPLATES_AUTO_RELOAD': True,\n    'MEMORY_SESSIONS': False,\n    'FETCHMAIL_ENABLED': True,\n    # Database settings\n    'DB_FLAVOR': None,\n    'DB_USER': 'mailu',\n    'DB_PW': None,\n    'DB_HOST': 'database',\n    'DB_NAME': 'mailu',\n    'SQLITE_DATABASE_FILE': 'data/main.db',\n    'SQLALCHEMY_DATABASE_URI': 'sqlite:////data/main.db',\n    'SQLALCHEMY_TRACK_MODIFICATIONS': False,\n    # Statistics management\n    'INSTANCE_ID_PATH': '/data/instance',\n    'STATS_ENDPOINT': '19.{}.stats.mailu.io',\n    # Common configuration variables\n    'SECRET_KEY': 'changeMe',\n    'DOMAIN': 'mailu.io',\n    'HOSTNAMES': 'mail.mailu.io,alternative.mailu.io,yetanother.mailu.io',\n    'POSTMASTER': 'postmaster',\n    'WILDCARD_SENDERS': '',\n    'TLS_FLAVOR': 'cert',\n    'INBOUND_TLS_ENFORCE': False,\n    'DEFER_ON_TLS_ERROR': True,\n    'AUTH_RATELIMIT_IP': '60/hour',\n    'AUTH_RATELIMIT_IP_V4_MASK': 24,\n    'AUTH_RATELIMIT_IP_V6_MASK': 56,\n    'AUTH_RATELIMIT_USER': '100/day',\n    'AUTH_RATELIMIT_EXEMPTION': '',\n    'AUTH_RATELIMIT_EXEMPTION_LENGTH': 86400,\n    'DISABLE_STATISTICS': False,\n    # Mail settings\n    'DMARC_RUA': None,\n    'DMARC_RUF': None,\n    'WELCOME': False,\n    'WELCOME_SUBJECT': 'Dummy welcome topic',\n    'WELCOME_BODY': 'Dummy welcome body',\n    'DKIM_SELECTOR': 'dkim',\n    'DKIM_PATH': '/dkim/{domain}.{selector}.key',\n    'DEFAULT_QUOTA': 1000000000,\n    'MESSAGE_RATELIMIT': '200/day',\n    'MESSAGE_RATELIMIT_EXEMPTION': '',\n    'RECIPIENT_DELIMITER': '',\n    # Web settings\n    'SITENAME': 'Mailu',\n    'WEBSITE': 'https://mailu.io',\n    'ADMIN': 'none',\n    'WEB_ADMIN': '/admin',\n    'WEB_WEBMAIL': '/webmail',\n    'WEBMAIL': 'none',\n    'RECAPTCHA_PUBLIC_KEY': '',\n    'RECAPTCHA_PRIVATE_KEY': '',\n    'LOGO_URL': None,\n    'LOGO_BACKGROUND': None,\n    # Advanced settings\n    'API': False,\n    'WEB_API': '/api',\n    'API_TOKEN': None,\n    'LOG_LEVEL': 'WARNING',\n    'SESSION_KEY_BITS': 128,\n    'SESSION_TIMEOUT': 3600,\n    'PERMANENT_SESSION_LIFETIME': 30*24*3600,\n    'SESSION_COOKIE_SECURE': None,\n    'CREDENTIAL_ROUNDS': 12,\n    'TLS_PERMISSIVE': True,\n    'TZ': 'Etc/UTC',\n    'DEFAULT_SPAM_THRESHOLD': 80,\n    'PROXY_AUTH_WHITELIST': '',\n    'PROXY_AUTH_HEADER': 'X-Auth-Email',\n    'PROXY_AUTH_CREATE': False,\n    'SUBNET': '192.168.203.0/24',\n    'SUBNET6': None,\n}\n\nclass ConfigManager:\n    \"\"\" Naive configuration manager that uses environment only\n    \"\"\"\n\n    DB_TEMPLATES = {\n        'sqlite': 'sqlite:////{SQLITE_DATABASE_FILE}',\n        'postgresql': 'postgresql://{DB_USER}:{DB_PW}@{DB_HOST}/{DB_NAME}',\n        'mysql': 'mysql+mysqlconnector://{DB_USER}:{DB_PW}@{DB_HOST}/{DB_NAME}',\n    }\n\n    def __init__(self):\n        self.config = dict()\n\n    def __get_env(self, key, value):\n        key_file = key + \"_FILE\"\n        if key_file in os.environ:\n            with open(os.environ.get(key_file)) as file:\n                value_from_file = file.read()\n            return value_from_file.strip()\n        else:\n            return os.environ.get(key, value)\n\n    def __coerce_value(self, value):\n        if isinstance(value, str) and value.lower() in ('true','yes'):\n            return True\n        elif isinstance(value, str) and value.lower() in ('false', 'no'):\n            return False\n        return value\n\n    def init_app(self, app):\n        # get current app config\n        self.config.update(app.config)\n        # get environment variables\n        for key in os.environ:\n            if key.endswith('_ADDRESS'):\n                self.config[key] = os.environ[key]\n\n        self.config.update({\n            key: self.__coerce_value(self.__get_env(key, value))\n            for key, value in DEFAULT_CONFIG.items()\n        })\n\n        # automatically set the sqlalchemy string\n        if self.config['DB_FLAVOR']:\n            template = self.DB_TEMPLATES[self.config['DB_FLAVOR']]\n            self.config['SQLALCHEMY_DATABASE_URI'] = template.format(**self.config)\n\n        if not self.config.get('RATELIMIT_STORAGE_URL'):\n            self.config['RATELIMIT_STORAGE_URL'] = f'redis://{self.config[\"REDIS_ADDRESS\"]}/2'\n\n        self.config['SESSION_STORAGE_URL'] = f'redis://{self.config[\"REDIS_ADDRESS\"]}/3'\n        self.config['SESSION_COOKIE_SAMESITE'] = 'Strict'\n        self.config['SESSION_COOKIE_HTTPONLY'] = True\n        if self.config['SESSION_COOKIE_SECURE'] is None:\n            self.config['SESSION_COOKIE_SECURE'] = self.config['TLS_FLAVOR'] != 'notls'\n        self.config['SESSION_PERMANENT'] = True\n        self.config['SESSION_TIMEOUT'] = int(self.config['SESSION_TIMEOUT'])\n        self.config['SESSION_KEY_BITS'] = int(self.config['SESSION_KEY_BITS'])\n        self.config['PERMANENT_SESSION_LIFETIME'] = int(self.config['PERMANENT_SESSION_LIFETIME'])\n        self.config['AUTH_RATELIMIT_IP_V4_MASK'] = int(self.config['AUTH_RATELIMIT_IP_V4_MASK'])\n        self.config['AUTH_RATELIMIT_IP_V6_MASK'] = int(self.config['AUTH_RATELIMIT_IP_V6_MASK'])\n        self.config['AUTH_RATELIMIT_EXEMPTION'] = set(ipaddress.ip_network(cidr, False) for cidr in (cidr.strip() for cidr in self.config['AUTH_RATELIMIT_EXEMPTION'].split(',')) if cidr)\n        self.config['MESSAGE_RATELIMIT_EXEMPTION'] = set([s for s in self.config['MESSAGE_RATELIMIT_EXEMPTION'].lower().replace(' ', '').split(',') if s])\n        hostnames = [host.strip() for host in self.config['HOSTNAMES'].split(',')]\n        self.config['HOSTNAMES'] = ','.join(hostnames)\n        self.config['HOSTNAME'] = hostnames[0]\n        self.config['DEFAULT_SPAM_THRESHOLD'] = int(self.config['DEFAULT_SPAM_THRESHOLD'])\n        self.config['PROXY_AUTH_WHITELIST'] = set(ipaddress.ip_network(cidr, False) for cidr in (cidr.strip() for cidr in self.config['PROXY_AUTH_WHITELIST'].split(',')) if cidr)\n\n        # update the app config\n        app.config.update(self.config)\n", "path": "core/admin/mailu/configuration.py"}], "after_files": [{"content": "import os\n\nfrom datetime import timedelta\nimport ipaddress\n\nDEFAULT_CONFIG = {\n    # Specific to the admin UI\n    'DOCKER_SOCKET': 'unix:///var/run/docker.sock',\n    'BABEL_DEFAULT_LOCALE': 'en',\n    'BABEL_DEFAULT_TIMEZONE': 'UTC',\n    'BOOTSTRAP_SERVE_LOCAL': True,\n    'RATELIMIT_STORAGE_URL': '',\n    'DEBUG': False,\n    'DEBUG_PROFILER': False,\n    'DEBUG_TB_INTERCEPT_REDIRECTS': False,\n    'DEBUG_ASSETS': '',\n    'DOMAIN_REGISTRATION': False,\n    'TEMPLATES_AUTO_RELOAD': True,\n    'MEMORY_SESSIONS': False,\n    'FETCHMAIL_ENABLED': True,\n    'MAILU_VERSION': 'unknown',\n    # Database settings\n    'DB_FLAVOR': None,\n    'DB_USER': 'mailu',\n    'DB_PW': None,\n    'DB_HOST': 'database',\n    'DB_NAME': 'mailu',\n    'SQLITE_DATABASE_FILE': 'data/main.db',\n    'SQLALCHEMY_DATABASE_URI': 'sqlite:////data/main.db',\n    'SQLALCHEMY_TRACK_MODIFICATIONS': False,\n    # Statistics management\n    'INSTANCE_ID_PATH': '/data/instance',\n    'STATS_ENDPOINT': '19.{}.stats.mailu.io',\n    # Common configuration variables\n    'SECRET_KEY': 'changeMe',\n    'DOMAIN': 'mailu.io',\n    'HOSTNAMES': 'mail.mailu.io,alternative.mailu.io,yetanother.mailu.io',\n    'POSTMASTER': 'postmaster',\n    'WILDCARD_SENDERS': '',\n    'TLS_FLAVOR': 'cert',\n    'INBOUND_TLS_ENFORCE': False,\n    'DEFER_ON_TLS_ERROR': True,\n    'AUTH_RATELIMIT_IP': '60/hour',\n    'AUTH_RATELIMIT_IP_V4_MASK': 24,\n    'AUTH_RATELIMIT_IP_V6_MASK': 56,\n    'AUTH_RATELIMIT_USER': '100/day',\n    'AUTH_RATELIMIT_EXEMPTION': '',\n    'AUTH_RATELIMIT_EXEMPTION_LENGTH': 86400,\n    'DISABLE_STATISTICS': False,\n    # Mail settings\n    'DMARC_RUA': None,\n    'DMARC_RUF': None,\n    'WELCOME': False,\n    'WELCOME_SUBJECT': 'Dummy welcome topic',\n    'WELCOME_BODY': 'Dummy welcome body',\n    'DKIM_SELECTOR': 'dkim',\n    'DKIM_PATH': '/dkim/{domain}.{selector}.key',\n    'DEFAULT_QUOTA': 1000000000,\n    'MESSAGE_RATELIMIT': '200/day',\n    'MESSAGE_RATELIMIT_EXEMPTION': '',\n    'RECIPIENT_DELIMITER': '',\n    # Web settings\n    'SITENAME': 'Mailu',\n    'WEBSITE': 'https://mailu.io',\n    'ADMIN': 'none',\n    'WEB_ADMIN': '/admin',\n    'WEB_WEBMAIL': '/webmail',\n    'WEBMAIL': 'none',\n    'RECAPTCHA_PUBLIC_KEY': '',\n    'RECAPTCHA_PRIVATE_KEY': '',\n    'LOGO_URL': None,\n    'LOGO_BACKGROUND': None,\n    # Advanced settings\n    'API': False,\n    'WEB_API': '/api',\n    'API_TOKEN': None,\n    'LOG_LEVEL': 'WARNING',\n    'SESSION_KEY_BITS': 128,\n    'SESSION_TIMEOUT': 3600,\n    'PERMANENT_SESSION_LIFETIME': 30*24*3600,\n    'SESSION_COOKIE_SECURE': None,\n    'CREDENTIAL_ROUNDS': 12,\n    'TLS_PERMISSIVE': True,\n    'TZ': 'Etc/UTC',\n    'DEFAULT_SPAM_THRESHOLD': 80,\n    'PROXY_AUTH_WHITELIST': '',\n    'PROXY_AUTH_HEADER': 'X-Auth-Email',\n    'PROXY_AUTH_CREATE': False,\n    'SUBNET': '192.168.203.0/24',\n    'SUBNET6': None,\n}\n\nclass ConfigManager:\n    \"\"\" Naive configuration manager that uses environment only\n    \"\"\"\n\n    DB_TEMPLATES = {\n        'sqlite': 'sqlite:////{SQLITE_DATABASE_FILE}',\n        'postgresql': 'postgresql://{DB_USER}:{DB_PW}@{DB_HOST}/{DB_NAME}',\n        'mysql': 'mysql+mysqlconnector://{DB_USER}:{DB_PW}@{DB_HOST}/{DB_NAME}',\n    }\n\n    def __init__(self):\n        self.config = dict()\n\n    def __get_env(self, key, value):\n        key_file = key + \"_FILE\"\n        if key_file in os.environ:\n            with open(os.environ.get(key_file)) as file:\n                value_from_file = file.read()\n            return value_from_file.strip()\n        else:\n            return os.environ.get(key, value)\n\n    def __coerce_value(self, value):\n        if isinstance(value, str) and value.lower() in ('true','yes'):\n            return True\n        elif isinstance(value, str) and value.lower() in ('false', 'no'):\n            return False\n        return value\n\n    def init_app(self, app):\n        # get current app config\n        self.config.update(app.config)\n        # get environment variables\n        for key in os.environ:\n            if key.endswith('_ADDRESS'):\n                self.config[key] = os.environ[key]\n\n        self.config.update({\n            key: self.__coerce_value(self.__get_env(key, value))\n            for key, value in DEFAULT_CONFIG.items()\n        })\n\n        # automatically set the sqlalchemy string\n        if self.config['DB_FLAVOR']:\n            template = self.DB_TEMPLATES[self.config['DB_FLAVOR']]\n            self.config['SQLALCHEMY_DATABASE_URI'] = template.format(**self.config)\n\n        if not self.config.get('RATELIMIT_STORAGE_URL'):\n            self.config['RATELIMIT_STORAGE_URL'] = f'redis://{self.config[\"REDIS_ADDRESS\"]}/2'\n\n        self.config['SESSION_STORAGE_URL'] = f'redis://{self.config[\"REDIS_ADDRESS\"]}/3'\n        self.config['SESSION_COOKIE_SAMESITE'] = 'Strict'\n        self.config['SESSION_COOKIE_HTTPONLY'] = True\n        if self.config['SESSION_COOKIE_SECURE'] is None:\n            self.config['SESSION_COOKIE_SECURE'] = self.config['TLS_FLAVOR'] != 'notls'\n        self.config['SESSION_PERMANENT'] = True\n        self.config['SESSION_TIMEOUT'] = int(self.config['SESSION_TIMEOUT'])\n        self.config['SESSION_KEY_BITS'] = int(self.config['SESSION_KEY_BITS'])\n        self.config['PERMANENT_SESSION_LIFETIME'] = int(self.config['PERMANENT_SESSION_LIFETIME'])\n        self.config['AUTH_RATELIMIT_IP_V4_MASK'] = int(self.config['AUTH_RATELIMIT_IP_V4_MASK'])\n        self.config['AUTH_RATELIMIT_IP_V6_MASK'] = int(self.config['AUTH_RATELIMIT_IP_V6_MASK'])\n        self.config['AUTH_RATELIMIT_EXEMPTION'] = set(ipaddress.ip_network(cidr, False) for cidr in (cidr.strip() for cidr in self.config['AUTH_RATELIMIT_EXEMPTION'].split(',')) if cidr)\n        self.config['MESSAGE_RATELIMIT_EXEMPTION'] = set([s for s in self.config['MESSAGE_RATELIMIT_EXEMPTION'].lower().replace(' ', '').split(',') if s])\n        hostnames = [host.strip() for host in self.config['HOSTNAMES'].split(',')]\n        self.config['HOSTNAMES'] = ','.join(hostnames)\n        self.config['HOSTNAME'] = hostnames[0]\n        self.config['DEFAULT_SPAM_THRESHOLD'] = int(self.config['DEFAULT_SPAM_THRESHOLD'])\n        self.config['PROXY_AUTH_WHITELIST'] = set(ipaddress.ip_network(cidr, False) for cidr in (cidr.strip() for cidr in self.config['PROXY_AUTH_WHITELIST'].split(',')) if cidr)\n        try:\n            self.config['MAILU_VERSION'] = open('/version', 'r').read()\n        except FileNotFoundError:\n            pass\n\n        # update the app config\n        app.config.update(self.config)\n", "path": "core/admin/mailu/configuration.py"}]}