prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <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)
  
  
  </issue>
  <code>
  [start of core/admin/mailu/internal/nginx.py]
  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 of core/admin/mailu/internal/nginx.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: 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
  
verification_info: {"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"}]}