SMTP_SSL SSLError: [SSL: UNKNOWN_PROTOCOL] unknown protocol (_ssl.c:590)

Muthuvel picture Muthuvel · Jun 26, 2017 · Viewed 8.2k times · Source

This issue is related to smtplib's SMTP_SSL connection.

While connection with SMTP (without ssl) it's working.

While trying the same host & port in SMTP_SSL, error raised. The error is based on host only, The gmail settings also works fine.

Please check the below example and let me know if any changes needed for outlook & office365.

In [1]: import smtplib

In [10]: smtplib.SMTP_SSL('smtp.gmail.com', 465, timeout=100)
Out[10]: <smtplib.SMTP_SSL instance at 0x109ccaf38>

In [2]: smtplib.SMTP('smtp-mail.outlook.com', 587, timeout=100)
Out[1]: <smtplib.SMTP instance at 0x10a00bb90>

In [3]: smtplib.SMTP_SSL('smtp-mail.outlook.com', 587, timeout=100)
---------------------------------------------------------------------------
SSLError                                  Traceback (most recent call last)
<ipython-input-9-f0c5b0de4e24> in <module>()
----> 1 smtplib.SMTP_SSL('smtp-mail.outlook.com', 587, timeout=100)

/python2.7/smtplib.pyc in __init__(self, host, port, local_hostname, keyfile, certfile, timeout)
    794             self.keyfile = keyfile
    795             self.certfile = certfile
--> 796             SMTP.__init__(self, host, port, local_hostname, timeout)
    797 
    798         def _get_socket(self, host, port, timeout):

python2.7/smtplib.pyc in __init__(self, host, port, local_hostname, timeout)
    254         self.esmtp_features = {}
    255         if host:
--> 256             (code, msg) = self.connect(host, port)
    257             if code != 220:
    258                 raise SMTPConnectError(code, msg)

python2.7/smtplib.pyc in connect(self, host, port)
    314         if self.debuglevel > 0:
    315             print>>stderr, 'connect:', (host, port)
--> 316         self.sock = self._get_socket(host, port, self.timeout)
    317         (code, msg) = self.getreply()
    318         if self.debuglevel > 0:

python2.7/smtplib.pyc in _get_socket(self, host, port, timeout)
    800                 print>>stderr, 'connect:', (host, port)
    801             new_socket = socket.create_connection((host, port), timeout)
--> 802             new_socket = ssl.wrap_socket(new_socket, self.keyfile, self.certfile)
    803             self.file = SSLFakeFile(new_socket)
    804             return new_socket

python2.7/ssl.pyc in wrap_socket(sock, keyfile, certfile, server_side, cert_reqs, ssl_version, ca_certs, do_handshake_on_connect, suppress_ragged_eofs, ciphers)
    909                      do_handshake_on_connect=do_handshake_on_connect,
    910                      suppress_ragged_eofs=suppress_ragged_eofs,
--> 911                      ciphers=ciphers)
    912 
    913 # some utility functions

python2.7/ssl.pyc in __init__(self, sock, keyfile, certfile, server_side, cert_reqs, ssl_version, ca_certs, do_handshake_on_connect, family, type, proto, fileno, suppress_ragged_eofs, npn_protocols, ciphers, server_hostname, _context)
    577                         # non-blocking
    578                         raise ValueError("do_handshake_on_connect should not be specified for non-blocking sockets")
--> 579                     self.do_handshake()
    580 
    581             except (OSError, ValueError):

python2.7/ssl.pyc in do_handshake(self, block)
    806             if timeout == 0.0 and block:
    807                 self.settimeout(None)
--> 808             self._sslobj.do_handshake()
    809         finally:
    810             self.settimeout(timeout)

SSLError: [SSL: UNKNOWN_PROTOCOL] unknown protocol (_ssl.c:590)

Ref URL: https://docs.python.org/2/library/smtplib.html#smtplib.SMTP_SSL

Answer

wyx picture wyx · Mar 23, 2018

I have had this the same problem today and I have solved it.

This is my demo.

def _send_email(self, msg):
    if self.smtp_port == 465:
        server = smtplib.SMTP_SSL(self.smtp_host, self.smtp_port)
    elif self.smtp_port == 587:
        server = smtplib.SMTP(self.smtp_host, self.smtp_port)
        server.starttls()
    else:
        raise Exception('port {} not support'.format(SMTP_PORT))
    server.set_debuglevel(1)
    server.login(self.from_addr, self.password)
    server.sendmail(self.from_addr, [self.to_addr], msg.as_string())
    server.quit()

In my opinion (perhaps it is wrong, just personal understanding.If sth wrong, please help me to fix it, thanks. ):

465 and 587 is for different protocol. The former use SSL and the latter use TLS.They all use SSL to encrypt our email content before SMTP communication.

But for 587. You must send STARTTLS first. If you don't do that you will get a message like this Must issue a STARTTLS command first. And for 465 you can't use tls command