Python 的新版本在 imaplib 上挂起。IMAP4_SSL()

New versions of Python hangs on imaplib.IMAP4_SSL()

我有一个应用程序可以从 home.pl 上的客户端 IMAP4 邮箱导入电子邮件(我认为它在波兰很受欢迎)。它在 Python 2.7.9 之前运行良好,但在 2.7.10 版本中它挂在 imaplib.IMAP4_SSL().

中的 read() 上

在我的 Fedora 23 上,我有 Python 3.4.3 和 2.7.10。

使用 Python 3.4.3 这样的代码按预期工作:

[mn] python3 -c "import imaplib; x=imaplib.IMAP4_SSL('imap.home.pl', 993); print('finish', x)"
finish <imaplib.IMAP4_SSL object at 0x7f80cfd31710>

但是在 Python 2.7.10 中它挂起。几秒钟后我按下了 Ctrl-C:

[mn] python -c "import imaplib; x=imaplib.IMAP4_SSL('imap.home.pl', 993); print('finish', x)"
^CTraceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/lib64/python2.7/imaplib.py", line 1166, in __init__
    IMAP4.__init__(self, host, port)
  File "/usr/lib64/python2.7/imaplib.py", line 202, in __init__
    typ, dat = self.capability()
  File "/usr/lib64/python2.7/imaplib.py", line 374, in capability
    typ, dat = self._simple_command(name)
  File "/usr/lib64/python2.7/imaplib.py", line 1088, in _simple_command
    return self._command_complete(name, self._command(name, *args))
  File "/usr/lib64/python2.7/imaplib.py", line 910, in _command_complete
    typ, data = self._get_tagged_response(tag)
  File "/usr/lib64/python2.7/imaplib.py", line 1017, in _get_tagged_response
    self._get_response()
  File "/usr/lib64/python2.7/imaplib.py", line 929, in _get_response
    resp = self._get_line()
  File "/usr/lib64/python2.7/imaplib.py", line 1027, in _get_line
    line = self.readline()
  File "/usr/lib64/python2.7/imaplib.py", line 1189, in readline
    return self.file.readline()
  File "/usr/lib64/python2.7/socket.py", line 451, in readline
    data = self._sock.recv(self._rbufsize)
  File "/usr/lib64/python2.7/ssl.py", line 734, in recv
    return self.read(buflen)
  File "/usr/lib64/python2.7/ssl.py", line 621, in read
    v = self._sslobj.read(len or 1024)
KeyboardInterrupt

您还可以使用 docker 对其进行测试,以查看它是否适用于旧版本的 Python:

[mn] sudo docker run --rm -it python:2.7.9 python -c "import imaplib; x=imaplib.IMAP4_SSL('imap.home.pl', 993); print('finish', x)"
('finish', <imaplib.IMAP4_SSL instance at 0x7f682422b2d8>)

[mn] sudo docker run --rm -it python:2.7.10 python -c "import imaplib; x=imaplib.IMAP4_SSL('imap.home.pl', 993); print('finish', x)"
^CTraceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/local/lib/python2.7/imaplib.py", line 1166, in __init__
    IMAP4.__init__(self, host, port)
  File "/usr/local/lib/python2.7/imaplib.py", line 202, in __init__
    typ, dat = self.capability()
  File "/usr/local/lib/python2.7/imaplib.py", line 374, in capability
    typ, dat = self._simple_command(name)
  File "/usr/local/lib/python2.7/imaplib.py", line 1088, in _simple_command
    return self._command_complete(name, self._command(name, *args))
  File "/usr/local/lib/python2.7/imaplib.py", line 910, in _command_complete
    typ, data = self._get_tagged_response(tag)
  File "/usr/local/lib/python2.7/imaplib.py", line 1017, in _get_tagged_response
    self._get_response()
  File "/usr/local/lib/python2.7/imaplib.py", line 929, in _get_response
    resp = self._get_line()
  File "/usr/local/lib/python2.7/imaplib.py", line 1027, in _get_line
    line = self.readline()
  File "/usr/local/lib/python2.7/imaplib.py", line 1189, in readline
    return self.file.readline()
  File "/usr/local/lib/python2.7/socket.py", line 451, in readline
    data = self._sock.recv(self._rbufsize)
  File "/usr/local/lib/python2.7/ssl.py", line 734, in recv
    return self.read(buflen)
  File "/usr/local/lib/python2.7/ssl.py", line 621, in read
    v = self._sslobj.read(len or 1024)
KeyboardInterrupt

我测试它挂起的方式与 Python 3.4.4.

相同

我认为这是一个错误,因为它挂起而不是引发带有有用信息的异常,所以我报告了它:http://bugs.python.org/issue26375

我该如何解决这个问题?

这是一个服务器问题,它没有响应 CAPABILITY 命令(为清楚起见添加了 < 和 >):

$ socat readline openssl:imap.home.pl:993,crlf,verify=0 
< * OK imap.home.pl IdeaImapServer v0.80 ready
> tag CAPABILITY

它在那里放了很长时间。服务器可能有问题。

奇怪的是,背靠背发送两个命令会踢它:

< a CAPABILITY
< b CAPABILITY
> * CAPABILITY IMAP4rev1 LITERAL+ CHILDREN I18NLEVEL=1 IDLE SORT UIDPLUS UNSELECT WITHIN XLIST AUTH=PLAIN AUTH=LOGIN
> a OK Completed
> * CAPABILITY IMAP4rev1 LITERAL+ CHILDREN I18NLEVEL=1 IDLE SORT UIDPLUS UNSELECT WITHIN XLIST AUTH=PLAIN AUTH=LOGIN
> b OK Completed

服务器存在严重的解析错误。