We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Missing wildcard option in alias flask command
Hi guys,

First of all, thank you for making this awesome Mailu project :+1: :100: 

I'm using command line to mass import some alias from an old server. There doesn't seem to have an option to toggle wildcard support:

```
Usage: flask mailu alias [OPTIONS] LOCALPART DOMAIN_NAME DESTINATION

  Create an alias

Options:
  --help  Show this message and exit.
```

Would be great if it can be done through CLI. Thanks again!

--- 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/manage.py`
Content:
```
1 from mailu import models
2 
3 from flask import current_app as app
4 from flask import cli as flask_cli
5 
6 import flask
7 import os
8 import socket
9 import uuid
10 import click
11 
12 
13 db = models.db
14 
15 
16 @click.group()
17 def mailu(cls=flask_cli.FlaskGroup):
18     """ Mailu command line
19     """
20 
21 
22 @mailu.command()
23 @flask_cli.with_appcontext
24 def advertise():
25     """ Advertise this server against statistic services.
26     """
27     if os.path.isfile(app.config["INSTANCE_ID_PATH"]):
28         with open(app.config["INSTANCE_ID_PATH"], "r") as handle:
29             instance_id = handle.read()
30     else:
31         instance_id = str(uuid.uuid4())
32         with open(app.config["INSTANCE_ID_PATH"], "w") as handle:
33             handle.write(instance_id)
34     if not app.config["DISABLE_STATISTICS"]:
35         try:
36             socket.gethostbyname(app.config["STATS_ENDPOINT"].format(instance_id))
37         except:
38             pass
39 
40 
41 @mailu.command()
42 @click.argument('localpart')
43 @click.argument('domain_name')
44 @click.argument('password')
45 @flask_cli.with_appcontext
46 def admin(localpart, domain_name, password):
47     """ Create an admin user
48     """
49     domain = models.Domain.query.get(domain_name)
50     if not domain:
51         domain = models.Domain(name=domain_name)
52         db.session.add(domain)
53     user = models.User(
54         localpart=localpart,
55         domain=domain,
56         global_admin=True
57     )
58     user.set_password(password)
59     db.session.add(user)
60     db.session.commit()
61 
62 
63 @mailu.command()
64 @click.argument('localpart')
65 @click.argument('domain_name')
66 @click.argument('password')
67 @click.argument('hash_scheme')
68 @flask_cli.with_appcontext
69 def user(localpart, domain_name, password, hash_scheme=None):
70     """ Create a user
71     """
72     if hash_scheme is None:
73         hash_scheme = app.config['PASSWORD_SCHEME']
74     domain = models.Domain.query.get(domain_name)
75     if not domain:
76         domain = models.Domain(name=domain_name)
77         db.session.add(domain)
78     user = models.User(
79         localpart=localpart,
80         domain=domain,
81         global_admin=False
82     )
83     user.set_password(password, hash_scheme=hash_scheme)
84     db.session.add(user)
85     db.session.commit()
86 
87 
88 @mailu.command()
89 @click.option('-n', '--domain_name')
90 @click.option('-u', '--max_users')
91 @click.option('-a', '--max_aliases')
92 @click.option('-q', '--max_quota_bytes')
93 @flask_cli.with_appcontext
94 def domain(domain_name, max_users=-1, max_aliases=-1, max_quota_bytes=0):
95     domain = models.Domain.query.get(domain_name)
96     if not domain:
97         domain = models.Domain(name=domain_name)
98         db.session.add(domain)
99         db.session.commit()
100 
101 
102 @mailu.command()
103 @click.argument('localpart')
104 @click.argument('domain_name')
105 @click.argument('password_hash')
106 @click.argument('hash_scheme')
107 @flask_cli.with_appcontext
108 def user_import(localpart, domain_name, password_hash, hash_scheme = None):
109     """ Import a user along with password hash.
110     """
111     if hash_scheme is None:
112         hash_scheme = app.config['PASSWORD_SCHEME']
113     domain = models.Domain.query.get(domain_name)
114     if not domain:
115         domain = models.Domain(name=domain_name)
116         db.session.add(domain)
117     user = models.User(
118         localpart=localpart,
119         domain=domain,
120         global_admin=False
121     )
122     user.set_password(password_hash, hash_scheme=hash_scheme, raw=True)
123     db.session.add(user)
124     db.session.commit()
125 
126 
127 @mailu.command()
128 @click.option('-v', '--verbose')
129 @click.option('-d', '--delete_objects')
130 @flask_cli.with_appcontext
131 def config_update(verbose=False, delete_objects=False):
132     """sync configuration with data from YAML-formatted stdin"""
133     import yaml
134     import sys
135     new_config = yaml.load(sys.stdin)
136     # print new_config
137     domains = new_config.get('domains', [])
138     tracked_domains = set()
139     for domain_config in domains:
140         if verbose:
141             print(str(domain_config))
142         domain_name = domain_config['name']
143         max_users = domain_config.get('max_users', -1)
144         max_aliases = domain_config.get('max_aliases', -1)
145         max_quota_bytes = domain_config.get('max_quota_bytes', 0)
146         tracked_domains.add(domain_name)
147         domain = models.Domain.query.get(domain_name)
148         if not domain:
149             domain = models.Domain(name=domain_name,
150                                    max_users=max_users,
151                                    max_aliases=max_aliases,
152                                    max_quota_bytes=max_quota_bytes)
153             db.session.add(domain)
154             print("Added " + str(domain_config))
155         else:
156             domain.max_users = max_users
157             domain.max_aliases = max_aliases
158             domain.max_quota_bytes = max_quota_bytes
159             db.session.add(domain)
160             print("Updated " + str(domain_config))
161 
162     users = new_config.get('users', [])
163     tracked_users = set()
164     user_optional_params = ('comment', 'quota_bytes', 'global_admin',
165                             'enable_imap', 'enable_pop', 'forward_enabled',
166                             'forward_destination', 'reply_enabled',
167                             'reply_subject', 'reply_body', 'displayed_name',
168                             'spam_enabled', 'email', 'spam_threshold')
169     for user_config in users:
170         if verbose:
171             print(str(user_config))
172         localpart = user_config['localpart']
173         domain_name = user_config['domain']
174         password_hash = user_config.get('password_hash', None)
175         hash_scheme = user_config.get('hash_scheme', None)
176         domain = models.Domain.query.get(domain_name)
177         email = '{0}@{1}'.format(localpart, domain_name)
178         optional_params = {}
179         for k in user_optional_params:
180             if k in user_config:
181                 optional_params[k] = user_config[k]
182         if not domain:
183             domain = models.Domain(name=domain_name)
184             db.session.add(domain)
185         user = models.User.query.get(email)
186         tracked_users.add(email)
187         tracked_domains.add(domain_name)
188         if not user:
189             user = models.User(
190                 localpart=localpart,
191                 domain=domain,
192                 **optional_params
193             )
194         else:
195             for k in optional_params:
196                 setattr(user, k, optional_params[k])
197         user.set_password(password_hash, hash_scheme=hash_scheme, raw=True)
198         db.session.add(user)
199 
200     aliases = new_config.get('aliases', [])
201     tracked_aliases = set()
202     for alias_config in aliases:
203         if verbose:
204             print(str(alias_config))
205         localpart = alias_config['localpart']
206         domain_name = alias_config['domain']
207         if type(alias_config['destination']) is str:
208             destination = alias_config['destination'].split(',')
209         else:
210             destination = alias_config['destination']
211         wildcard = alias_config.get('wildcard', False)
212         domain = models.Domain.query.get(domain_name)
213         email = '{0}@{1}'.format(localpart, domain_name)
214         if not domain:
215             domain = models.Domain(name=domain_name)
216             db.session.add(domain)
217         alias = models.Alias.query.get(email)
218         tracked_aliases.add(email)
219         tracked_domains.add(domain_name)
220         if not alias:
221             alias = models.Alias(
222                 localpart=localpart,
223                 domain=domain,
224                 wildcard=wildcard,
225                 destination=destination,
226                 email=email
227             )
228         else:
229             alias.destination = destination
230             alias.wildcard = wildcard
231         db.session.add(alias)
232 
233     db.session.commit()
234 
235     managers = new_config.get('managers', [])
236     # tracked_managers=set()
237     for manager_config in managers:
238         if verbose:
239             print(str(manager_config))
240         domain_name = manager_config['domain']
241         user_name = manager_config['user']
242         domain = models.Domain.query.get(domain_name)
243         manageruser = models.User.query.get(user_name + '@' + domain_name)
244         if manageruser not in domain.managers:
245             domain.managers.append(manageruser)
246         db.session.add(domain)
247 
248     db.session.commit()
249 
250     if delete_objects:
251         for user in db.session.query(models.User).all():
252             if not (user.email in tracked_users):
253                 if verbose:
254                     print("Deleting user: " + str(user.email))
255                 db.session.delete(user)
256         for alias in db.session.query(models.Alias).all():
257             if not (alias.email in tracked_aliases):
258                 if verbose:
259                     print("Deleting alias: " + str(alias.email))
260                 db.session.delete(alias)
261         for domain in db.session.query(models.Domain).all():
262             if not (domain.name in tracked_domains):
263                 if verbose:
264                     print("Deleting domain: " + str(domain.name))
265                 db.session.delete(domain)
266     db.session.commit()
267 
268 
269 @mailu.command()
270 @click.argument('email')
271 @flask_cli.with_appcontext
272 def user_delete(email):
273     """delete user"""
274     user = models.User.query.get(email)
275     if user:
276         db.session.delete(user)
277     db.session.commit()
278 
279 
280 @mailu.command()
281 @click.argument('email')
282 @flask_cli.with_appcontext
283 def alias_delete(email):
284     """delete alias"""
285     alias = models.Alias.query.get(email)
286     if alias:
287         db.session.delete(alias)
288     db.session.commit()
289 
290 
291 @mailu.command()
292 @click.argument('localpart')
293 @click.argument('domain_name')
294 @click.argument('destination')
295 @flask_cli.with_appcontext
296 def alias(localpart, domain_name, destination):
297     """ Create an alias
298     """
299     domain = models.Domain.query.get(domain_name)
300     if not domain:
301         domain = models.Domain(name=domain_name)
302         db.session.add(domain)
303     alias = models.Alias(
304         localpart=localpart,
305         domain=domain,
306         destination=destination.split(','),
307         email="%s@%s" % (localpart, domain_name)
308     )
309     db.session.add(alias)
310     db.session.commit()
311 
312 
313 @mailu.command()
314 @click.argument('domain_name')
315 @click.argument('max_users')
316 @click.argument('max_aliases')
317 @click.argument('max_quota_bytes')
318 @flask_cli.with_appcontext
319 def setlimits(domain_name, max_users, max_aliases, max_quota_bytes):
320     """ Set domain limits
321     """
322     domain = models.Domain.query.get(domain_name)
323     domain.max_users = max_users
324     domain.max_aliases = max_aliases
325     domain.max_quota_bytes = max_quota_bytes
326     db.session.add(domain)
327     db.session.commit()
328 
329 
330 @mailu.command()
331 @click.argument('domain_name')
332 @click.argument('user_name')
333 @flask_cli.with_appcontext
334 def setmanager(domain_name, user_name='manager'):
335     """ Make a user manager of a domain
336     """
337     domain = models.Domain.query.get(domain_name)
338     manageruser = models.User.query.get(user_name + '@' + domain_name)
339     domain.managers.append(manageruser)
340     db.session.add(domain)
341     db.session.commit()
342 
343 
344 if __name__ == '__main__':
345     cli()
346
```
--- 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/manage.py b/core/admin/mailu/manage.py
--- a/core/admin/mailu/manage.py
+++ b/core/admin/mailu/manage.py
@@ -292,8 +292,9 @@
 @click.argument('localpart')
 @click.argument('domain_name')
 @click.argument('destination')
+@click.option('-w', '--wildcard', is_flag=True)
 @flask_cli.with_appcontext
-def alias(localpart, domain_name, destination):
+def alias(localpart, domain_name, destination, wildcard=False):
     """ Create an alias
     """
     domain = models.Domain.query.get(domain_name)
@@ -303,6 +304,7 @@
     alias = models.Alias(
         localpart=localpart,
         domain=domain,
+        wildcard=wildcard,
         destination=destination.split(','),
         email="%s@%s" % (localpart, domain_name)
     )

{"golden_diff": "diff --git a/core/admin/mailu/manage.py b/core/admin/mailu/manage.py\n--- a/core/admin/mailu/manage.py\n+++ b/core/admin/mailu/manage.py\n@@ -292,8 +292,9 @@\n @click.argument('localpart')\n @click.argument('domain_name')\n @click.argument('destination')\n+@click.option('-w', '--wildcard', is_flag=True)\n @flask_cli.with_appcontext\n-def alias(localpart, domain_name, destination):\n+def alias(localpart, domain_name, destination, wildcard=False):\n     \"\"\" Create an alias\n     \"\"\"\n     domain = models.Domain.query.get(domain_name)\n@@ -303,6 +304,7 @@\n     alias = models.Alias(\n         localpart=localpart,\n         domain=domain,\n+        wildcard=wildcard,\n         destination=destination.split(','),\n         email=\"%s@%s\" % (localpart, domain_name)\n     )\n", "issue": "Missing wildcard option in alias flask command\nHi guys,\r\n\r\nFirst of all, thank you for making this awesome Mailu project :+1: :100: \r\n\r\nI'm using command line to mass import some alias from an old server. There doesn't seem to have an option to toggle wildcard support:\r\n\r\n```\r\nUsage: flask mailu alias [OPTIONS] LOCALPART DOMAIN_NAME DESTINATION\r\n\r\n  Create an alias\r\n\r\nOptions:\r\n  --help  Show this message and exit.\r\n```\r\n\r\nWould be great if it can be done through CLI. Thanks again!\n", "before_files": [{"content": "from mailu import models\n\nfrom flask import current_app as app\nfrom flask import cli as flask_cli\n\nimport flask\nimport os\nimport socket\nimport uuid\nimport click\n\n\ndb = models.db\n\n\n@click.group()\ndef mailu(cls=flask_cli.FlaskGroup):\n    \"\"\" Mailu command line\n    \"\"\"\n\n\n@mailu.command()\n@flask_cli.with_appcontext\ndef advertise():\n    \"\"\" Advertise this server against statistic services.\n    \"\"\"\n    if os.path.isfile(app.config[\"INSTANCE_ID_PATH\"]):\n        with open(app.config[\"INSTANCE_ID_PATH\"], \"r\") as handle:\n            instance_id = handle.read()\n    else:\n        instance_id = str(uuid.uuid4())\n        with open(app.config[\"INSTANCE_ID_PATH\"], \"w\") as handle:\n            handle.write(instance_id)\n    if not app.config[\"DISABLE_STATISTICS\"]:\n        try:\n            socket.gethostbyname(app.config[\"STATS_ENDPOINT\"].format(instance_id))\n        except:\n            pass\n\n\n@mailu.command()\n@click.argument('localpart')\n@click.argument('domain_name')\n@click.argument('password')\n@flask_cli.with_appcontext\ndef admin(localpart, domain_name, password):\n    \"\"\" Create an admin user\n    \"\"\"\n    domain = models.Domain.query.get(domain_name)\n    if not domain:\n        domain = models.Domain(name=domain_name)\n        db.session.add(domain)\n    user = models.User(\n        localpart=localpart,\n        domain=domain,\n        global_admin=True\n    )\n    user.set_password(password)\n    db.session.add(user)\n    db.session.commit()\n\n\n@mailu.command()\n@click.argument('localpart')\n@click.argument('domain_name')\n@click.argument('password')\n@click.argument('hash_scheme')\n@flask_cli.with_appcontext\ndef user(localpart, domain_name, password, hash_scheme=None):\n    \"\"\" Create a user\n    \"\"\"\n    if hash_scheme is None:\n        hash_scheme = app.config['PASSWORD_SCHEME']\n    domain = models.Domain.query.get(domain_name)\n    if not domain:\n        domain = models.Domain(name=domain_name)\n        db.session.add(domain)\n    user = models.User(\n        localpart=localpart,\n        domain=domain,\n        global_admin=False\n    )\n    user.set_password(password, hash_scheme=hash_scheme)\n    db.session.add(user)\n    db.session.commit()\n\n\n@mailu.command()\n@click.option('-n', '--domain_name')\n@click.option('-u', '--max_users')\n@click.option('-a', '--max_aliases')\n@click.option('-q', '--max_quota_bytes')\n@flask_cli.with_appcontext\ndef domain(domain_name, max_users=-1, max_aliases=-1, max_quota_bytes=0):\n    domain = models.Domain.query.get(domain_name)\n    if not domain:\n        domain = models.Domain(name=domain_name)\n        db.session.add(domain)\n        db.session.commit()\n\n\n@mailu.command()\n@click.argument('localpart')\n@click.argument('domain_name')\n@click.argument('password_hash')\n@click.argument('hash_scheme')\n@flask_cli.with_appcontext\ndef user_import(localpart, domain_name, password_hash, hash_scheme = None):\n    \"\"\" Import a user along with password hash.\n    \"\"\"\n    if hash_scheme is None:\n        hash_scheme = app.config['PASSWORD_SCHEME']\n    domain = models.Domain.query.get(domain_name)\n    if not domain:\n        domain = models.Domain(name=domain_name)\n        db.session.add(domain)\n    user = models.User(\n        localpart=localpart,\n        domain=domain,\n        global_admin=False\n    )\n    user.set_password(password_hash, hash_scheme=hash_scheme, raw=True)\n    db.session.add(user)\n    db.session.commit()\n\n\n@mailu.command()\n@click.option('-v', '--verbose')\n@click.option('-d', '--delete_objects')\n@flask_cli.with_appcontext\ndef config_update(verbose=False, delete_objects=False):\n    \"\"\"sync configuration with data from YAML-formatted stdin\"\"\"\n    import yaml\n    import sys\n    new_config = yaml.load(sys.stdin)\n    # print new_config\n    domains = new_config.get('domains', [])\n    tracked_domains = set()\n    for domain_config in domains:\n        if verbose:\n            print(str(domain_config))\n        domain_name = domain_config['name']\n        max_users = domain_config.get('max_users', -1)\n        max_aliases = domain_config.get('max_aliases', -1)\n        max_quota_bytes = domain_config.get('max_quota_bytes', 0)\n        tracked_domains.add(domain_name)\n        domain = models.Domain.query.get(domain_name)\n        if not domain:\n            domain = models.Domain(name=domain_name,\n                                   max_users=max_users,\n                                   max_aliases=max_aliases,\n                                   max_quota_bytes=max_quota_bytes)\n            db.session.add(domain)\n            print(\"Added \" + str(domain_config))\n        else:\n            domain.max_users = max_users\n            domain.max_aliases = max_aliases\n            domain.max_quota_bytes = max_quota_bytes\n            db.session.add(domain)\n            print(\"Updated \" + str(domain_config))\n\n    users = new_config.get('users', [])\n    tracked_users = set()\n    user_optional_params = ('comment', 'quota_bytes', 'global_admin',\n                            'enable_imap', 'enable_pop', 'forward_enabled',\n                            'forward_destination', 'reply_enabled',\n                            'reply_subject', 'reply_body', 'displayed_name',\n                            'spam_enabled', 'email', 'spam_threshold')\n    for user_config in users:\n        if verbose:\n            print(str(user_config))\n        localpart = user_config['localpart']\n        domain_name = user_config['domain']\n        password_hash = user_config.get('password_hash', None)\n        hash_scheme = user_config.get('hash_scheme', None)\n        domain = models.Domain.query.get(domain_name)\n        email = '{0}@{1}'.format(localpart, domain_name)\n        optional_params = {}\n        for k in user_optional_params:\n            if k in user_config:\n                optional_params[k] = user_config[k]\n        if not domain:\n            domain = models.Domain(name=domain_name)\n            db.session.add(domain)\n        user = models.User.query.get(email)\n        tracked_users.add(email)\n        tracked_domains.add(domain_name)\n        if not user:\n            user = models.User(\n                localpart=localpart,\n                domain=domain,\n                **optional_params\n            )\n        else:\n            for k in optional_params:\n                setattr(user, k, optional_params[k])\n        user.set_password(password_hash, hash_scheme=hash_scheme, raw=True)\n        db.session.add(user)\n\n    aliases = new_config.get('aliases', [])\n    tracked_aliases = set()\n    for alias_config in aliases:\n        if verbose:\n            print(str(alias_config))\n        localpart = alias_config['localpart']\n        domain_name = alias_config['domain']\n        if type(alias_config['destination']) is str:\n            destination = alias_config['destination'].split(',')\n        else:\n            destination = alias_config['destination']\n        wildcard = alias_config.get('wildcard', False)\n        domain = models.Domain.query.get(domain_name)\n        email = '{0}@{1}'.format(localpart, domain_name)\n        if not domain:\n            domain = models.Domain(name=domain_name)\n            db.session.add(domain)\n        alias = models.Alias.query.get(email)\n        tracked_aliases.add(email)\n        tracked_domains.add(domain_name)\n        if not alias:\n            alias = models.Alias(\n                localpart=localpart,\n                domain=domain,\n                wildcard=wildcard,\n                destination=destination,\n                email=email\n            )\n        else:\n            alias.destination = destination\n            alias.wildcard = wildcard\n        db.session.add(alias)\n\n    db.session.commit()\n\n    managers = new_config.get('managers', [])\n    # tracked_managers=set()\n    for manager_config in managers:\n        if verbose:\n            print(str(manager_config))\n        domain_name = manager_config['domain']\n        user_name = manager_config['user']\n        domain = models.Domain.query.get(domain_name)\n        manageruser = models.User.query.get(user_name + '@' + domain_name)\n        if manageruser not in domain.managers:\n            domain.managers.append(manageruser)\n        db.session.add(domain)\n\n    db.session.commit()\n\n    if delete_objects:\n        for user in db.session.query(models.User).all():\n            if not (user.email in tracked_users):\n                if verbose:\n                    print(\"Deleting user: \" + str(user.email))\n                db.session.delete(user)\n        for alias in db.session.query(models.Alias).all():\n            if not (alias.email in tracked_aliases):\n                if verbose:\n                    print(\"Deleting alias: \" + str(alias.email))\n                db.session.delete(alias)\n        for domain in db.session.query(models.Domain).all():\n            if not (domain.name in tracked_domains):\n                if verbose:\n                    print(\"Deleting domain: \" + str(domain.name))\n                db.session.delete(domain)\n    db.session.commit()\n\n\n@mailu.command()\n@click.argument('email')\n@flask_cli.with_appcontext\ndef user_delete(email):\n    \"\"\"delete user\"\"\"\n    user = models.User.query.get(email)\n    if user:\n        db.session.delete(user)\n    db.session.commit()\n\n\n@mailu.command()\n@click.argument('email')\n@flask_cli.with_appcontext\ndef alias_delete(email):\n    \"\"\"delete alias\"\"\"\n    alias = models.Alias.query.get(email)\n    if alias:\n        db.session.delete(alias)\n    db.session.commit()\n\n\n@mailu.command()\n@click.argument('localpart')\n@click.argument('domain_name')\n@click.argument('destination')\n@flask_cli.with_appcontext\ndef alias(localpart, domain_name, destination):\n    \"\"\" Create an alias\n    \"\"\"\n    domain = models.Domain.query.get(domain_name)\n    if not domain:\n        domain = models.Domain(name=domain_name)\n        db.session.add(domain)\n    alias = models.Alias(\n        localpart=localpart,\n        domain=domain,\n        destination=destination.split(','),\n        email=\"%s@%s\" % (localpart, domain_name)\n    )\n    db.session.add(alias)\n    db.session.commit()\n\n\n@mailu.command()\n@click.argument('domain_name')\n@click.argument('max_users')\n@click.argument('max_aliases')\n@click.argument('max_quota_bytes')\n@flask_cli.with_appcontext\ndef setlimits(domain_name, max_users, max_aliases, max_quota_bytes):\n    \"\"\" Set domain limits\n    \"\"\"\n    domain = models.Domain.query.get(domain_name)\n    domain.max_users = max_users\n    domain.max_aliases = max_aliases\n    domain.max_quota_bytes = max_quota_bytes\n    db.session.add(domain)\n    db.session.commit()\n\n\n@mailu.command()\n@click.argument('domain_name')\n@click.argument('user_name')\n@flask_cli.with_appcontext\ndef setmanager(domain_name, user_name='manager'):\n    \"\"\" Make a user manager of a domain\n    \"\"\"\n    domain = models.Domain.query.get(domain_name)\n    manageruser = models.User.query.get(user_name + '@' + domain_name)\n    domain.managers.append(manageruser)\n    db.session.add(domain)\n    db.session.commit()\n\n\nif __name__ == '__main__':\n    cli()\n", "path": "core/admin/mailu/manage.py"}], "after_files": [{"content": "from mailu import models\n\nfrom flask import current_app as app\nfrom flask import cli as flask_cli\n\nimport flask\nimport os\nimport socket\nimport uuid\nimport click\n\n\ndb = models.db\n\n\n@click.group()\ndef mailu(cls=flask_cli.FlaskGroup):\n    \"\"\" Mailu command line\n    \"\"\"\n\n\n@mailu.command()\n@flask_cli.with_appcontext\ndef advertise():\n    \"\"\" Advertise this server against statistic services.\n    \"\"\"\n    if os.path.isfile(app.config[\"INSTANCE_ID_PATH\"]):\n        with open(app.config[\"INSTANCE_ID_PATH\"], \"r\") as handle:\n            instance_id = handle.read()\n    else:\n        instance_id = str(uuid.uuid4())\n        with open(app.config[\"INSTANCE_ID_PATH\"], \"w\") as handle:\n            handle.write(instance_id)\n    if not app.config[\"DISABLE_STATISTICS\"]:\n        try:\n            socket.gethostbyname(app.config[\"STATS_ENDPOINT\"].format(instance_id))\n        except:\n            pass\n\n\n@mailu.command()\n@click.argument('localpart')\n@click.argument('domain_name')\n@click.argument('password')\n@flask_cli.with_appcontext\ndef admin(localpart, domain_name, password):\n    \"\"\" Create an admin user\n    \"\"\"\n    domain = models.Domain.query.get(domain_name)\n    if not domain:\n        domain = models.Domain(name=domain_name)\n        db.session.add(domain)\n    user = models.User(\n        localpart=localpart,\n        domain=domain,\n        global_admin=True\n    )\n    user.set_password(password)\n    db.session.add(user)\n    db.session.commit()\n\n\n@mailu.command()\n@click.argument('localpart')\n@click.argument('domain_name')\n@click.argument('password')\n@click.argument('hash_scheme')\n@flask_cli.with_appcontext\ndef user(localpart, domain_name, password, hash_scheme=None):\n    \"\"\" Create a user\n    \"\"\"\n    if hash_scheme is None:\n        hash_scheme = app.config['PASSWORD_SCHEME']\n    domain = models.Domain.query.get(domain_name)\n    if not domain:\n        domain = models.Domain(name=domain_name)\n        db.session.add(domain)\n    user = models.User(\n        localpart=localpart,\n        domain=domain,\n        global_admin=False\n    )\n    user.set_password(password, hash_scheme=hash_scheme)\n    db.session.add(user)\n    db.session.commit()\n\n\n@mailu.command()\n@click.option('-n', '--domain_name')\n@click.option('-u', '--max_users')\n@click.option('-a', '--max_aliases')\n@click.option('-q', '--max_quota_bytes')\n@flask_cli.with_appcontext\ndef domain(domain_name, max_users=-1, max_aliases=-1, max_quota_bytes=0):\n    domain = models.Domain.query.get(domain_name)\n    if not domain:\n        domain = models.Domain(name=domain_name)\n        db.session.add(domain)\n        db.session.commit()\n\n\n@mailu.command()\n@click.argument('localpart')\n@click.argument('domain_name')\n@click.argument('password_hash')\n@click.argument('hash_scheme')\n@flask_cli.with_appcontext\ndef user_import(localpart, domain_name, password_hash, hash_scheme = None):\n    \"\"\" Import a user along with password hash.\n    \"\"\"\n    if hash_scheme is None:\n        hash_scheme = app.config['PASSWORD_SCHEME']\n    domain = models.Domain.query.get(domain_name)\n    if not domain:\n        domain = models.Domain(name=domain_name)\n        db.session.add(domain)\n    user = models.User(\n        localpart=localpart,\n        domain=domain,\n        global_admin=False\n    )\n    user.set_password(password_hash, hash_scheme=hash_scheme, raw=True)\n    db.session.add(user)\n    db.session.commit()\n\n\n@mailu.command()\n@click.option('-v', '--verbose')\n@click.option('-d', '--delete_objects')\n@flask_cli.with_appcontext\ndef config_update(verbose=False, delete_objects=False):\n    \"\"\"sync configuration with data from YAML-formatted stdin\"\"\"\n    import yaml\n    import sys\n    new_config = yaml.load(sys.stdin)\n    # print new_config\n    domains = new_config.get('domains', [])\n    tracked_domains = set()\n    for domain_config in domains:\n        if verbose:\n            print(str(domain_config))\n        domain_name = domain_config['name']\n        max_users = domain_config.get('max_users', -1)\n        max_aliases = domain_config.get('max_aliases', -1)\n        max_quota_bytes = domain_config.get('max_quota_bytes', 0)\n        tracked_domains.add(domain_name)\n        domain = models.Domain.query.get(domain_name)\n        if not domain:\n            domain = models.Domain(name=domain_name,\n                                   max_users=max_users,\n                                   max_aliases=max_aliases,\n                                   max_quota_bytes=max_quota_bytes)\n            db.session.add(domain)\n            print(\"Added \" + str(domain_config))\n        else:\n            domain.max_users = max_users\n            domain.max_aliases = max_aliases\n            domain.max_quota_bytes = max_quota_bytes\n            db.session.add(domain)\n            print(\"Updated \" + str(domain_config))\n\n    users = new_config.get('users', [])\n    tracked_users = set()\n    user_optional_params = ('comment', 'quota_bytes', 'global_admin',\n                            'enable_imap', 'enable_pop', 'forward_enabled',\n                            'forward_destination', 'reply_enabled',\n                            'reply_subject', 'reply_body', 'displayed_name',\n                            'spam_enabled', 'email', 'spam_threshold')\n    for user_config in users:\n        if verbose:\n            print(str(user_config))\n        localpart = user_config['localpart']\n        domain_name = user_config['domain']\n        password_hash = user_config.get('password_hash', None)\n        hash_scheme = user_config.get('hash_scheme', None)\n        domain = models.Domain.query.get(domain_name)\n        email = '{0}@{1}'.format(localpart, domain_name)\n        optional_params = {}\n        for k in user_optional_params:\n            if k in user_config:\n                optional_params[k] = user_config[k]\n        if not domain:\n            domain = models.Domain(name=domain_name)\n            db.session.add(domain)\n        user = models.User.query.get(email)\n        tracked_users.add(email)\n        tracked_domains.add(domain_name)\n        if not user:\n            user = models.User(\n                localpart=localpart,\n                domain=domain,\n                **optional_params\n            )\n        else:\n            for k in optional_params:\n                setattr(user, k, optional_params[k])\n        user.set_password(password_hash, hash_scheme=hash_scheme, raw=True)\n        db.session.add(user)\n\n    aliases = new_config.get('aliases', [])\n    tracked_aliases = set()\n    for alias_config in aliases:\n        if verbose:\n            print(str(alias_config))\n        localpart = alias_config['localpart']\n        domain_name = alias_config['domain']\n        if type(alias_config['destination']) is str:\n            destination = alias_config['destination'].split(',')\n        else:\n            destination = alias_config['destination']\n        wildcard = alias_config.get('wildcard', False)\n        domain = models.Domain.query.get(domain_name)\n        email = '{0}@{1}'.format(localpart, domain_name)\n        if not domain:\n            domain = models.Domain(name=domain_name)\n            db.session.add(domain)\n        alias = models.Alias.query.get(email)\n        tracked_aliases.add(email)\n        tracked_domains.add(domain_name)\n        if not alias:\n            alias = models.Alias(\n                localpart=localpart,\n                domain=domain,\n                wildcard=wildcard,\n                destination=destination,\n                email=email\n            )\n        else:\n            alias.destination = destination\n            alias.wildcard = wildcard\n        db.session.add(alias)\n\n    db.session.commit()\n\n    managers = new_config.get('managers', [])\n    # tracked_managers=set()\n    for manager_config in managers:\n        if verbose:\n            print(str(manager_config))\n        domain_name = manager_config['domain']\n        user_name = manager_config['user']\n        domain = models.Domain.query.get(domain_name)\n        manageruser = models.User.query.get(user_name + '@' + domain_name)\n        if manageruser not in domain.managers:\n            domain.managers.append(manageruser)\n        db.session.add(domain)\n\n    db.session.commit()\n\n    if delete_objects:\n        for user in db.session.query(models.User).all():\n            if not (user.email in tracked_users):\n                if verbose:\n                    print(\"Deleting user: \" + str(user.email))\n                db.session.delete(user)\n        for alias in db.session.query(models.Alias).all():\n            if not (alias.email in tracked_aliases):\n                if verbose:\n                    print(\"Deleting alias: \" + str(alias.email))\n                db.session.delete(alias)\n        for domain in db.session.query(models.Domain).all():\n            if not (domain.name in tracked_domains):\n                if verbose:\n                    print(\"Deleting domain: \" + str(domain.name))\n                db.session.delete(domain)\n    db.session.commit()\n\n\n@mailu.command()\n@click.argument('email')\n@flask_cli.with_appcontext\ndef user_delete(email):\n    \"\"\"delete user\"\"\"\n    user = models.User.query.get(email)\n    if user:\n        db.session.delete(user)\n    db.session.commit()\n\n\n@mailu.command()\n@click.argument('email')\n@flask_cli.with_appcontext\ndef alias_delete(email):\n    \"\"\"delete alias\"\"\"\n    alias = models.Alias.query.get(email)\n    if alias:\n        db.session.delete(alias)\n    db.session.commit()\n\n\n@mailu.command()\n@click.argument('localpart')\n@click.argument('domain_name')\n@click.argument('destination')\n@click.option('-w', '--wildcard', is_flag=True)\n@flask_cli.with_appcontext\ndef alias(localpart, domain_name, destination, wildcard=False):\n    \"\"\" Create an alias\n    \"\"\"\n    domain = models.Domain.query.get(domain_name)\n    if not domain:\n        domain = models.Domain(name=domain_name)\n        db.session.add(domain)\n    alias = models.Alias(\n        localpart=localpart,\n        domain=domain,\n        wildcard=wildcard,\n        destination=destination.split(','),\n        email=\"%s@%s\" % (localpart, domain_name)\n    )\n    db.session.add(alias)\n    db.session.commit()\n\n\n@mailu.command()\n@click.argument('domain_name')\n@click.argument('max_users')\n@click.argument('max_aliases')\n@click.argument('max_quota_bytes')\n@flask_cli.with_appcontext\ndef setlimits(domain_name, max_users, max_aliases, max_quota_bytes):\n    \"\"\" Set domain limits\n    \"\"\"\n    domain = models.Domain.query.get(domain_name)\n    domain.max_users = max_users\n    domain.max_aliases = max_aliases\n    domain.max_quota_bytes = max_quota_bytes\n    db.session.add(domain)\n    db.session.commit()\n\n\n@mailu.command()\n@click.argument('domain_name')\n@click.argument('user_name')\n@flask_cli.with_appcontext\ndef setmanager(domain_name, user_name='manager'):\n    \"\"\" Make a user manager of a domain\n    \"\"\"\n    domain = models.Domain.query.get(domain_name)\n    manageruser = models.User.query.get(user_name + '@' + domain_name)\n    domain.managers.append(manageruser)\n    db.session.add(domain)\n    db.session.commit()\n\n\nif __name__ == '__main__':\n    cli()\n", "path": "core/admin/mailu/manage.py"}]}