Repository: Mailu/Mailu

Issue:
[SUGG] Little verification in Mailu setup
Hi thanks for Mailu it is a good project.
I submit this suggestion because i made the error and take many time to find it.
In step 4 of Mailu Setup for Docker compose : 
**Subnet of the docker network** it could be nice to verify if the last octet of the IP4 address is equal to 0 because if it is not the SMTP wont work.

![mailu](https://user-images.githubusercontent.com/11191723/83033266-302b2200-a037-11ea-9774-ffc326700811.jpg)

Regards 



Discussion:
I agree, just simple bitand should work to check if IP is valid for CIDR
Hi There,

The `Mailu`-Project is currently in a bit of a bind! We are short on man-power, and we need to judge if it is possible for us to put in some work on this issue.

To help with that, we are currently trying to find out which issues are actively keeping users from using `Mailu`, which issues have someone who want to work on them — and which issues may be less important. These a less important ones could be discarded for the time being, until the project is in a more stable and regular state once again.

In order for us to better assess this, it would be helpful if you could put a **reaction on this post** (use the :smiley: icon to the top-right).
- 👍️ if you **need this** to be able to use Mailu. Ideally, you’d also be able to test this on your installation, and provide feedback …
- 🎉 if you find it a **nice bonus**, but no deal-breaker
- 🚀 if you want to **work on it yourself**!
We want to keep this **voting open for 2 weeks** from now, so please help out!
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

An easy dirty fix could be to add this explicitly to the setup website. Warning the user that the last octet must be 0

Resolving patch:
diff --git a/setup/server.py b/setup/server.py
--- a/setup/server.py
+++ b/setup/server.py
@@ -10,12 +10,16 @@
 import ipaddress
 import hashlib
 import time
-
+import secrets
+from flask_bootstrap import StaticCDN
 
 version = os.getenv("this_version", "master")
 static_url_path = "/" + version + "/static"
 app = flask.Flask(__name__, static_url_path=static_url_path)
+app.secret_key = secrets.token_hex(16)
 flask_bootstrap.Bootstrap(app)
+# Load our jQuery. Do not use jQuery 1.
+app.extensions['bootstrap']['cdns']['jquery'] = StaticCDN()
 db = redis.StrictRedis(host='redis', port=6379, db=0)
 
 
@@ -90,12 +94,47 @@ def wizard():
     def submit():
         data = flask.request.form.copy()
         data['uid'] = str(uuid.uuid4())
+        valid = True
+        try:
+            ipaddress.IPv4Address(data['bind4'])
+        except:
+            flask.flash('Configured IPv4 address is invalid', 'error')
+            valid = False
+        try:
+            ipaddress.IPv6Address(data['bind6'])
+        except:
+            flask.flash('Configured IPv6 address is invalid', 'error')
+            valid = False
+        try:
+            ipaddress.IPv4Network(data['subnet'])
+        except:
+            flask.flash('Configured subnet(IPv4) is invalid', 'error')
+            valid = False
+        try:
+            ipaddress.IPv6Network(data['subnet6'])
+        except:
+            flask.flash('Configured subnet(IPv6) is invalid', 'error')
+            valid = False
         try:
             data['dns'] = str(ipaddress.IPv4Network(data['subnet'], strict=False)[-2])
         except ValueError as err:
-            return "Error while generating files: " + str(err)
-        db.set(data['uid'], json.dumps(data))
-        return flask.redirect(flask.url_for('.setup', uid=data['uid']))
+            flask.flash('Invalid configuration: ' + str(err))
+            valid = False
+        if 'api_enabled' in data:
+            if (data['api_enabled'] == 'true'):
+                if  data['api_token'] == '':
+                    flask.flash('API token cannot be empty when API is enabled', 'error')
+                    valid = False
+        if valid:
+            db.set(data['uid'], json.dumps(data))
+            return flask.redirect(flask.url_for('.setup', uid=data['uid']))
+        else:
+            return flask.render_template(
+                'wizard.html',
+                flavor="compose",
+                steps=sorted(os.listdir(os.path.join(path, "templates", "steps", "compose"))),
+                subnet6=random_ipv6_subnet()
+            )
 
     @prefix_bp.route("/setup/<uid>", methods=["GET"])
     @root_bp.route("/setup/<uid>", methods=["GET"])


Test patch: