smtplib.SMTP starttls因tlsv1警报解码错误而失败

Bur*_*dar 5 ssl openssl smtp smtplib python-3.4

我今天遇到了以下特有的行为.

以下代码适用于Python 3.3:

smtp = smtplib.SMTP()
smtp.connect(host="smtp.gmail.com", port=587)
smtp.ehlo()
smtp.starttls()
Run Code Online (Sandbox Code Playgroud)

在Pyhton 3.4中,上面的代码不起作用,而是遇到以下错误:

   File "smtp_test.py", line 10, in <module>
    smtp.starttls()
   File "/usr/lib/python3.4/smtplib.py", line 676, in starttls
    server_hostname=server_hostname)
   File "/usr/lib/python3.4/ssl.py", line 344, in wrap_socket
    _context=self)
   File "/usr/lib/python3.4/ssl.py", line 540, in __init__
    self.do_handshake()
   File "/usr/lib/python3.4/ssl.py", line 767, in do_handshake
    self._sslobj.do_handshake()
   ssl.SSLError: [SSL: TLSV1_ALERT_DECODE_ERROR] tlsv1 alert decode error (_ssl.c:598)
Run Code Online (Sandbox Code Playgroud)

如果上面的代码被修改为在构造函数中指定主机和端口而不使用connect方法,如下面的代码所示,那么它可以工作.

smtp = smtplib.SMTP(host="smtp.gmail.com", port=587)
smtp.ehlo()
smtp.starttls()
Run Code Online (Sandbox Code Playgroud)

OpenSSL版本1.0.1f和OpenSSL 1.0.1g发生上述行为

有人可以向我解释这种行为吗?

Ste*_*ich 4

根据 tcpdump,3.4 中的代码发送带有空目标名称的 SNI 扩展。当同一 IP 地址后面有不同的证书时,使用 SNI(服务器名称指示)。我认为这是一个错误:如果它没有名称,则不应发送 SNI 扩展名,而应发送其中包含零长度名称的扩展名。