We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Rainloop Webmail - Authentication fails if you have a special character in your password
In the admin interface, you can define a new password and you can put a special character like `è`.

It works fine with admin interface but it doesn't work at all with the Rainloop webmail. If you try to log in, you will have a message to indicate that the authentication fails, see screenshoot in french:

![Capture d’écran de 2019-08-25 10-57-56](https://user-images.githubusercontent.com/21110485/63647853-904b0b80-c727-11e9-9938-d66a1e10ca4e.png)


--- 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/internal/nginx.py`
Content:
```
1 from mailu import models
2 from flask import current_app as app
3 
4 import re
5 import urllib
6 import ipaddress
7 import socket
8 import tenacity
9 
10 
11 SUPPORTED_AUTH_METHODS = ["none", "plain"]
12 
13 
14 STATUSES = {
15     "authentication": ("Authentication credentials invalid", {
16         "imap": "AUTHENTICATIONFAILED",
17         "smtp": "535 5.7.8",
18         "pop3": "-ERR Authentication failed"
19     }),
20 }
21 
22 
23 def handle_authentication(headers):
24     """ Handle an HTTP nginx authentication request
25     See: http://nginx.org/en/docs/mail/ngx_mail_auth_http_module.html#protocol
26     """
27     method = headers["Auth-Method"]
28     protocol = headers["Auth-Protocol"]
29     # Incoming mail, no authentication
30     if method == "none" and protocol == "smtp":
31         server, port = get_server(headers["Auth-Protocol"], False)
32         return {
33             "Auth-Status": "OK",
34             "Auth-Server": server,
35             "Auth-Port": port
36         }
37     # Authenticated user
38     elif method == "plain":
39         server, port = get_server(headers["Auth-Protocol"], True)
40         user_email = urllib.parse.unquote(headers["Auth-User"])
41         password = urllib.parse.unquote(headers["Auth-Pass"])
42         ip = urllib.parse.unquote(headers["Client-Ip"])
43         user = models.User.query.get(user_email)
44         status = False
45         if user:
46             for token in user.tokens:
47                 if (token.check_password(password) and
48                     (not token.ip or token.ip == ip)):
49                         status = True
50             if user.check_password(password):
51                 status = True
52             if status:
53                 if protocol == "imap" and not user.enable_imap:
54                     status = False
55                 elif protocol == "pop3" and not user.enable_pop:
56                     status = False
57         if status and user.enabled:
58             return {
59                 "Auth-Status": "OK",
60                 "Auth-Server": server,
61                 "Auth-Port": port
62             }
63         else:
64             status, code = get_status(protocol, "authentication")
65             return {
66                 "Auth-Status": status,
67                 "Auth-Error-Code": code,
68                 "Auth-Wait": 0
69             }
70     # Unexpected
71     return {}
72 
73 
74 def get_status(protocol, status):
75     """ Return the proper error code depending on the protocol
76     """
77     status, codes = STATUSES[status]
78     return status, codes[protocol]
79 
80 def extract_host_port(host_and_port, default_port):
81     host, _, port = re.match('^(.*)(:([0-9]*))?$', host_and_port).groups()
82     return host, int(port) if port else default_port
83 
84 def get_server(protocol, authenticated=False):
85     if protocol == "imap":
86         hostname, port = extract_host_port(app.config['IMAP_ADDRESS'], 143)
87     elif protocol == "pop3":
88         hostname, port = extract_host_port(app.config['POP3_ADDRESS'], 110)
89     elif protocol == "smtp":
90         if authenticated:
91             hostname, port = extract_host_port(app.config['AUTHSMTP_ADDRESS'], 10025)
92         else:
93             hostname, port = extract_host_port(app.config['SMTP_ADDRESS'], 25)
94     try:
95         # test if hostname is already resolved to an ip adddress
96         ipaddress.ip_address(hostname)
97     except:
98         # hostname is not an ip address - so we need to resolve it
99         hostname = resolve_hostname(hostname)
100     return hostname, port
101 
102 @tenacity.retry(stop=tenacity.stop_after_attempt(100),
103                 wait=tenacity.wait_random(min=2, max=5))
104 def resolve_hostname(hostname):
105     """ This function uses system DNS to resolve a hostname.
106     It is capable of retrying in case the host is not immediately available
107     """
108     return socket.gethostbyname(hostname)
109
```
--- 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/internal/nginx.py b/core/admin/mailu/internal/nginx.py
--- a/core/admin/mailu/internal/nginx.py
+++ b/core/admin/mailu/internal/nginx.py
@@ -37,8 +37,14 @@
     # Authenticated user
     elif method == "plain":
         server, port = get_server(headers["Auth-Protocol"], True)
-        user_email = urllib.parse.unquote(headers["Auth-User"])
-        password = urllib.parse.unquote(headers["Auth-Pass"])
+        # According to RFC2616 section 3.7.1 and PEP 3333, HTTP headers should
+        # be ASCII and are generally considered ISO8859-1. However when passing
+        # the password, nginx does not transcode the input UTF string, thus
+        # we need to manually decode.
+        raw_user_email = urllib.parse.unquote(headers["Auth-User"])
+        user_email = raw_user_email.encode("iso8859-1").decode("utf8")
+        raw_password = urllib.parse.unquote(headers["Auth-Pass"])
+        password = raw_password.encode("iso8859-1").decode("utf8")
         ip = urllib.parse.unquote(headers["Client-Ip"])
         user = models.User.query.get(user_email)
         status = False

{"golden_diff": "diff --git a/core/admin/mailu/internal/nginx.py b/core/admin/mailu/internal/nginx.py\n--- a/core/admin/mailu/internal/nginx.py\n+++ b/core/admin/mailu/internal/nginx.py\n@@ -37,8 +37,14 @@\n     # Authenticated user\n     elif method == \"plain\":\n         server, port = get_server(headers[\"Auth-Protocol\"], True)\n-        user_email = urllib.parse.unquote(headers[\"Auth-User\"])\n-        password = urllib.parse.unquote(headers[\"Auth-Pass\"])\n+        # According to RFC2616 section 3.7.1 and PEP 3333, HTTP headers should\n+        # be ASCII and are generally considered ISO8859-1. However when passing\n+        # the password, nginx does not transcode the input UTF string, thus\n+        # we need to manually decode.\n+        raw_user_email = urllib.parse.unquote(headers[\"Auth-User\"])\n+        user_email = raw_user_email.encode(\"iso8859-1\").decode(\"utf8\")\n+        raw_password = urllib.parse.unquote(headers[\"Auth-Pass\"])\n+        password = raw_password.encode(\"iso8859-1\").decode(\"utf8\")\n         ip = urllib.parse.unquote(headers[\"Client-Ip\"])\n         user = models.User.query.get(user_email)\n         status = False\n", "issue": "Rainloop Webmail - Authentication fails if you have a special character in your password\nIn the admin interface, you can define a new password and you can put a special character like `\u00e8`.\r\n\r\nIt works fine with admin interface but it doesn't work at all with the Rainloop webmail. If you try to log in, you will have a message to indicate that the authentication fails, see screenshoot in french:\r\n\r\n![Capture d\u2019\u00e9cran de 2019-08-25 10-57-56](https://user-images.githubusercontent.com/21110485/63647853-904b0b80-c727-11e9-9938-d66a1e10ca4e.png)\r\n\n", "before_files": [{"content": "from mailu import models\nfrom flask import current_app as app\n\nimport re\nimport urllib\nimport ipaddress\nimport socket\nimport tenacity\n\n\nSUPPORTED_AUTH_METHODS = [\"none\", \"plain\"]\n\n\nSTATUSES = {\n    \"authentication\": (\"Authentication credentials invalid\", {\n        \"imap\": \"AUTHENTICATIONFAILED\",\n        \"smtp\": \"535 5.7.8\",\n        \"pop3\": \"-ERR Authentication failed\"\n    }),\n}\n\n\ndef handle_authentication(headers):\n    \"\"\" Handle an HTTP nginx authentication request\n    See: http://nginx.org/en/docs/mail/ngx_mail_auth_http_module.html#protocol\n    \"\"\"\n    method = headers[\"Auth-Method\"]\n    protocol = headers[\"Auth-Protocol\"]\n    # Incoming mail, no authentication\n    if method == \"none\" and protocol == \"smtp\":\n        server, port = get_server(headers[\"Auth-Protocol\"], False)\n        return {\n            \"Auth-Status\": \"OK\",\n            \"Auth-Server\": server,\n            \"Auth-Port\": port\n        }\n    # Authenticated user\n    elif method == \"plain\":\n        server, port = get_server(headers[\"Auth-Protocol\"], True)\n        user_email = urllib.parse.unquote(headers[\"Auth-User\"])\n        password = urllib.parse.unquote(headers[\"Auth-Pass\"])\n        ip = urllib.parse.unquote(headers[\"Client-Ip\"])\n        user = models.User.query.get(user_email)\n        status = False\n        if user:\n            for token in user.tokens:\n                if (token.check_password(password) and\n                    (not token.ip or token.ip == ip)):\n                        status = True\n            if user.check_password(password):\n                status = True\n            if status:\n                if protocol == \"imap\" and not user.enable_imap:\n                    status = False\n                elif protocol == \"pop3\" and not user.enable_pop:\n                    status = False\n        if status and user.enabled:\n            return {\n                \"Auth-Status\": \"OK\",\n                \"Auth-Server\": server,\n                \"Auth-Port\": port\n            }\n        else:\n            status, code = get_status(protocol, \"authentication\")\n            return {\n                \"Auth-Status\": status,\n                \"Auth-Error-Code\": code,\n                \"Auth-Wait\": 0\n            }\n    # Unexpected\n    return {}\n\n\ndef get_status(protocol, status):\n    \"\"\" Return the proper error code depending on the protocol\n    \"\"\"\n    status, codes = STATUSES[status]\n    return status, codes[protocol]\n\ndef extract_host_port(host_and_port, default_port):\n    host, _, port = re.match('^(.*)(:([0-9]*))?$', host_and_port).groups()\n    return host, int(port) if port else default_port\n\ndef get_server(protocol, authenticated=False):\n    if protocol == \"imap\":\n        hostname, port = extract_host_port(app.config['IMAP_ADDRESS'], 143)\n    elif protocol == \"pop3\":\n        hostname, port = extract_host_port(app.config['POP3_ADDRESS'], 110)\n    elif protocol == \"smtp\":\n        if authenticated:\n            hostname, port = extract_host_port(app.config['AUTHSMTP_ADDRESS'], 10025)\n        else:\n            hostname, port = extract_host_port(app.config['SMTP_ADDRESS'], 25)\n    try:\n        # test if hostname is already resolved to an ip adddress\n        ipaddress.ip_address(hostname)\n    except:\n        # hostname is not an ip address - so we need to resolve it\n        hostname = resolve_hostname(hostname)\n    return hostname, port\n\n@tenacity.retry(stop=tenacity.stop_after_attempt(100),\n                wait=tenacity.wait_random(min=2, max=5))\ndef resolve_hostname(hostname):\n    \"\"\" This function uses system DNS to resolve a hostname.\n    It is capable of retrying in case the host is not immediately available\n    \"\"\"\n    return socket.gethostbyname(hostname)\n", "path": "core/admin/mailu/internal/nginx.py"}], "after_files": [{"content": "from mailu import models\nfrom flask import current_app as app\n\nimport re\nimport urllib\nimport ipaddress\nimport socket\nimport tenacity\n\n\nSUPPORTED_AUTH_METHODS = [\"none\", \"plain\"]\n\n\nSTATUSES = {\n    \"authentication\": (\"Authentication credentials invalid\", {\n        \"imap\": \"AUTHENTICATIONFAILED\",\n        \"smtp\": \"535 5.7.8\",\n        \"pop3\": \"-ERR Authentication failed\"\n    }),\n}\n\n\ndef handle_authentication(headers):\n    \"\"\" Handle an HTTP nginx authentication request\n    See: http://nginx.org/en/docs/mail/ngx_mail_auth_http_module.html#protocol\n    \"\"\"\n    method = headers[\"Auth-Method\"]\n    protocol = headers[\"Auth-Protocol\"]\n    # Incoming mail, no authentication\n    if method == \"none\" and protocol == \"smtp\":\n        server, port = get_server(headers[\"Auth-Protocol\"], False)\n        return {\n            \"Auth-Status\": \"OK\",\n            \"Auth-Server\": server,\n            \"Auth-Port\": port\n        }\n    # Authenticated user\n    elif method == \"plain\":\n        server, port = get_server(headers[\"Auth-Protocol\"], True)\n        # According to RFC2616 section 3.7.1 and PEP 3333, HTTP headers should\n        # be ASCII and are generally considered ISO8859-1. However when passing\n        # the password, nginx does not transcode the input UTF string, thus\n        # we need to manually decode.\n        raw_user_email = urllib.parse.unquote(headers[\"Auth-User\"])\n        user_email = raw_user_email.encode(\"iso8859-1\").decode(\"utf8\")\n        raw_password = urllib.parse.unquote(headers[\"Auth-Pass\"])\n        password = raw_password.encode(\"iso8859-1\").decode(\"utf8\")\n        ip = urllib.parse.unquote(headers[\"Client-Ip\"])\n        user = models.User.query.get(user_email)\n        status = False\n        if user:\n            for token in user.tokens:\n                if (token.check_password(password) and\n                    (not token.ip or token.ip == ip)):\n                        status = True\n            if user.check_password(password):\n                status = True\n            if status:\n                if protocol == \"imap\" and not user.enable_imap:\n                    status = False\n                elif protocol == \"pop3\" and not user.enable_pop:\n                    status = False\n        if status and user.enabled:\n            return {\n                \"Auth-Status\": \"OK\",\n                \"Auth-Server\": server,\n                \"Auth-Port\": port\n            }\n        else:\n            status, code = get_status(protocol, \"authentication\")\n            return {\n                \"Auth-Status\": status,\n                \"Auth-Error-Code\": code,\n                \"Auth-Wait\": 0\n            }\n    # Unexpected\n    return {}\n\n\ndef get_status(protocol, status):\n    \"\"\" Return the proper error code depending on the protocol\n    \"\"\"\n    status, codes = STATUSES[status]\n    return status, codes[protocol]\n\ndef extract_host_port(host_and_port, default_port):\n    host, _, port = re.match('^(.*)(:([0-9]*))?$', host_and_port).groups()\n    return host, int(port) if port else default_port\n\ndef get_server(protocol, authenticated=False):\n    if protocol == \"imap\":\n        hostname, port = extract_host_port(app.config['IMAP_ADDRESS'], 143)\n    elif protocol == \"pop3\":\n        hostname, port = extract_host_port(app.config['POP3_ADDRESS'], 110)\n    elif protocol == \"smtp\":\n        if authenticated:\n            hostname, port = extract_host_port(app.config['AUTHSMTP_ADDRESS'], 10025)\n        else:\n            hostname, port = extract_host_port(app.config['SMTP_ADDRESS'], 25)\n    try:\n        # test if hostname is already resolved to an ip adddress\n        ipaddress.ip_address(hostname)\n    except:\n        # hostname is not an ip address - so we need to resolve it\n        hostname = resolve_hostname(hostname)\n    return hostname, port\n\n@tenacity.retry(stop=tenacity.stop_after_attempt(100),\n                wait=tenacity.wait_random(min=2, max=5))\ndef resolve_hostname(hostname):\n    \"\"\" This function uses system DNS to resolve a hostname.\n    It is capable of retrying in case the host is not immediately available\n    \"\"\"\n    return socket.gethostbyname(hostname)\n", "path": "core/admin/mailu/internal/nginx.py"}]}