mjs / imapclient

An easy-to-use, Pythonic and complete IMAP client library
https://imapclient.readthedocs.io/
Other
519 stars 85 forks source link

[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: Hostname mismatch, certificate is not valid for ‘***.com’. (_ssl.c:1108) #470

Closed oscaroteromar closed 2 years ago

oscaroteromar commented 2 years ago

This is happening on Docker alpine:3.11 (both running on MacOS Catalina 10.15.5, and on Ubuntu 20.04). When running the following code, just trying to instantiate the client, an exception raises (can’t reveal the server name for business purposes):

Code:

import imapclient as ic
import ssl
kwargs = {'port': 993, 'use_uid': True, 'ssl': True, 'timeout': ic.SocketTimeout(connect=15, read=60)}
c = ic.IMAPClient('***.com', **kwargs)

Output:

>>> c = ic.IMAPClient('***.com', **kwargs)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/.../.local/share/virtualenvs/myenv-dHcvPec6/lib/python3.8/site-packages/imapclient/imapclient.py", line 284, in __init__
    self._imap = self._create_IMAP4()
  File "/Users/.../.local/share/virtualenvs/myenv-dHcvPec6/lib/python3.8/site-packages/imapclient/imapclient.py", line 321, in _create_IMAP4
    return tls.IMAP4_TLS(
  File "/Users/.../.local/share/virtualenvs/myenv-dHcvPec6/lib/python3.8/site-packages/imapclient/tls.py", line 44, in __init__
    imaplib.IMAP4.__init__(self, host, port)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/imaplib.py", line 198, in __init__
    self.open(host, port)
  File "/Users/.../.local/share/virtualenvs/myenv-dHcvPec6/lib/python3.8/site-packages/imapclient/tls.py", line 52, in open
    self.sock = wrap_socket(sock, self.ssl_context, host)
  File "/Users/.../.local/share/virtualenvs/myenv-dHcvPec6/lib/python3.8/site-packages/imapclient/tls.py", line 32, in wrap_socket
    return ssl_context.wrap_socket(sock, server_hostname=host)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/ssl.py", line 500, in wrap_socket
    return self.sslsocket_class._create(
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/ssl.py", line 1040, in _create
    self.do_handshake()
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/ssl.py", line 1309, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: Hostname mismatch, certificate is not valid for '***.com'. (_ssl.c:1108)

However,

After some research… I have discovered that creating the object with a custom SSLContext solves the problem:

import imapclient as ic
import ssl
kwargs = {'port': 993, 'use_uid': True, 'ssl': True, 'timeout': ic.SocketTimeout(connect=15, read=60)}
ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
c = ic.IMAPClient('***.com', ssl_context=ctx, **kwargs)

This might be because the SSLContext that uses imapclient by default has an attribute context.check_hostname = True which seems to be the one causing the exception. I wouldn’t like to unset that, it looks safer to keep it that way and the checking should work anyways.

Any hint?

Thank you

NicolasLM commented 2 years ago

Hi, it's a bit hard to tell with the *** but it looks like you are trying to connect to foo.com and the server provides a certificate for bar.com. In which case the failure is expected because it is protecting you from a server pretending to be foo.com. I am pretty sure the IMAP server you are connecting to is not configured properly. You haven't mentioned if you tried to connect using another client, like an email client, I would start with that.

Disabling hostname checking or using SSL 2.3 is very insecure and you shouldn't have to do that to connect to an IMAP server in 2022.